diff --git a/keyboard/fc660c/Makefile b/keyboard/fc660c/Makefile new file mode 100644 index 0000000..7476d0f --- /dev/null +++ b/keyboard/fc660c/Makefile @@ -0,0 +1,110 @@ +# Target name +TARGET ?= fc660c + +# Location of tmk_core +TMK_DIR ?= ../../tmk_core + +# Location of target dependent files exist +TARGET_DIR ?= . + + +# List C source files +SRC ?= fc660c.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 +#UNIMAP_ENABLE ?= yes # Universal keymap +ACTIONMAP_ENABLE ?= yes # Use 16bit actionmap instead of 8bit 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/fc660c/README.md b/keyboard/fc660c/README.md new file mode 100644 index 0000000..3b46dae --- /dev/null +++ b/keyboard/fc660c/README.md @@ -0,0 +1,65 @@ +FC660C controller +================= +2017/02/24 + +Connector +--------- +### Hirose DF14A-20P-1.25H +[datasheet](http://www.mouser.com/ds/2/185/DF14_catalog-939195.pdf) + +### Pinouts +LV07A and LVC138A are 5V-tolerant, the keyboard will work only with 5V power. + + |Controller |Switch |Description |ATmega32u4 + |-----------|--------|------------------------------------------|-------------- + | 1 | 20 | +Z7-LV07A-13-~CapsLED |PB6 + | 2 | 19 | +Z7-LV07A-11-~InsertLED |PB7 + | 3 | 18 | +Z3-LVC138A-4-~G2A Z6-TP1684-5-~EN |PD7 + | 4 | 17 | +Z3-LVC138A-3-A |PD4 + | 5 | 16 | +Z3-LVC138A-3-B |PD5 + | 6 | 15 | +Z3-LVC138A-3-C |PD6 + | 7 | 14 | +Z7-LV07A-3 LV4051A-11-A |PB0 + | 8 | 13 | +Z7-LV07A-1 LV4051A-10-B |PB1 + | 9 | 12 | +Z7-LV07A-5 LV4051A-9-C |PB2 + |10 | 11 | *Z5-LV4051A-6-~EN(Col 8-F) |PB3 + |11 | 10 | *Z4-LV4051A-6-~EN(Col 0-7) |PB4 + |12 | 9 | *Z2-AD5258-4-SDA(I2C) |PD1(TWI) + |13 | 8 | *Z2-AD5258-5-SDL(I2C) |PD0(TWI) + |14 | 7 | *Z6-TP1684-2-KEY(i) |PC6 + |15 | 6 | *Z6-TP1684-4-HYS(o) |PC7 + |16 | 5 | 5V |5V + |17 | 4 | 3.3V |5V + |18 | 3 | GND |GND + |19 | 2 | GND |GND + |20 | 1 | FG |GND + +``` +* 5V intferface ++ 3.3V interface +``` + +Key Matrix +---------- +Row5-7 has no key, you can omit scaning those. Topre original controller scans those rows for some reason. + + | |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |A |B |C |D |E |F | + |----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----|----| + | 0|Q |W |E |Tab |R |U |T |Y |O |P |[ |I |] | |\ |Del | + | 1|1 |2 |3 |Esc |4 |7 |5 |6 |9 |0 |- |8 |= | |BSpc|Ins | + | 2| |LWin|LAlt|LCtl| | | |Spc |RAlt| |RCtl| |Fn |Down|Left|Rght| + | 3| |Z |X |LSft|C |N |V |B |, |. |/ |M |RSft|Up | | | + | 4|A |S |D |Caps|F |J |G |H |L |; |' |K | | |Entr| | + | 5| | | | | | | | | | | | | | | | | + | 6| | | | | | | | | | | | | | | | | + | 7| | | | | | | | | | | | | | | | | + + +Scan +---- +Row: Drive(LVC138A) +Col: Sense(4051) + + +Resources +--------- +- Pics https://imgur.com/a/4UKkZ diff --git a/keyboard/fc660c/actionmap.c b/keyboard/fc660c/actionmap.c new file mode 100644 index 0000000..e153cc1 --- /dev/null +++ b/keyboard/fc660c/actionmap.c @@ -0,0 +1,86 @@ +#include "action.h" +#include "actionmap.h" +#include "hook.h" + + +#define AMAP( \ + 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 } \ +} + + +#define AC_L3 ACTION_LAYER_MOMENTARY(3) +#define AC_L4 ACTION_LAYER_MOMENTARY(4) +#define AC_LS_2 ACTION_LAYER_MODS(2, MOD_LSFT) +#define AC_RS_2 ACTION_LAYER_MODS(2, MOD_RSFT) +#define AC_TGL1 ACTION_LAYER_TOGGLE(1) + +// emulates FC660C default keymap +const action_t actionmaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = { + [0] = AMAP( \ + ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, \ + LCTL,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, \ + LS_2,Z, X, C, V, B, N, M, COMM,DOT, SLSH, RS_2,UP, \ + LCTL,LGUI,LALT, SPC, RALT,RCTL,L3, LEFT,DOWN,RGHT \ + ), + [1] = AMAP( \ + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, INS, \ + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, DEL, \ + LCTL,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,RCTL,L4, LEFT,DOWN,RGHT \ + ), + [2] = AMAP( \ + GRV, 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, TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS, \ + TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS, TRNS,TRNS,TRNS \ + ), + [3] = AMAP( \ + GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, TRNS, \ + CAPS,TGL1,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,TRNS,TRNS, TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,TRNS,TRNS, TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,TRNS, TRNS,PGUP, \ + TRNS,TRNS,TRNS, TRNS, TRNS,APP, L3, HOME,PGDN,END \ + ), + [4] = AMAP( \ + ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, TRNS, TRNS, \ + CAPS,TGL1,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS,TRNS,TRNS,TRNS, TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,HOME,PGUP,TRNS,TRNS, TRNS, \ + TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,END, PGDN,TRNS, TRNS,PGUP, \ + TRNS,TRNS,TRNS, TRNS, TRNS,APP, L4, HOME,PGDN,END \ + ), +}; + + +void hook_layer_change(uint32_t layer_state) +{ + // lights LED on Insert when layer 1 is enabled + if (layer_state & (1L<<1)) { + PORTB &= ~(1<<7); + } else { + PORTB |= (1<<7); + } +} diff --git a/keyboard/fc660c/config.h b/keyboard/fc660c/config.h new file mode 100644 index 0000000..fc2c8f4 --- /dev/null +++ b/keyboard/fc660c/config.h @@ -0,0 +1,49 @@ +/* +Copyright 2017 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 + + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x660C +#define DEVICE_VER 0x0100 +#define MANUFACTURER TMK. +#define PRODUCT FC660C Alt Controller +#define DESCRIPTION TMK. keyboard firmware for FC660C + + +/* 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/fc660c/fc660c.c b/keyboard/fc660c/fc660c.c new file mode 100644 index 0000000..6269885 --- /dev/null +++ b/keyboard/fc660c/fc660c.c @@ -0,0 +1,139 @@ +/* +Copyright 2017 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 "print.h" +#include "debug.h" +#include "util.h" +#include "timer.h" +#include "matrix.h" +#include +#include "suspend.h" +#include "lufa.h" +#include "led.h" +#include "fc660c.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 + + KEY_INIT(); + + // LEDs on CapsLock and Insert + DDRB |= (1<<6) | (1<<7); + PORTB |= (1<<6) | (1<<7); + + // 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< 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< +#include +#include +#include +#include + + +// 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 + + +/* + * HHKB Matrix I/O + * + * row: HC4051[A,B,C] selects scan row0-7 + * row-ext: [En0,En1] row extention for JP + * col: LS145[A,B,C,D] selects scan col0-7 and enable(D) + * key: on: 0/off: 1 + * prev: hysteresis control: assert(1) when previous key state is on + */ + + +/* + * Pin configuration for ATMega32U4 + * + * Row: PD4-6, 7(~EN) + * Col: PB0-2, 3(Z5 ~EN), 4(Z4 ~EN) + * 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 |= 0x1F; + /* 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) +{ + // set row with unabling key + PORTD = (PORTD & 0x0F) | (1<<7) | ((ROW & 0x07) << 4); +} +static inline void SET_COL(uint8_t COL) +{ + // |PB3(Z5 ~EN)|PB4(Z4 ~EN) + // --------|-----------|----------- + // Col:0-7 |high |low + // Col:8-F |low |high + PORTB = (PORTB & 0xE0) | ((COL & 0x08) ? 1<<4 : 1<<3) | (COL & 0x07); +} + +#endif