Browse Source

QMK port of Hasu's fc980c alt controller (#2043)

* fc980c port, builds but yet untested.

* add my own keymap
Balz Guenat 7 years ago
parent
commit
2f5bb2506a

+ 84 - 0
keyboards/fc980c/config.h

@@ -0,0 +1,84 @@
+/*
+Copyright 2017 Balz Guenat
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID       0xFEED
+#define PRODUCT_ID      0x980C
+#define DEVICE_VER      0x0100
+#define MANUFACTURER    QMK
+#define PRODUCT         Leopold FC980C with QMK
+#define DESCRIPTION     Leopold FC980C with Hasu alternative controller using QMK
+
+/* key matrix size */
+#define MATRIX_ROWS 8
+#define MATRIX_COLS 16
+
+// #define MATRIX_ROW_PINS { B0, B2, B4, B5, B6 }
+// #define MATRIX_COL_PINS { F5, B1, F0, F1, F4, B3, D7, D6, D4, D5, D3, D2, D1, D0 }
+// #define UNUSED_PINS
+
+#define DIODE_DIRECTION CUSTOM_MATRIX
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* number of backlight levels */
+// #define BACKLIGHT_LEVELS  1
+
+/* mapping backlight LEDs to correct Pin */
+// #define BACKLIGHT_PIN B7
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCING_DELAY  0
+#define TAPPING_TERM      175
+
+/* 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)) \
+)
+
+
+
+/*
+ * Feature disable options
+ *  These options are also useful to firmware size reduction.
+ */
+
+/* disable debug print */
+//#define NO_DEBUG
+
+/* disable print */
+//#define NO_PRINT
+
+/* disable action features */
+//#define NO_ACTION_LAYER
+//#define NO_ACTION_TAPPING
+//#define NO_ACTION_ONESHOT
+//#define NO_ACTION_MACRO
+//#define NO_ACTION_FUNCTION
+
+#endif

+ 58 - 0
keyboards/fc980c/fc980c.c

@@ -0,0 +1,58 @@
+/*
+Copyright 2017 Balz Guenat
+
+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 <http://www.gnu.org/licenses/>.
+*/
+#include "fc980c.h"
+
+void matrix_init_kb(void) {
+	// put your keyboard start-up code here
+	// runs once when the firmware starts up
+
+	matrix_init_user();
+}
+
+void matrix_scan_kb(void) {
+	// put your looping keyboard code here
+	// runs every cycle (a lot)
+
+	matrix_scan_user();
+}
+
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+	// put your per-action keyboard code here
+	// runs for every action, just before processing by the firmware
+
+	return process_record_user(keycode, record);
+}
+
+void led_set_kb(uint8_t usb_led) {
+    if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+        PORTB |=  (1<<4);
+    } else {
+        PORTB &= ~(1<<4);
+    }
+    if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+        PORTB |=  (1<<5);
+    } else {
+        PORTB &= ~(1<<5);
+    }
+    if (usb_led & (1<<USB_LED_SCROLL_LOCK)) {
+        PORTB |=  (1<<6);
+    } else {
+        PORTB &= ~(1<<6);
+    }
+
+	led_set_user(usb_led);
+}

+ 76 - 0
keyboards/fc980c/fc980c.h

@@ -0,0 +1,76 @@
+/*
+Copyright 2017 Balz Guenat
+
+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 <http://www.gnu.org/licenses/>.
+*/
+#ifndef FC980C_H
+#define FC980C_H
+
+#include "quantum.h"
+// #include "quantum_keycodes.h"
+
+/*
+----------------------------------------------------------------------------------------------------------------------
+| K0D |     | K2D | K5D | K3D | K6D |  | K7D | K7F | K7E | K7C |  | K72 | K71 | K70 | K73 |  | K74 | K76 | K77 | K75 |
+----------------------------------------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------------------------
+| K0A | K69 | K59 | K58 | K5B | K6F | K5F | K5E | K6C | K5C | K52 | K51 | K50 |    K55    |  | K54 | K56 | K57 | K65 |
+----------------------------------------------------------------------------------------------------------------------
+|  K6A   | K39 | K68 | K6B | K3B | K3F | K6E | K3E | K3C | K62 | K61 | K60 | K33 |  K53   |  | K64 | K66 | K67 |     |
+---------------------------------------------------------------------------------------------------------------| K25 |
+|   K3A   | K29 | K38 | K28 | K2B | K2F | K2E | K2C | K1C | K32 | K31 | K20 |     K63     |  | K24 | K26 | K27 |     |
+----------------------------------------------------------------------------------------------------------------------
+|     K2A    | K18 | K08 | K1B | K0B | K1F | K1E | K0E | K22 | K11 | K21 |    K30    || K34 || K14 | K16 | K17 |     |
+---------------------------------------------------------------------------------------------------------------| K15 |
+| K1A  | K09 | K19  |                   K0F                | K02  | K01 | K10  || K00 | K04 | K06 || K07 | K05 |     |
+----------------------------------------------------------------------------------------------------------------------
+*/
+
+#define KEYMAP(                                                                           \
+    K0D,    K2D,K5D,K3D,K6D,K7D,K7F,K7E,K7C,K72,K71,K70,K73,             K74,K76,K77,K75, \
+    K0A,K69,K59,K58,K5B,K6F,K5F,K5E,K6C,K5C,K52,K51,K50,K55,             K54,K56,K57,K65, \
+    K6A,K39,K68,K6B,K3B,K3F,K6E,K3E,K3C,K62,K61,K60,K33,K53,             K64,K66,K67,K25, \
+    K3A,K29,K38,K28,K2B,K2F,K2E,K2C,K1C,K32,K31,K20,    K63,             K24,K26,K27,     \
+    K2A,    K18,K08,K1B,K0B,K1F,K1E,K0E,K22,K11,K21,    K30,     K34,    K14,K16,K17,K15, \
+    K1A,K09,K19,            K0F,                K02,K01,K10, K00,K04,K06,    K07,K05      \
+) {                                                                                       \
+    { K00,  K01,  K02,  KC_NO,K04,  K05,  K06,  K07   ,  \
+      K08,  K09,  K0A,  K0B,  KC_NO,K0D,  K0E,  K0F   }, \
+    { K10,  K11,  KC_NO,KC_NO,K14,  K15,  K16,  K17   ,  \
+      K18,  K19,  K1A,  K1B,  K1C,  KC_NO,K1E,  K1F   }, \
+    { K20,  K21,  K22,  KC_NO,K24,  K25,  K26,  K27   ,  \
+      K28,  K29,  K2A,  K2B,  K2C,  K2D,  K2E,  K2F   }, \
+    { K30,  K31,  K32,  K33,  K34,  KC_NO,KC_NO,KC_NO ,  \
+      K38,  K39,  K3A,  K3B,  K3C,  K3D,  K3E,  K3F   }, \
+    { KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO ,  \
+      KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO,KC_NO }, \
+    { K50,  K51,  K52,  K53,  K54,  K55,  K56,  K57   ,  \
+      K58,  K59,  KC_NO,K5B,  K5C,  K5D,  K5E,  K5F   }, \
+    { K60,  K61,  K62,  K63,  K64,  K65,  K66,  K67   ,  \
+      K68,  K69,  K6A,  K6B,  K6C,  K6D,  K6E,  K6F   }, \
+    { K70,  K71,  K72,  K73,  K74,  K75,  K76,  K77   ,  \
+      KC_NO,KC_NO,KC_NO,KC_NO,K7C,  K7D,  K7E,  K7F   }  \
+}
+/*
+KEYMAP(
+    _______,        _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,                         _______,_______,_______,_______,
+    _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,                         _______,_______,_______,_______,
+    _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,                         _______,_______,_______,_______,
+    _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,        _______,                         _______,_______,_______,    
+    _______,        _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,        _______,         _______,        _______,_______,_______,_______,
+    _______,_______,_______,                           _______,                             _______,_______,_______, _______,_______,_______,        _______,_______     
+)
+*/
+
+#endif

+ 1 - 0
keyboards/fc980c/keymaps/coloneljesus/README.md

@@ -0,0 +1 @@
+# My FC980C keymap

+ 24 - 0
keyboards/fc980c/keymaps/coloneljesus/config.h

@@ -0,0 +1,24 @@
+/* Copyright 2017 Balz Guenat
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "config_common.h"
+
+// place overrides here
+
+#endif

+ 39 - 0
keyboards/fc980c/keymaps/coloneljesus/keymap.c

@@ -0,0 +1,39 @@
+/*
+Copyright 2017 Balz Guenat
+
+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 <http://www.gnu.org/licenses/>.
+*/
+#include "fc980c.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+  [0] = KEYMAP(
+    KC_ESC,      KC_F1,KC_F2,KC_F3,KC_F4,KC_F5,KC_F6,KC_F7,KC_F8,  KC_F9,  KC_F10, KC_F11, KC_F12,                          KC_DEL, KC_INS, KC_PGUP,KC_PGDN,
+    KC_GRV, KC_1,KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9,   KC_0,   KC_MINS,KC_EQL, KC_BSPC,                         KC_NLCK,KC_PSLS,KC_PAST,KC_PMNS,
+    KC_TAB, KC_Q,KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,   KC_P,   KC_LBRC,KC_RBRC,KC_BSLS,                         KC_P7,  KC_P8,  KC_P9,  KC_PPLS,
+    MO(1) , KC_A,KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L,   KC_SCLN,KC_QUOT,        KC_ENT,                          KC_P4,  KC_P5,  KC_P6,
+    KC_LSFT,     KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,        KC_RSFT,         KC_UP,          KC_P1,  KC_P2,  KC_P3,  KC_PENT,
+    KC_LCTL,KC_LGUI,KC_LALT,                     KC_SPC,                   KC_RALT,KC_RCTL,MO(1),   KC_LEFT,KC_DOWN,KC_RGHT,        KC_P0,  KC_PDOT
+    ),
+  [1] = KEYMAP(
+    _______,        _______,_______,_______,_______,_______,_______,      _______,      _______,_______,_______,_______,_______,                        _______,_______,KC_HOME,KC_END,
+    _______,_______,_______,_______,_______,_______,_______,_______,      _______,      _______,_______,_______,_______,_______,                        _______,_______,_______,_______,
+    KC_CAPS,KC_MPRV,KC_VOLU,KC_MNXT,KC_PGUP,KC_INS,KC_HOME, LCTL(KC_LEFT),LCTL(KC_RGHT),KC_END, KC_PSCR,KC_SLCK,KC_PAUS,_______,                        _______,_______,_______,_______,
+    _______,KC_MUTE,KC_VOLD,KC_MPLY,KC_PGDN,KC_DEL,KC_LEFT, KC_DOWN,      KC_UP,        KC_RGHT,_______,_______,        _______,                        _______,_______,_______,
+    _______,        _______,_______,_______,_______,_______,LCTL(KC_BSPC),LCTL(KC_DEL), _______,_______,_______,        _______,         KC_PGUP,       _______,_______,_______,_______,
+    _______,_______,_______,                           _______,                                         _______,KC_APP, _______, KC_HOME,KC_PGDN,KC_END,        _______,_______     
+    ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};

+ 5 - 0
keyboards/fc980c/keymaps/default/README.md

@@ -0,0 +1,5 @@
+# The default keymap for the FC980C
+
+Emulates original keymap.
+
+![](https://i.imgur.com/bQBXPkY.jpg)

+ 24 - 0
keyboards/fc980c/keymaps/default/config.h

@@ -0,0 +1,24 @@
+/* Copyright 2017 Balz Guenat
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CONFIG_USER_H
+#define CONFIG_USER_H
+
+#include "config_common.h"
+
+// place overrides here
+
+#endif

+ 39 - 0
keyboards/fc980c/keymaps/default/keymap.c

@@ -0,0 +1,39 @@
+/*
+Copyright 2017 Balz Guenat
+
+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 <http://www.gnu.org/licenses/>.
+*/
+#include "fc980c.h"
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+  [0] = KEYMAP(
+    KC_ESC,      KC_F1,KC_F2,KC_F3,KC_F4,KC_F5,KC_F6,KC_F7,KC_F8,  KC_F9,  KC_F10, KC_F11, KC_F12,                          KC_DEL, KC_INS, KC_PGUP,KC_PGDN,
+    KC_GRV, KC_1,KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9,   KC_0,   KC_MINS,KC_EQL, KC_BSPC,                         KC_NLCK,KC_PSLS,KC_PAST,KC_PMNS,
+    KC_TAB, KC_Q,KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O,   KC_P,   KC_LBRC,KC_RBRC,KC_BSLS,                         KC_P7,  KC_P8,  KC_P9,  KC_PPLS,
+    KC_CAPS,KC_A,KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L,   KC_SCLN,KC_QUOT,        KC_ENT,                          KC_P4,  KC_P5,  KC_P6,
+    KC_LSFT,     KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH,        KC_RSFT,         KC_UP,          KC_P1,  KC_P2,  KC_P3,  KC_PENT,
+    KC_LCTL,KC_LGUI,KC_LALT,                     KC_SPC,                   KC_RALT,KC_RCTL,MO(1),   KC_LEFT,KC_DOWN,KC_RGHT,        KC_P0,  KC_PDOT
+    ),
+  [1] = KEYMAP(
+    _______,        _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______,_______,                        _______,_______,KC_HOME,KC_END,
+    _______,_______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,_______,_______,                        _______,_______,_______,_______,
+    _______,_______,_______,_______,_______,_______,_______,_______,KC_PSCR, KC_SLCK, KC_PAUS, _______,_______,_______,                        _______,_______,_______,_______,
+    _______,_______,_______,_______,_______,_______,_______,_______,_______, _______, _______, _______,        _______,                        _______,_______,_______,
+    _______,        _______,_______,_______,_______,_______,_______,_______, _______, _______, _______,        _______,         KC_PGUP,       _______,_______,_______,_______,
+    _______,_______,_______,                           _______,                                _______,KC_APP, _______, KC_HOME,KC_PGDN,KC_END,        _______,_______     
+    ),
+};
+
+const uint16_t PROGMEM fn_actions[] = {
+};

+ 228 - 0
keyboards/fc980c/matrix.c

@@ -0,0 +1,228 @@
+/*
+Copyright 2017 Balz Guenat
+based on work by Jun Wako <wakojun@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * scan matrix
+ */
+#include <stdint.h>
+#include <stdbool.h>
+#include <util/delay.h>
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "timer.h"
+#include "matrix.h"
+#include "led.h"
+// #include "fc980c.h"
+
+
+// Timer resolution check
+#if (1000000/TIMER_RAW_FREQ > 20)
+#   error "Timer resolution(>20us) is not enough for HHKB matrix scan tweak on V-USB."
+#endif
+
+
+/*
+ * Pin configuration for ATMega32U4
+ *
+ * Row:     PD4-6, PD7(~EN)
+ * Col:     PB0-3
+ * Key:     PC6(pull-uped)
+ * Hys:     PC7
+ */
+static inline void KEY_ENABLE(void) { (PORTD &= ~(1<<7)); }
+static inline void KEY_UNABLE(void) { (PORTD |=  (1<<7)); }
+static inline bool KEY_STATE(void) { return (PINC & (1<<6)); }
+static inline void KEY_HYS_ON(void) { (PORTC |=  (1<<7)); }
+static inline void KEY_HYS_OFF(void) { (PORTC &= ~(1<<7)); }
+static inline void KEY_INIT(void)
+{
+    /* Col */
+    DDRB  |=  0x0F;
+    /* Key: input with pull-up */
+    DDRC  &= ~(1<<6);
+    PORTC |=  (1<<6);
+    /* Hys */
+    DDRC  |=  (1<<7);
+    /* Row */
+    DDRD  |=  0xF0;
+
+    KEY_UNABLE();
+    KEY_HYS_OFF();
+}
+static inline void SET_ROW(uint8_t ROW)
+{
+    // PD4-6
+    PORTD = (PORTD & 0x8F) | ((ROW & 0x07) << 4);
+}
+static inline void SET_COL(uint8_t COL)
+{
+    // PB0-3
+    PORTB = (PORTB & 0xF0) | (COL & 0x0F);
+}
+
+static uint32_t matrix_last_modified = 0;
+
+// matrix state buffer(1:on, 0:off)
+static matrix_row_t *matrix;
+static matrix_row_t *matrix_prev;
+static matrix_row_t _matrix0[MATRIX_ROWS];
+static matrix_row_t _matrix1[MATRIX_ROWS];
+
+
+__attribute__ ((weak))
+void matrix_init_quantum(void) {
+    matrix_init_kb();
+}
+
+__attribute__ ((weak))
+void matrix_scan_quantum(void) {
+    matrix_scan_kb();
+}
+
+__attribute__ ((weak))
+void matrix_init_kb(void) {
+    matrix_init_user();
+}
+
+__attribute__ ((weak))
+void matrix_scan_kb(void) {
+    matrix_scan_user();
+}
+
+__attribute__ ((weak))
+void matrix_init_user(void) {
+}
+
+__attribute__ ((weak))
+void matrix_scan_user(void) {
+}
+
+
+void matrix_init(void)
+{
+    debug_enable = true;
+    debug_matrix = true;
+
+    KEY_INIT();
+
+    // LEDs on NumLock, CapsLock and ScrollLock(PB4, PB5, PB6)
+    DDRB  |= (1<<4) | (1<<5) | (1<<6);
+    PORTB |= (1<<4) | (1<<5) | (1<<6);
+
+    // initialize matrix state: all keys off
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00;
+    for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix1[i] = 0x00;
+    matrix = _matrix0;
+    matrix_prev = _matrix1;
+    matrix_init_quantum();
+}
+
+uint8_t matrix_scan(void)
+{
+    matrix_row_t *tmp;
+
+    tmp = matrix_prev;
+    matrix_prev = matrix;
+    matrix = tmp;
+
+    uint8_t row, col;
+    for (col = 0; col < MATRIX_COLS; col++) {
+        SET_COL(col);
+        for (row = 0; row < MATRIX_ROWS; row++) {
+            //KEY_SELECT(row, col);
+            SET_ROW(row);
+            _delay_us(2);
+
+            // Not sure this is needed. This just emulates HHKB controller's behaviour.
+            if (matrix_prev[row] & (1<<col)) {
+                KEY_HYS_ON();
+            }
+            _delay_us(10);
+
+            // NOTE: KEY_STATE is valid only in 20us after KEY_ENABLE.
+            // If V-USB interrupts in this section we could lose 40us or so
+            // and would read invalid value from KEY_STATE.
+            uint8_t last = TIMER_RAW;
+
+            KEY_ENABLE();
+
+            // Wait for KEY_STATE outputs its value.
+            _delay_us(2);
+
+            if (KEY_STATE()) {
+                matrix[row] &= ~(1<<col);
+            } else {
+                matrix[row] |= (1<<col);
+            }
+
+            // Ignore if this code region execution time elapses more than 20us.
+            // MEMO: 20[us] * (TIMER_RAW_FREQ / 1000000)[count per us]
+            // MEMO: then change above using this rule: a/(b/c) = a*1/(b/c) = a*(c/b)
+            if (TIMER_DIFF_RAW(TIMER_RAW, last) > 20/(1000000/TIMER_RAW_FREQ)) {
+                matrix[row] = matrix_prev[row];
+            }
+
+            _delay_us(5);
+            KEY_HYS_OFF();
+            KEY_UNABLE();
+
+            // NOTE: KEY_STATE keep its state in 20us after KEY_ENABLE.
+            // This takes 25us or more to make sure KEY_STATE returns to idle state.
+            _delay_us(75);
+        }
+        if (matrix[row] ^ matrix_prev[row]) {
+            matrix_last_modified = timer_read32();
+        }
+    }
+    matrix_scan_quantum();
+    return 1;
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row) {
+    return matrix[row];
+}
+
+void matrix_print(void)
+{
+#if (MATRIX_COLS <= 8)
+    print("r/c 01234567\n");
+#elif (MATRIX_COLS <= 16)
+    print("r/c 0123456789ABCDEF\n");
+#elif (MATRIX_COLS <= 32)
+    print("r/c 0123456789ABCDEF0123456789ABCDEF\n");
+#endif
+
+    for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+
+#if (MATRIX_COLS <= 8)
+        xprintf("%02X: %08b%s\n", row, bitrev(matrix_get_row(row)),
+#elif (MATRIX_COLS <= 16)
+        xprintf("%02X: %016b%s\n", row, bitrev16(matrix_get_row(row)),
+#elif (MATRIX_COLS <= 32)
+        xprintf("%02X: %032b%s\n", row, bitrev32(matrix_get_row(row)),
+#endif
+#ifdef MATRIX_HAS_GHOST
+        matrix_has_ghost_in_row(row) ?  " <ghost" : ""
+#else
+        ""
+#endif
+        );
+    }
+}

+ 64 - 0
keyboards/fc980c/rules.mk

@@ -0,0 +1,64 @@
+# MCU name
+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
+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
+
+CUSTOM_MATRIX = yes
+SRC += matrix.c