]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
fc980c: Add initial files
authortmk <hasu@tmk-kbd.com>
Tue, 11 Jul 2017 07:01:19 +0000 (16:01 +0900)
committertmk <hasu@tmk-kbd.com>
Fri, 21 Jul 2017 04:00:37 +0000 (13:00 +0900)
keyboard/fc980c/Makefile [new file with mode: 0644]
keyboard/fc980c/README.md [new file with mode: 0644]
keyboard/fc980c/config.h [new file with mode: 0644]
keyboard/fc980c/fc980c.c [new file with mode: 0644]
keyboard/fc980c/fc980c.h [new file with mode: 0644]
keyboard/fc980c/unimap.c [new file with mode: 0644]

diff --git a/keyboard/fc980c/Makefile b/keyboard/fc980c/Makefile
new file mode 100644 (file)
index 0000000..cecec45
--- /dev/null
@@ -0,0 +1,110 @@
+# Target name
+TARGET ?= fc980c
+
+# Location of tmk_core
+TMK_DIR ?= ../../tmk_core
+
+# Location of target dependent files exist
+TARGET_DIR ?= .
+
+
+# List C source files
+SRC ?= fc980c.c
+
+# Configure file
+CONFIG_H ?= config.h
+
+
+# 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
+OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
+
+
+# Boot Section Size in *bytes*
+#   Teensy halfKay   512
+#   Teensy++ halfKay 1024
+#   Atmel DFU loader 4096      (TMK Alt Controller)
+#   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
+MOUSEKEY_ENABLE ?= yes         # Mouse keys
+EXTRAKEY_ENABLE ?= yes         # Audio control and System control
+CONSOLE_ENABLE ?= yes          # Console for debug
+COMMAND_ENABLE ?= yes          # Commands for debug and configuration
+NKRO_ENABLE ?= yes             # USB Nkey Rollover
+#ACTIONMAP_ENABLE ?= yes               # Use 16bit actionmap instead of 8bit keymap
+UNIMAP_ENABLE ?= yes           # Universal keymap
+KEYMAP_SECTION_ENABLE ?= yes   # fixed address keymap for keymap editor
+
+#OPT_DEFS += -DNO_ACTION_TAPPING
+#OPT_DEFS += -DNO_ACTION_LAYER
+#OPT_DEFS += -DNO_ACTION_MACRO
+
+
+#
+# Keymap file
+#
+ifeq (yes,$(strip $(UNIMAP_ENABLE)))
+    KEYMAP_FILE = unimap
+else
+    ifeq (yes,$(strip $(ACTIONMAP_ENABLE)))
+        KEYMAP_FILE = actionmap
+    else
+        KEYMAP_FILE = keymap
+    endif
+endif
+ifdef KEYMAP
+    SRC := $(KEYMAP_FILE)_$(KEYMAP).c $(SRC)
+else
+    SRC := $(KEYMAP_FILE).c $(SRC)
+endif
+
+
+# Search Path
+VPATH += $(TARGET_DIR)
+VPATH += $(TMK_DIR)
+
+include $(TMK_DIR)/protocol/lufa.mk
+include $(TMK_DIR)/common.mk
+include $(TMK_DIR)/rules.mk
diff --git a/keyboard/fc980c/README.md b/keyboard/fc980c/README.md
new file mode 100644 (file)
index 0000000..7833c5f
--- /dev/null
@@ -0,0 +1,138 @@
+FC980C Alt controller
+=====================
+2017/07/11
+
+This keyboard is very similar to FC660C hardware.
+
+FC660C Alt Controller: https://geekhack.org/index.php?topic=88439.0
+
+
+Firmware
+--------
+Just `make` to build firmware. And consult with wiki for further information.
+
+https://github.com/tmk/tmk_keyboard/wiki
+
+
+Pinouts
+-------
+ATMega32u4 pin configuration is temporary for test with FC660C Alt controller.
+
+    |Switch  |Controller |
+    |  board |     board |Description                           |Function   |ATmega32u4
+    |--------|-----------|--------------------------------------|-----------|------------
+    | 1      |20         | FG                                   |FG         |GND
+    | 2      |19         | GND                                  |GND        |GND
+    | 3      |18         | GND                                  |GND        |GND
+    | 4      |17         | 3.3V                                 |V33        |3.3V/5V
+    | 5      |16         | 5V                                   |Vcc        |5V
+    | 6      |15         |*Z6-TP1684-4-HYS(o)                   |KEY_HYS    |PC7
+    | 7      |14         |*Z6-TP1684-2-KEY(i)                   |KEY_STATE  |PC6
+    | 8      |13         |*Z7-AD5258-5-SCL(I2C)                 |I2C_CCL    |PD0(TWI)
+    | 9      |12         |*Z7-AD5258-4-SDA(I2C)                 |I2C_SDA    |PD1(TWI)
+    |10      |11         |*Z5/4-LV4051A-6-~EN(Lo:Z5 Hi:Z4)      |COL_bit3   |PB4    PB3
+    |11      |10         |+Z3-LV07A-5 (LV4051A-9-C)             |COL_bit2   |PB3    PB2
+    |12      | 9         |+Z3-LV07A-1 (LV4051A-10-B)            |COL_bit1   |PB2    PB1
+    |13      | 8         |+Z3-LV07A-3 (LV4051A-11-A)            |COL_bit0   |PB1    PB0
+    |14      | 7         |+Z1-LVC138A-3-C                       |ROW_bit2   |PB0    PD6
+    |15      | 6         |+Z1-LVC138A-2-B                       |ROW_bit1   |PD6    PD5
+    |16      | 5         |+Z1-LVC138A-1-A                       |ROW_bit0   |PD5    PD4
+    |17      | 4         |+Z1-LVC138A-4-~G2A  Z6-TP1684-5-~EN   |KEY_ENABLE |PD4    PD7
+    |18      | 3         |+Q4-MOSFET-G-NumLock_LED(Hi:On)       |LED_NUML   |PD7    PB4
+    |19      | 2         |+Q3-MOSFET-G-CapsLock_LED(Hi:On)      |LED_CAPS   |PB5
+    |20      | 1         |+Q2-MOSFET-G-ScrollLock_LED(Hi:On)    |LED_SCRL   |PB6
+
+```
+* 5V intferface
++ 3.3V interface
+```
+
+- Connector on Switch board: https://i.imgur.com/Zi89xO5.jpg
+- Connector on Controller board: https://i.imgur.com/9SZUzYo.jpg
+
+
+Key Matrix
+----------
+
+    |    |0   |1   |2   |3   |4   |5   |6   |7   |8   |9   |A   |B   |C   |D   |E   |F   |
+    |----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|
+    |   0|Left|RCtl|RAlt|    |Down|P.  |Righ|P0  |X   |LGui|`   |V   |    |Esc |M   |Spc |
+    |   1|Fn  |.   |    |    |P1  |PEnt|P2  |P3  |Z   |LAlt|RCtl|C   |K   |    |N   |B   |
+    |   2|'   |/   |,   |    |P4  |P+  |P5  |P6  |D   |A   |LSft|F   |J   |F1  |H   |G   |
+    |   3|RSft|;   |L   |]   |Up  |    |    |    |S   |Q   |Caps|R   |I   |F3  |U   |T   |
+    |   4|    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |    |
+    |   5|=   |-   |0   |\   |NLck|BSpc|P/  |P*  |3   |2   |    |4   |9   |F2  |7   |6   |
+    |   6|[   |P   |O   |Ent |P7  |P-  |P8  |P9  |W   |1   |Tab |E   |8   |F4  |Y   |5   |
+    |   7|F11 |F10 |F9  |F12 |Del |PgDn|Ins |PgUp|    |    |    |    |F8  |F5  |F7  |F6  |
+
+
+Logic analyzer pics:
+- http://i.imgur.com/9XoNTev.png
+- https://i.imgur.com/5FCP1Ay.png
+
+This code emuluates what original cotnroller does for matrix scan.
+- https://github.com/tmk/tmk_keyboard/blob/master/keyboard/fc660c/fc660c.c
+
+
+### Row designation
+LV138A(Z1) selects a row line and gives strobe by enabling with ~G2A(18).
+
+    |Row |A/16|B/15|C/14|
+    |----|----|----|----|
+    |0   |0   |0   |0   |
+    |1   |1   |0   |0   |
+    |2   |0   |1   |0   |
+    |3   |1   |1   |0   |
+    |4   |0   |0   |1   |
+    |5   |1   |0   |1   |
+    |6   |0   |1   |1   |
+    |7   |1   |1   |1   |
+
+
+### Column designation
+LV4051A(Z4, Z5) select one of 16 column lines to sense capacitance of switches.
+
+    |Col |A/13|B/12|C/11|Z4/5-EN/10|
+    |----|----|----|----|----------|
+    |0   |0   |0   |0   |0         |
+    |1   |1   |0   |0   |0         |
+    |2   |0   |1   |0   |0         |
+    |3   |1   |1   |0   |0         |
+    |4   |0   |0   |1   |0         |
+    |5   |1   |0   |1   |0         |
+    |6   |0   |1   |1   |0         |
+    |7   |1   |1   |1   |0         |
+    |8   |0   |0   |0   |1         |
+    |9   |1   |0   |0   |1         |
+    |A   |0   |1   |0   |1         |
+    |B   |1   |1   |0   |1         |
+    |C   |0   |0   |1   |1         |
+    |D   |1   |0   |1   |1         |
+    |E   |0   |1   |1   |1         |
+    |F   |1   |1   |1   |1         |
+
+
+Datasheets
+----------
+- Hirose DF14A-20P-1.25H: http://www.mouser.com/ds/2/185/DF14_catalog-939195.pdf
+- LV07A: http://www.ti.com/lit/ds/symlink/sn74lv07a.pdf
+- LV138A: http://www.ti.com/lit/ds/symlink/sn74lvc138a.pdf
+- LV4051A: http://www.ti.com/lit/ds/symlink/sn74lv4051a.pdf
+- AD5258: http://www.analog.com/media/en/technical-documentation/data-sheets/AD5258.pdf
+
+
+3.3V power supply
+-----------------
+LV07A and LVC138A are 5V-tolerant and can be powered with 5V, the keyboard will work only with 5V power supply. It may not be completely safe to operate LV138A with 5V Vcc, its datasheet says:
+
+> Exposure to absolute-maximum-rated conditions for extended periods may affect device reliability.
+
+Digipot AD5258
+--------------
+Controller can operate AD5258 via I2C to change actuation point of keys. This may make keyboard unusable accidentally and it will be difficult to recovery in some situation. For safety firmware doesn't support it at this point, though.
+
+Lower value of RDAC register causes shallower actuation point.
+
+Resources
+---------
+- Pics: http://imgur.com/a/HhyIq
diff --git a/keyboard/fc980c/config.h b/keyboard/fc980c/config.h
new file mode 100644 (file)
index 0000000..adbf29c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+Copyright 2017 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/>.
+*/
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+
+#define VENDOR_ID       0xFEED
+#define PRODUCT_ID      0x980C
+#define DEVICE_VER      0x0100
+#define MANUFACTURER    TMK.
+#define PRODUCT         FC980C Alt Controller
+#define DESCRIPTION     TMK. keyboard firmware for FC980C
+
+
+/* matrix size */
+#define MATRIX_ROWS 8
+#define MATRIX_COLS 16
+
+
+/* key combination for command */
+#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT))) 
+
+
+/* period of tapping(ms) */
+#define TAPPING_TERM    300
+/* tap count needed for toggling a feature */
+#define TAPPING_TOGGLE  5
+/* Oneshot timeout(ms) */
+#define ONESHOT_TIMEOUT 300
+
+/* Boot Magic salt key: Space */
+#define BOOTMAGIC_KEY_SALT      KC_SPACE
+
+#endif
diff --git a/keyboard/fc980c/fc980c.c b/keyboard/fc980c/fc980c.c
new file mode 100644 (file)
index 0000000..f64ad80
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+Copyright 2017 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"
+
+
+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];
+
+
+void matrix_init(void)
+{
+#if 0
+    debug_enable = true;
+    debug_keyboard = true;
+    debug_matrix = true;
+#endif
+    debug_enable = true;
+    debug_matrix = true;
+
+    KEY_INIT();
+
+    // LEDs on NumLock, CapsLock and ScrollLock(PD7, PB5, PB6)
+    DDRD  |= (1<<7);
+    PORTD |= (1<<7);
+    DDRB  |= (1<<5) | (1<<6);
+    PORTB |= (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;
+}
+
+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();
+        }
+    }
+    return 1;
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+    return matrix[row];
+}
+
+void led_set(uint8_t usb_led)
+{
+    if (usb_led & (1<<USB_LED_NUM_LOCK)) {
+        PORTD |=  (1<<7);
+    } else {
+        PORTD &= ~(1<<7);
+    }
+    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);
+    }
+}
+
+
+#ifdef UNIMAP_ENABLE
+#include <avr/pgmspace.h>
+#include "unimap.h"
+
+const uint8_t PROGMEM unimap_trans[MATRIX_ROWS][MATRIX_COLS] = {
+    { UNIMAP_LEFT, UNIMAP_RCTL, UNIMAP_RALT, UNIMAP_NO  , UNIMAP_DOWN, UNIMAP_PDOT, UNIMAP_RGHT, UNIMAP_P0  ,
+      UNIMAP_X   , UNIMAP_LGUI, UNIMAP_GRV , UNIMAP_V   , UNIMAP_NO  , UNIMAP_ESC , UNIMAP_M   , UNIMAP_SPC   },
+    { UNIMAP_RGUI, UNIMAP_DOT , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_P1  , UNIMAP_PENT, UNIMAP_P2  , UNIMAP_P3  ,
+      UNIMAP_Z   , UNIMAP_LALT, UNIMAP_RCTL, UNIMAP_C   , UNIMAP_K   , UNIMAP_NO  , UNIMAP_N   , UNIMAP_B     },
+    { UNIMAP_QUOT, UNIMAP_SLSH, UNIMAP_COMM, UNIMAP_NO  , UNIMAP_P4  , UNIMAP_PPLS, UNIMAP_P5  , UNIMAP_P6  ,
+      UNIMAP_D   , UNIMAP_A   , UNIMAP_LSFT, UNIMAP_F   , UNIMAP_J   , UNIMAP_F1  , UNIMAP_H   , UNIMAP_G     },
+    { UNIMAP_RSFT, UNIMAP_SCLN, UNIMAP_L   , UNIMAP_RBRC, UNIMAP_UP  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  ,
+      UNIMAP_S   , UNIMAP_Q   , UNIMAP_CAPS, UNIMAP_R   , UNIMAP_I   , UNIMAP_F3  , UNIMAP_U   , UNIMAP_T     },
+    { UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  ,
+      UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO    },
+    { UNIMAP_EQL , UNIMAP_MINS, UNIMAP_0   , UNIMAP_BSLS, UNIMAP_NLCK, UNIMAP_BSPC, UNIMAP_PSLS, UNIMAP_PAST,
+      UNIMAP_3   , UNIMAP_2   , UNIMAP_NO  , UNIMAP_4   , UNIMAP_9   , UNIMAP_F2  , UNIMAP_7   , UNIMAP_6     },
+    { UNIMAP_LBRC, UNIMAP_P   , UNIMAP_O   , UNIMAP_ENT , UNIMAP_P7  , UNIMAP_PMNS, UNIMAP_P8  , UNIMAP_P9  ,
+      UNIMAP_W   , UNIMAP_1   , UNIMAP_TAB , UNIMAP_E   , UNIMAP_8   , UNIMAP_F4  , UNIMAP_Y   , UNIMAP_5     },
+    { UNIMAP_F11 , UNIMAP_F10 , UNIMAP_F9  , UNIMAP_F12 , UNIMAP_DEL , UNIMAP_PGDN, UNIMAP_INS , UNIMAP_PGUP,
+      UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_NO  , UNIMAP_F8  , UNIMAP_F5  , UNIMAP_F7  , UNIMAP_F6    }
+
+};
+#endif
diff --git a/keyboard/fc980c/fc980c.h b/keyboard/fc980c/fc980c.h
new file mode 100644 (file)
index 0000000..c08478c
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef FC980C_H
+#define FC980C_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "timer.h"
+#include "unimap.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:     PD5,6,PB0, PD4(~EN)
+ * Col:     PB1-3, 4
+ * Key:     PC6(pull-uped)
+ * Hys:     PC7
+ */
+static inline void KEY_ENABLE(void) { (PORTD &= ~(1<<4)); }
+static inline void KEY_UNABLE(void) { (PORTD |=  (1<<4)); }
+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  |=  0x1F;
+    /* Key: input with pull-up */
+    DDRC  &= ~(1<<6);
+    PORTC |=  (1<<6);
+    /* Hys */
+    DDRC  |=  (1<<7);
+    /* Row */
+    DDRD  |=  0x70;
+
+    KEY_UNABLE();
+    KEY_HYS_OFF();
+}
+static inline void SET_ROW(uint8_t ROW)
+{
+    // set row with unabling key
+    PORTB = (PORTB & 0xFE) | ((ROW & 0x04) >> 2); // PB0
+    PORTD = (PORTD & 0x9F) | ((ROW & 0x03) << 5); // PD5,6
+}
+static inline void SET_COL(uint8_t COL)
+{
+    // PB4(Lo:Z5, Hi:Z4)
+    // PB1-3
+    PORTB = (PORTB & 0xE1) | ((COL & 0x0F) << 1);
+}
+
+
+#ifdef UNIMAP_ENABLE
+/* unimap */
+#define KMAP( \
+    K29,    K3A,K3B,K3C,K3D,K3E,K3F,K40,K41,K42,K43,K44,K45,                K4C,K49,K4B,K4E, \
+    K35,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K2D,K2E,K2A,                K53,K54,K55,K56, \
+    K2B,K14,K1A,K08,K15,K17,K1C,K18,K0C,K12,K13,K2F,K30,K31,                K5F,K60,K61,K57, \
+    K39,K04,K16,K07,K09,K0A,K0B,K0D,K0E,K0F,K33,K34,    K28,                K5C,K5D,K5E,     \
+    K79,    K1D,K1B,K06,K19,K05,K11,K10,K36,K37,K38,    K7D,      K52,      K59,K5A,K5B,K58, \
+    K78,K7B,K7A,            K2C,                K7E,K7C,K7F,  K50,K51,K4F,      K62,K63      \
+) UNIMAP( \
+            NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO, NO,                                      \
+    K29,    K3A,K3B,K3C,K3D,K3E,K3F,K40,K41,K42,K43,K44,K45,      NO, NO, NO,       NO, NO, NO,  \
+    K35,K1E,K1F,K20,K21,K22,K23,K24,K25,K26,K27,K2D,K2E,NO, K2A,  K49,NO, K4B,  K53,K54,K55,K56, \
+    K2B,K14,K1A,K08,K15,K17,K1C,K18,K0C,K12,K13,K2F,K30,    K31,  K4C,NO, K4E,  K5F,K60,K61,K57, \
+    K39,K04,K16,K07,K09,K0A,K0B,K0D,K0E,K0F,K33,K34,    NO, K28,                K5C,K5D,K5E,NO,  \
+    K79,NO, K1D,K1B,K06,K19,K05,K11,K10,K36,K37,K38,    NO, K7D,      K52,      K59,K5A,K5B,K58, \
+    K78,K7B,K7A,NO,         K2C,        NO, NO, K7E,K7F,NO, K7C,  K50,K51,K4F,      K62,K63,NO   \
+)
+#else
+/* actionmap */
+/*
+#define KMAP( \
+    K13, K10, K11, K12, K14, K16, K17, K15, K1B, K18, K19, K1A, K1C, K1E,      K1F, \
+    K03, K00, K01, K02, K04, K06, K07, K05, K0B, K08, K09, K0A, K0C, K0E,      K0F, \
+    K43, K40, K41, K42, K44, K46, K47, K45, K4B, K48, K49, K4A,      K4E,           \
+    K33, K31, K32, K34, K36, K37, K35, K3B, K38, K39, K3A,           K3C, K3D,      \
+    K23, K21, K22,                K27,                K28, K2A, K2C, K2E, K2D, K2F  \
+) { \
+    { AC_##K00, AC_##K01, AC_##K02, AC_##K03, AC_##K04, AC_##K05, AC_##K06, AC_##K07,   \
+      AC_##K08, AC_##K09, AC_##K0A, AC_##K0B, AC_##K0C, AC_NO,    AC_##K0E, AC_##K0F }, \
+    { AC_##K10, AC_##K11, AC_##K12, AC_##K13, AC_##K14, AC_##K15, AC_##K16, AC_##K17,   \
+      AC_##K18, AC_##K19, AC_##K1A, AC_##K1B, AC_##K1C, AC_NO,    AC_##K1E, AC_##K1F }, \
+    { AC_NO,    AC_##K21, AC_##K22, AC_##K23, AC_NO,    AC_NO,    AC_NO,    AC_##K27,   \
+      AC_##K28, AC_NO,    AC_##K2A, AC_NO,    AC_##K2C, AC_##K2D, AC_##K2E, AC_##K2F }, \
+    { AC_NO,    AC_##K31, AC_##K32, AC_##K33, AC_##K34, AC_##K35, AC_##K36, AC_##K37,   \
+      AC_##K38, AC_##K39, AC_##K3A, AC_##K3B, AC_##K3C, AC_##K3D, AC_NO,    AC_NO    }, \
+    { AC_##K40, AC_##K41, AC_##K42, AC_##K43, AC_##K44, AC_##K45, AC_##K46, AC_##K47,   \
+      AC_##K48, AC_##K49, AC_##K4A, AC_##K4B, AC_NO,    AC_NO,    AC_##K4E, AC_NO    }, \
+    { AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,      \
+      AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO    }, \
+    { AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,      \
+      AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO    }, \
+    { AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,      \
+      AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO,    AC_NO    }  \
+}
+*/
+#endif
+
+#endif
diff --git a/keyboard/fc980c/unimap.c b/keyboard/fc980c/unimap.c
new file mode 100644 (file)
index 0000000..0caf4ef
--- /dev/null
@@ -0,0 +1,20 @@
+#include "action.h"
+#include "actionmap.h"
+#include "hook.h"
+#include "fc980c.h"
+
+
+#ifdef KEYMAP_SECTION_ENABLE
+const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] __attribute__ ((section (".keymap.keymaps"))) = {
+#else
+const action_t actionmaps[][UNIMAP_ROWS][UNIMAP_COLS] PROGMEM = {
+#endif
+    [0] = KMAP(
+    ESC,      F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11, F12,                         DEL, INS, PGUP,PGDN,
+    GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,EQL, BSPC,                        NLCK,PSLS,PAST,PMNS,
+    TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,                        P7,  P8,  P9,  PPLS,
+    CAPS,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,     ENT,                         P4,  P5,  P6,       
+    LSFT,     Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,     RSFT,          UP,           P1,  P2,  P3,  PENT,
+    LCTL,LGUI,LALT,               SPC,                     RALT,RCTL,RGUI,     LEFT,DOWN,RGHT,         P0,  PDOT     
+    ),
+};