Merge branch 'fc660c'

This commit is contained in:
tmk 2017-03-06 09:26:16 +09:00
commit 1972b40eae
6 changed files with 519 additions and 0 deletions

110
keyboard/fc660c/Makefile Normal file
View file

@ -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

65
keyboard/fc660c/README.md Normal file
View file

@ -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

View file

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

49
keyboard/fc660c/config.h Normal file
View file

@ -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 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

139
keyboard/fc660c/fc660c.c Normal file
View file

@ -0,0 +1,139 @@
/*
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 <avr/wdt.h>
#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<<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_CAPS_LOCK)) {
PORTB &= ~(1<<6);
} else {
PORTB |= (1<<6);
}
}

70
keyboard/fc660c/fc660c.h Normal file
View file

@ -0,0 +1,70 @@
#ifndef FC660C_H
#define FC660C_H
#include <stdint.h>
#include <stdbool.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.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
/*
* 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