summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfredizzimo <fsundvik@gmail.com>2016-07-01 17:04:53 +0300
committerJack Humbert <jack.humb@gmail.com>2016-07-01 10:04:53 -0400
commit4d4f7684e684bec319f166121463a88cd4a62703 (patch)
tree4c04ce03e49356283925556342845b1bd656e930
parenta8b55f8c858933a0f7641f7bf2dede640235aa70 (diff)
Add ChibiOS support for QMK (#465)
* Modularity and gcc warnings fixes. * Add ChibiOS support (USB stack + support files). * Make usb_main more USB_DRIVER #define independent. * Move chibios to tool. * Implement jump-to-bootloader. * Small updates. * Fix bootloader-jump compiling. * Move AVR specific sleep_led.c into avr. * Add basic sleep_led for chibios. * Update chibios README. * NKRO fixes. * Rename some Makefile defines. * Move STM32 bootloader address config to separate .h file. * Add ARM Teensies bootloader code. * Fix chibios/usb_main GET_REPORT handing. * Add missing #include to keymap.c. * Make bootmagic.c code portable (_delay_ms -> wait_ms). * Move declaration of keymap_config. Should really not declare variables in .h files - since it's included in different .c files, a proper linker then complains that the same variable is declared more than once (once for each .c file that the offending .h is included in). * Add eeprom support for chibios/kinetis. * Rename chibios example keyboard. * Move chibios/cortex selection to local Makefiles. * Chibios: use WFI in idle. WIP suspend stuff. * ChibiOS/kinetis: sending remote wakeup. * ChibiOS/STM32: send remote wakeup. * Fix report size of boot protocol. * Fix drop key stroke Keyboard report should be checked if its transfer finishs successfully. Otherwise key stroke can be missing when other key event occurs before the last report transfer is done. Boot protocol 10ms interval probably causes this problem in case it receives key events in a row within the period. NKRO protocol suffers less or nothing due to its interval 1ms. * Chibios/usb_main: rename a variable for clarity. * Add correct chibios/bootloader_jump for infinity KB. * ChibiOS: make reset request more CMSISy. * Chibios: Add breathing sleep LED on Kinetis MCUs. * ChibiOS: Update infinity bootloader code to match updated ChibiOS. * ChibiOS: prettify/document sleep_led code. * Chibios: Remove the wait in the main loop. * Add maple mini code. * Do timeout when writing to CONSOLE EP queue. Fixes TMK bug #266. * Chibios: add 'core/protocol' to the makefiles' search path. * Chibios: Update to new USB API. * Chibios: add more guards for transmitting (fix a deadlock bug). * Add update for chibios in README * Chibios: Fix a HardFault bug (wait after start). * Chibios: cleanup usb_main code. * Chibios: Revert common.mk change (fix AVR linking problem). * core: Fix chibios user compile options Compile options can be defined in project Makefile such as UDEFS, UADEFS, UINCDIR, ULIBDIR and ULIBS. * Sysv format for ChibiOS arm-none-eabi-size Some new patches to ChibiOS puts heap as it's own section. So the berkeley format is now useless, as the heap will be included in the BSS report. The sysv format displays the bss size correctly. * Fix hard-coded path of CHIBIOS * Add support for new version of ChibiOS and Contrib The Kinetis support has moved to a separate Contrib repository in the newest version of Chibios. There has also been some structure changes. So this adds support for those, while maintaining back- wards compability. * Update ChibiOS instructions * Chibios: implement sleep LED for STM32. * Chibios: Update the main chibios README. * Chibios: fix STM32_BOOTLOADER_ADDRESS name. * Chibios: make the default bootloader_jump redefinable (weak). * Chibios: disable LTO (link-time optimisation). With LTO enabled, sometimes things fail for mysterious reasons (e.g. bootloader jump on WF with LEDs enabled), just because the linker optimisation is too aggressive. * Chibios: add default location for chibios-contrib. * ChibiOS: update mk to match chibios/master. * ChibiOS: update instructions.md. * Add chibi_onekey example. * Add comments to chibi_onekey Makefile. * Rename some Makefile defines. * Move STM32 bootloader address config to separate .h file. * Rename chibios example keyboard. * Move chibios/cortex selection to local Makefiles. * Add Teensy LC onekey example. * Chibios: use WFI in idle. WIP suspend stuff. * Update chibi/teensy instructions. * Update chibios/Teensy instructions. * Add infinity_chibios * Add keymap_hasu.c * Infinity_chibios: select correct bootloader_jump. * Infinity_chibios: improve comments. * Add generic STM32F103C8T6 example. * Add maple mini code. * STM32F103x fixes. * Add maple mini pinout pic. * Chibios: updates for 3.0.4 git. * Chibios: rename example stm32_onekey -> stm32_f072_onekey. * Chibios: add makefiles for Teensy 3.x examples. * Chibios: update Teensy 3.x instructions. * Chibios: Tsy LC is cortex-m0plus. * Chibios: add more guards for transmitting (fix a deadlock bug). * Change README for chibios * Chibios: update examples to current chibios git. Match the changes in mainline chibios: - update chconf.h - update supplied ld scripts structure - update Teensy instructions (switch to official chibios and introduce contrib) * Add ChibiOS and ChibiOS-Contrib submodules Also fix the makefile path for them. * Moves chibios keyboards to keyboards folder * First version of ChibiOS compilation Only the stm32_f072_onkey keyboard is ported at the moment. It compiles, but still doesn't link. * More chibios fixes It now compiles without warnings and links * Move the teensy_lc_onekey to the keyboards folder * Clean up the make file rule structure * Remove keymap_fn_to_action * Update more ChibiOS keyboards to QMK Most of them does not compile at the moment though. * Use older version of Chibios libraries The newest ones have problems with compilation * Remove USB_UNCONFIGURED event It isn't present in the older version of ChibiOS * Fix the infinity_chibios compilation * Fix potentially uninitialized variable * Add missing include * Fix the ChibiOS makefile * Fix some Chibios keyboard compilation * Revert the rules.mk file back to master version * Combine the chibios and AVR makefiles With just the required overrides in the respective platform specific one. * Slight makefile restrucuring Platform specific compiler options * Move avr specific targets out of the main rules * Fix ChibiOS objcopy The ChibiOS objcopy needs different parameters, so the parameters are moved to the corresponding platform rule file * Fix the objcopy for real this time The comands were moved around, so chibios used avr and the ohter way around. Also change the objsize output format * Fix the thumb flags * Fix the infinity hasu keymap * Per platform cpp flags * Add gcc-arm-none-eabi package to travis * Add arm-none-eabi-newlib to travis * Fix the name of the libnewlib-arm-none-eabi lib * Fix the ChibiOS paths So that they are properly relative, and builds don't generate extra folders * Fix the board path of stm32_f103_onekey * Only consider folders with Makefiles as subproject
-rw-r--r--.gitmodules6
-rw-r--r--.travis.yml5
-rw-r--r--Makefile31
-rw-r--r--keyboards/infinity_chibios/MEMO.txt385
-rw-r--r--keyboards/infinity_chibios/Makefile70
-rw-r--r--keyboards/infinity_chibios/bootloader_defs.h1
-rw-r--r--keyboards/infinity_chibios/chconf.h524
-rw-r--r--keyboards/infinity_chibios/config.h75
-rw-r--r--keyboards/infinity_chibios/halconf.h353
-rw-r--r--keyboards/infinity_chibios/infinity_chibios.c17
-rw-r--r--keyboards/infinity_chibios/infinity_chibios.h66
-rw-r--r--keyboards/infinity_chibios/keymaps/default/keymap.c48
-rw-r--r--keyboards/infinity_chibios/keymaps/hasu/keymap.c199
-rw-r--r--keyboards/infinity_chibios/led.c24
-rw-r--r--keyboards/infinity_chibios/matrix.c128
-rw-r--r--keyboards/infinity_chibios/mcuconf.h55
-rw-r--r--keyboards/planck/out.txt66
-rw-r--r--keyboards/stm32_f072_onekey/Makefile50
-rw-r--r--keyboards/stm32_f072_onekey/bootloader_defs.h7
-rw-r--r--keyboards/stm32_f072_onekey/chconf.h524
-rw-r--r--keyboards/stm32_f072_onekey/config.h76
-rw-r--r--keyboards/stm32_f072_onekey/halconf.h353
-rw-r--r--keyboards/stm32_f072_onekey/keymaps/default/keymap.c25
-rw-r--r--keyboards/stm32_f072_onekey/led.c34
-rw-r--r--keyboards/stm32_f072_onekey/matrix.c163
-rw-r--r--keyboards/stm32_f072_onekey/mcuconf.h171
-rw-r--r--keyboards/stm32_f072_onekey/stm32_f072_onekey.c1
-rw-r--r--keyboards/stm32_f072_onekey/stm32_f072_onekey.h5
-rw-r--r--keyboards/stm32_f103_onekey/Makefile64
-rw-r--r--keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.c49
-rw-r--r--keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.h166
-rw-r--r--keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.mk5
-rw-r--r--keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/mini_stm32_mapping.pngbin0 -> 162908 bytes
-rw-r--r--keyboards/stm32_f103_onekey/boards/maple_mini_mapping.pngbin0 -> 237977 bytes
-rw-r--r--keyboards/stm32_f103_onekey/bootloader_defs.h10
-rw-r--r--keyboards/stm32_f103_onekey/chconf.h524
-rw-r--r--keyboards/stm32_f103_onekey/config.h75
-rwxr-xr-xkeyboards/stm32_f103_onekey/flash.sh2
-rw-r--r--keyboards/stm32_f103_onekey/halconf.h353
-rw-r--r--keyboards/stm32_f103_onekey/keymaps/default/keymap.c25
-rw-r--r--keyboards/stm32_f103_onekey/ld/STM32F103x8_stm32duino_bootloader.ld88
-rw-r--r--keyboards/stm32_f103_onekey/led.c43
-rw-r--r--keyboards/stm32_f103_onekey/matrix.c177
-rw-r--r--keyboards/stm32_f103_onekey/mcuconf.h209
-rw-r--r--keyboards/stm32_f103_onekey/stm32_f103_onekey.c1
-rw-r--r--keyboards/stm32_f103_onekey/stm32_f103_onekey.h4
-rw-r--r--keyboards/teensy_lc_onekey/Makefile62
-rw-r--r--keyboards/teensy_lc_onekey/Makefile.3.077
-rw-r--r--keyboards/teensy_lc_onekey/Makefile.3.277
-rw-r--r--keyboards/teensy_lc_onekey/chconf.h524
-rw-r--r--keyboards/teensy_lc_onekey/config.h75
-rw-r--r--keyboards/teensy_lc_onekey/halconf.h187
-rw-r--r--keyboards/teensy_lc_onekey/instructions.md82
-rw-r--r--keyboards/teensy_lc_onekey/keymaps/default/keymap.c32
-rw-r--r--keyboards/teensy_lc_onekey/ld/MKL26Z64.ld105
-rw-r--r--keyboards/teensy_lc_onekey/led.c32
-rw-r--r--keyboards/teensy_lc_onekey/matrix.c163
-rw-r--r--keyboards/teensy_lc_onekey/mcuconf.h55
-rw-r--r--keyboards/teensy_lc_onekey/teensy_lc_onekey.c1
-rw-r--r--keyboards/teensy_lc_onekey/teensy_lc_onekey.h4
m---------lib/chibios0
m---------lib/chibios-contrib0
-rw-r--r--quantum/keycode_config.h2
-rw-r--r--quantum/keymap.h11
-rw-r--r--quantum/keymap_common.c (renamed from quantum/keymap.c)10
-rw-r--r--quantum/matrix.c2
-rw-r--r--quantum/quantum.c2
-rw-r--r--quantum/quantum.h8
-rw-r--r--readme.md3
-rw-r--r--tmk_core/avr.mk185
-rw-r--r--tmk_core/chibios.mk154
-rw-r--r--tmk_core/common.mk36
-rw-r--r--tmk_core/common/action_tapping.c2
-rw-r--r--tmk_core/common/avr/sleep_led.c (renamed from tmk_core/common/sleep_led.c)0
-rw-r--r--tmk_core/common/bootmagic.c7
-rw-r--r--tmk_core/common/chibios/bootloader.c47
-rw-r--r--tmk_core/common/chibios/eeprom.c588
-rw-r--r--tmk_core/common/chibios/printf.c240
-rw-r--r--tmk_core/common/chibios/printf.h111
-rw-r--r--tmk_core/common/chibios/sleep_led.c226
-rw-r--r--tmk_core/common/chibios/suspend.c65
-rw-r--r--tmk_core/common/chibios/timer.c27
-rw-r--r--tmk_core/common/command.c23
-rw-r--r--tmk_core/common/eeconfig.c (renamed from tmk_core/common/avr/eeconfig.c)2
-rw-r--r--tmk_core/common/eeprom.h22
-rw-r--r--tmk_core/common/magic.c4
-rw-r--r--tmk_core/common/print.c8
-rw-r--r--tmk_core/common/print.h10
-rw-r--r--tmk_core/common/progmem.h4
-rw-r--r--tmk_core/common/report.h5
-rw-r--r--tmk_core/common/wait.h8
-rw-r--r--tmk_core/protocol/chibios.mk10
-rw-r--r--tmk_core/protocol/chibios/README.md55
-rw-r--r--tmk_core/protocol/chibios/main.c147
-rw-r--r--tmk_core/protocol/chibios/usb_main.c1372
-rw-r--r--tmk_core/protocol/chibios/usb_main.h139
-rw-r--r--tmk_core/readme.md16
-rw-r--r--tmk_core/rules.mk220
-rw-r--r--tmk_core/tool/chibios/.gitignore2
-rw-r--r--tmk_core/tool/chibios/ch-bootloader-jump.patch116
100 files changed, 10364 insertions, 258 deletions
diff --git a/.gitmodules b/.gitmodules
index e69de29bb2..1576b8dc0b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "lib/chibios"]
+ path = lib/chibios
+ url = https://github.com/ChibiOS/ChibiOS.git
+[submodule "lib/chibios-contrib"]
+ path = lib/chibios-contrib
+ url = https://github.com/ChibiOS/ChibiOS-Contrib.git
diff --git a/.travis.yml b/.travis.yml
index 955f696794..26deac0ceb 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,4 +18,7 @@ addons:
- gcc-avr
- dfu-programmer
- pandoc
-after_success: bash util/travis_compiled_push.sh \ No newline at end of file
+ - gcc-arm-none-eabi
+ - binutils-arm-none-eabi
+ - libnewlib-arm-none-eabi
+after_success: bash util/travis_compiled_push.sh
diff --git a/Makefile b/Makefile
index f9b865b9f8..c285dabad4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,8 @@ ifndef VERBOSE
.SILENT:
endif
+.DEFAULT_GOAL := all
+
space := $(subst ,, )
starting_makefile := $(subst $(space),_SPACE_,$(abspath $(firstword $(MAKEFILE_LIST))))
mkfile_path := $(subst $(space),_SPACE_,$(abspath $(lastword $(MAKEFILE_LIST))))
@@ -41,6 +43,7 @@ endif
TOP_DIR = $(tmk_root)
TMK_DIR = tmk_core
TMK_PATH = $(TOP_DIR)/$(TMK_DIR)
+LIB_PATH = $(TOP_DIR)/lib
QUANTUM_DIR = quantum
QUANTUM_PATH = $(TOP_DIR)/$(QUANTUM_DIR)
@@ -126,6 +129,13 @@ ifdef SUBPROJECT
else
TARGET ?= $(KEYBOARD)_$(KEYMAP)
endif
+BUILD_DIR = .build
+
+# Object files directory
+# To put object files in current directory, use a dot (.), do NOT make
+# this an empty or blank macro!
+OBJDIR = $(BUILD_DIR)/obj_$(TARGET)
+
ifneq ("$(wildcard $(KEYMAP_PATH)/config.h)","")
@@ -143,7 +153,7 @@ endif
SRC += $(KEYBOARD_FILE) \
$(KEYMAP_FILE) \
$(QUANTUM_DIR)/quantum.c \
- $(QUANTUM_DIR)/keymap.c \
+ $(QUANTUM_DIR)/keymap_common.c \
$(QUANTUM_DIR)/keycode_config.c \
$(QUANTUM_DIR)/process_keycode/process_leader.c
@@ -208,8 +218,25 @@ VPATH += $(QUANTUM_PATH)/keymap_extras
VPATH += $(QUANTUM_PATH)/audio
VPATH += $(QUANTUM_PATH)/process_keycode
-include $(TMK_PATH)/protocol/lufa.mk
+
+# We can assume a ChibiOS target When MCU_FAMILY is defined, since it's not used for LUFA
+ifdef MCU_FAMILY
+ PLATFORM=CHIBIOS
+else
+ PLATFORM=AVR
+endif
+
include $(TMK_PATH)/common.mk
+ifeq ($(PLATFORM),AVR)
+ include $(TMK_PATH)/protocol/lufa.mk
+ include $(TMK_PATH)/avr.mk
+else ifeq ($(PLATFORM),CHIBIOS)
+ include $(TMK_PATH)/protocol/chibios.mk
+ include $(TMK_PATH)/chibios.mk
+else
+ $(error Unknown platform)
+endif
+
include $(TMK_PATH)/rules.mk
GIT_VERSION := $(shell git describe --abbrev=6 --dirty --always --tags 2>/dev/null || date +"%Y-%m-%d-%H:%M:%S")
diff --git a/keyboards/infinity_chibios/MEMO.txt b/keyboards/infinity_chibios/MEMO.txt
new file mode 100644
index 0000000000..e2886aa002
--- /dev/null
+++ b/keyboards/infinity_chibios/MEMO.txt
@@ -0,0 +1,385 @@
+flabbergast's TMK/ChibiOS port
+==============================
+2015/10/16
+
+
+Build
+-----
+$ git clone -b chibios https://github.com/flabbergast/tmk_keyboard.git
+
+$ cd tmk_keyboard
+$ git submodule add -f -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+or
+$ cd tmk_keyboard/tmk_core/tool/chibios
+$ git clone -b kinetis https://github.com/flabbergast/ChibiOS.git tmk_core/tool/chibios/chibios
+
+$ cd tmk_keyboard/keyboard/infinity_chibios
+$ make
+
+
+
+
+Chibios Configuration
+---------------------
+halconf.h: for HAL configuration
+ placed in project directory
+ read in chibios/os/hal/hal.mk
+ included in chibios/os/hal/include/hal.h
+mcuconf.h: for MCU configuration
+ placed in project directory
+ included in halconf.h
+
+
+Chibios Term
+------------
+PAL = Port Abstraction Layer
+ palWritePad
+ palReadPad
+ palSetPad
+ chibios/os/hal/include/pal.h
+
+LLD = Low Level Driver
+
+
+Makefile
+--------
+ # <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+ MCU_FAMILY = KINETIS
+ MCU_SERIES = KL2x
+
+ # - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+ # or <this_dir>/ld/
+ MCU_LDSCRIPT = MKL26Z64
+
+ # - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+ MCU_STARTUP = kl2x
+
+ # Board: it should exist either in <chibios>/os/hal/boards/
+ # or <this_dir>/boards
+ BOARD = PJRC_TEENSY_LC
+
+ MCU = cortex-m0
+
+ # ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ ARMV = 6
+
+
+halconf.h
+---------
+
+
+mcuconf.h
+---------
+
+
+chconf.h
+--------
+
+
+ld script
+---------
+--- ../../tmk_core/tool/chibios/chibios/os/common/ports/ARMCMx/compilers/GCC/ld/MKL26Z64.ld 2015-10-15 09:08:58.732904304 +0900
++++ ld/MKL26Z64.ld 2015-10-15 08:48:06.430215496 +0900
+@@ -27,7 +27,8 @@
+ {
+ flash0 : org = 0x00000000, len = 0xc0
+ flashcfg : org = 0x00000400, len = 0x10
+- flash : org = 0x00000410, len = 64k - 0x410
++ flash : org = 0x00000410, len = 62k - 0x410
++ eeprom_emu : org = 0x0000F800, len = 2k
+ ram : org = 0x1FFFF800, len = 8k
+ }
+
+@@ -35,6 +36,10 @@
+ __ram_size__ = LENGTH(ram);
+ __ram_end__ = __ram_start__ + __ram_size__;
+
++__eeprom_workarea_start__ = ORIGIN(eeprom_emu);
++__eeprom_workarea_size__ = LENGTH(eeprom_emu);
++__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__;
++
+ SECTIONS
+ {
+ . = 0;
+
+
+
+Configuration/Startup for Infinity 60%
+--------------------------------------
+Configuration:
+
+
+Clock:
+Inifinity
+ FEI(FLL Engaged Internal) mode with core clock:48MHz, bus clock:48MHz, flash clock:24MHz
+ Clock dividor:
+ SIM_CLKDIV1[OUTDIV1] = 0 divide-by-1 for core clock
+ SIM_CLKDIV1[OUTDIV2] = 0 divide-by-1 for bus clock
+ SIM_CLKDIV1[OUTDIV4] = 1 divide-by-2 for flash clock
+ Internal reference clock:
+ MCG_C1[IREFS] = 1 Internal Reference Select for clock source for FLL
+ MCG_C1[IRCLKEN] = 1 Internal Reference Clock Enable
+ FLL multipilication:
+ MCG_C4[DMX32] = 1
+ MCG_C4[DRST_DRS] = 01 FLL factor 1464 * 32.768kHz = 48MHz
+
+chibios/os/hal/ports/KINETIS/K20x/hal_lld.c
+ k20x_clock_init(): called in __early_init() defined in board.c
+ disable watchdog and configure clock
+
+ configurable macros:
+ KINETIS_NO_INIT: whether init or not
+ KINETIS_MCG_MODE: clock mode
+ KINETIS_MCG_MODE_FEI
+ KINETIS_MCG_MODE_PEE
+ hal/ports/KINETIS/K20x/hal_lld.h
+
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.h
+ PALConfig pal_default_config
+ boardInit()
+ __early_init()
+ macro definitions for board infos, freq and mcu type
+
+chibios/os/hal/boards/FREESCALE_FREEDOM_K20D50M/board.c
+
+USB
+
+
+Startup
+-------
+ common/ports/ARMCMx/GCC/crt0_v[67]m.s
+ Reset_Handler: startup code
+ common/ports/ARMCMx/GCC/crt1.c
+ __core_init(): weak
+ __early_init(): weak
+ __late_init(): weak
+ __default_exit(): weak
+ called from Reset_Handler of crt0
+ common/ports/ARMCMx/GCC/vector.c
+ common/ports/ARMCMx/GCC/ld/*.ld
+
+chibios/os/common/ports/ARMCMx/compilers/GCC/
+├── crt0_v6m.s
+├── crt0_v7m.s
+├── crt1.c
+├── ld
+│   ├── MK20DX128BLDR3.ld
+│   ├── MK20DX128BLDR4.ld
+│   ├── MK20DX128.ld
+│   ├── MK20DX256.ld
+│   ├── MKL25Z128.ld
+│   ├── MKL26Z128.ld
+│   ├── MKL26Z64.ld
+│   └── STM32L476xG.ld
+├── mk
+│   ├── startup_k20x5.mk
+│   ├── startup_k20x7.mk
+│   ├── startup_k20x.mk
+│   ├── startup_kl2x.mk
+│   └── startup_stm32l4xx.mk
+├── rules.ld
+├── rules.mk
+└── vectors.c
+
+chibios/os/hal/
+├── boards
+│   ├── FREESCALE_FREEDOM_K20D50M
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── MCHCK_K20
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_3_1
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── PJRC_TEENSY_LC
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── readme.txt
+│   ├── simulator
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   └── board.mk
+│   ├── ST_NUCLEO_F030R8
+│   │   ├── board.c
+│   │   ├── board.h
+│   │   ├── board.mk
+│   │   └── cfg
+│   │   └── board.chcfg
+├── hal.mk
+├── include
+│   ├── adc.h
+│   ├── can.h
+│   ├── dac.h
+│   ├── ext.h
+│   ├── gpt.h
+│   ├── hal_channels.h
+│   ├── hal_files.h
+│   ├── hal.h
+│   ├── hal_ioblock.h
+│   ├── hal_mmcsd.h
+│   ├── hal_queues.h
+│   ├── hal_streams.h
+│   ├── i2c.h
+│   ├── i2s.h
+│   ├── icu.h
+│   ├── mac.h
+│   ├── mii.h
+│   ├── mmc_spi.h
+│   ├── pal.h
+│   ├── pwm.h
+│   ├── rtc.h
+│   ├── sdc.h
+│   ├── serial.h
+│   ├── serial_usb.h
+│   ├── spi.h
+│   ├── st.h
+│   ├── uart.h
+│   └── usb.h
+├── lib
+│   └── streams
+│   ├── chprintf.c
+│   ├── chprintf.h
+│   ├── memstreams.c
+│   ├── memstreams.h
+│   ├── nullstreams.c
+│   └── nullstreams.h
+├── osal
+│   ├── nil
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   ├── os-less
+│   │   └── ARMCMx
+│   │   ├── osal.c
+│   │   ├── osal.h
+│   │   └── osal.mk
+│   └── rt
+│   ├── osal.c
+│   ├── osal.h
+│   └── osal.mk
+├── ports
+│   ├── AVR
+│   ├── common
+│   │   └── ARMCMx
+│   │   ├── mpu.h
+│   │   ├── nvic.c
+│   │   └── nvic.h
+│   ├── KINETIS
+│   │   ├── K20x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.dox
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   ├── pwm_lld.h
+│   │   │   ├── spi_lld.c
+│   │   │   └── spi_lld.h
+│   │   ├── KL2x
+│   │   │   ├── hal_lld.c
+│   │   │   ├── hal_lld.h
+│   │   │   ├── kinetis_registry.h
+│   │   │   ├── platform.mk
+│   │   │   ├── pwm_lld.c
+│   │   │   └── pwm_lld.h
+│   │   ├── LLD
+│   │   │   ├── adc_lld.c
+│   │   │   ├── adc_lld.h
+│   │   │   ├── ext_lld.c
+│   │   │   ├── ext_lld.h
+│   │   │   ├── gpt_lld.c
+│   │   │   ├── gpt_lld.h
+│   │   │   ├── i2c_lld.c
+│   │   │   ├── i2c_lld.h
+│   │   │   ├── pal_lld.c
+│   │   │   ├── pal_lld.h
+│   │   │   ├── serial_lld.c
+│   │   │   ├── serial_lld.h
+│   │   │   ├── st_lld.c
+│   │   │   ├── st_lld.h
+│   │   │   ├── usb_lld.c
+│   │   │   └── usb_lld.h
+│   │   └── README.md
+│   ├── LPC
+│   ├── simulator
+│   └── STM32
+├── src
+│   ├── adc.c
+│   ├── can.c
+│   ├── dac.c
+│   ├── ext.c
+│   ├── gpt.c
+│   ├── hal.c
+│   ├── hal_mmcsd.c
+│   ├── hal_queues.c
+│   ├── i2c.c
+│   ├── i2s.c
+│   ├── icu.c
+│   ├── mac.c
+│   ├── mmc_spi.c
+│   ├── pal.c
+│   ├── pwm.c
+│   ├── rtc.c
+│   ├── sdc.c
+│   ├── serial.c
+│   ├── serial_usb.c
+│   ├── spi.c
+│   ├── st.c
+│   ├── uart.c
+│   └── usb.c
+└── templates
+ ├── adc_lld.c
+ ├── adc_lld.h
+ ├── can_lld.c
+ ├── can_lld.h
+ ├── dac_lld.c
+ ├── dac_lld.h
+ ├── ext_lld.c
+ ├── ext_lld.h
+ ├── gpt_lld.c
+ ├── gpt_lld.h
+ ├── halconf.h
+ ├── hal_lld.c
+ ├── hal_lld.h
+ ├── i2c_lld.c
+ ├── i2c_lld.h
+ ├── i2s_lld.c
+ ├── i2s_lld.h
+ ├── icu_lld.c
+ ├── icu_lld.h
+ ├── mac_lld.c
+ ├── mac_lld.h
+ ├── mcuconf.h
+ ├── osal
+ │   ├── osal.c
+ │   ├── osal.h
+ │   └── osal.mk
+ ├── pal_lld.c
+ ├── pal_lld.h
+ ├── platform.mk
+ ├── pwm_lld.c
+ ├── pwm_lld.h
+ ├── rtc_lld.c
+ ├── rtc_lld.h
+ ├── sdc_lld.c
+ ├── sdc_lld.h
+ ├── serial_lld.c
+ ├── serial_lld.h
+ ├── spi_lld.c
+ ├── spi_lld.h
+ ├── st_lld.c
+ ├── st_lld.h
+ ├── uart_lld.c
+ ├── uart_lld.h
+ ├── usb_lld.c
+ └── usb_lld.h
diff --git a/keyboards/infinity_chibios/Makefile b/keyboards/infinity_chibios/Makefile
new file mode 100644
index 0000000000..649b43e64d
--- /dev/null
+++ b/keyboards/infinity_chibios/Makefile
@@ -0,0 +1,70 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+# - For Infinity KB, SERIES = K20x
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+# - MK20DX128BLDR4 for Infinity with Kiibohd bootloader
+MCU_LDSCRIPT = MK20DX128BLDR4
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0 and Infinity KB
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x5
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+# - MCHCK_K20 for Infinity KB
+BOARD = MCHCK_K20
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Vector table for application
+# 0x00000000-0x00001000 area is occupied by bootlaoder.*/
+# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB
+OPT_DEFS = -DCORTEX_VTOR_INIT=0x00001000
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+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
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif \ No newline at end of file
diff --git a/keyboards/infinity_chibios/bootloader_defs.h b/keyboards/infinity_chibios/bootloader_defs.h
new file mode 100644
index 0000000000..c67153be60
--- /dev/null
+++ b/keyboards/infinity_chibios/bootloader_defs.h
@@ -0,0 +1 @@
+#define KIIBOHD_BOOTLOADER
diff --git a/keyboards/infinity_chibios/chconf.h b/keyboards/infinity_chibios/chconf.h
new file mode 100644
index 0000000000..b886c383bb
--- /dev/null
+++ b/keyboards/infinity_chibios/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 20
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/infinity_chibios/config.h b/keyboards/infinity_chibios/config.h
new file mode 100644
index 0000000000..cb90222055
--- /dev/null
+++ b/keyboards/infinity_chibios/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 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
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "Infinity keyboard/TMK"
+#define USBSTR_PRODUCT 'I', '\x00', 'n', '\x00', 'f', '\x00', 'i', '\x00', 'n', '\x00', 'i', '\x00', 't', '\x00', 'y', '\x00', ' ', '\x00', 'k', '\x00', 'e', '\x00', 'y', '\x00', 'b', '\x00', 'o', '\x00', 'a', '\x00', 'r', '\x00', 'd', '\x00', '/', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00'
+
+/* key matrix size */
+#define MATRIX_ROWS 9
+#define MATRIX_COLS 7
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* 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)) \
+)
+
+/* Keymap for Infiity prototype */
+#define INFINITY_PROTOTYPE
+
+
+/*
+ * 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
diff --git a/keyboards/infinity_chibios/halconf.h b/keyboards/infinity_chibios/halconf.h
new file mode 100644
index 0000000000..53538de149
--- /dev/null
+++ b/keyboards/infinity_chibios/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB TRUE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/infinity_chibios/infinity_chibios.c b/keyboards/infinity_chibios/infinity_chibios.c
new file mode 100644
index 0000000000..845eda01b0
--- /dev/null
+++ b/keyboards/infinity_chibios/infinity_chibios.c
@@ -0,0 +1,17 @@
+/*
+Copyright 2012,2013 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/>.
+*/
+#include "infinity_chibios.h"
diff --git a/keyboards/infinity_chibios/infinity_chibios.h b/keyboards/infinity_chibios/infinity_chibios.h
new file mode 100644
index 0000000000..a44c68b82d
--- /dev/null
+++ b/keyboards/infinity_chibios/infinity_chibios.h
@@ -0,0 +1,66 @@
+/*
+Copyright 2014 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 KEYMAP_COMMON_H
+#define KEYMAP_COMMON_H
+
+#include "quantum.h"
+
+#ifdef INFINITY_PROTOTYPE
+
+/* Infinity prototype */
+#define KEYMAP( \
+ K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K86, \
+ K51, K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, \
+ K13, K23, K33, K43, K53, K63, K73, K83, K04, K14, K24, K34, K44, \
+ K54, K64, K74, K84, K05, K15, K25, K35, K45, K55, K65, K75, K85, \
+ K06, K16, K26, K36, K46, K56, K66, K76 \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06 }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16 }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26 }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36 }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46 }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56 }, \
+ { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66 }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76 }, \
+ { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 } \
+}
+
+#else
+
+/* Infinity production */
+#define KEYMAP( \
+ K00, K10, K20, K30, K40, K50, K60, K70, K80, K01, K11, K21, K31, K41, K51, \
+ K61, K71, K81, K02, K12, K22, K32, K42, K52, K62, K72, K82, K03, K13, \
+ K23, K33, K43, K53, K63, K73, K83, K04, K14, K24, K34, K44, K54, \
+ K64, K74, K84, K05, K15, K25, K35, K45, K55, K65, K75, K85, K06, \
+ K16, K26, K36, K46, K56, K66, K76, K86 \
+) { \
+ { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06 }, \
+ { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16 }, \
+ { KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26 }, \
+ { KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36 }, \
+ { KC_##K40, KC_##K41, KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46 }, \
+ { KC_##K50, KC_##K51, KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56 }, \
+ { KC_##K60, KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66 }, \
+ { KC_##K70, KC_##K71, KC_##K72, KC_##K73, KC_##K74, KC_##K75, KC_##K76 }, \
+ { KC_##K80, KC_##K81, KC_##K82, KC_##K83, KC_##K84, KC_##K85, KC_##K86 } \
+}
+
+#endif
+
+#endif
diff --git a/keyboards/infinity_chibios/keymaps/default/keymap.c b/keyboards/infinity_chibios/keymaps/default/keymap.c
new file mode 100644
index 0000000000..2acf728494
--- /dev/null
+++ b/keyboards/infinity_chibios/keymaps/default/keymap.c
@@ -0,0 +1,48 @@
+#include "infinity_chibios.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Layer 0: Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp|
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
+ * |-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [0] =
+ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS, GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ 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,FN0, \
+ NO, LGUI,LALT, SPC, RALT,RGUI,NO, NO),
+
+ /* Layer 1: HHKB mode (HHKB Fn)
+ * ,-----------------------------------------------------------.
+ * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
+ * |-----------------------------------------------------------|
+ * | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
+ * |-----------------------------------------------------------|
+ * | | | | | | | +| -|End|PgD|Dow| | |
+ * `-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [1] =
+ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS, BSPC, \
+ TRNS,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,PENT, \
+ TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,TRNS,TRNS, \
+ TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS),
+};
+
+const uint16_t fn_actions[] = {
+ [0] = ACTION_LAYER_MOMENTARY(1),
+};
+
diff --git a/keyboards/infinity_chibios/keymaps/hasu/keymap.c b/keyboards/infinity_chibios/keymaps/hasu/keymap.c
new file mode 100644
index 0000000000..e9a212f0eb
--- /dev/null
+++ b/keyboards/infinity_chibios/keymaps/hasu/keymap.c
@@ -0,0 +1,199 @@
+#include "infinity_chibios.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ /* Layer 0: Default Layer
+ * ,-----------------------------------------------------------.
+ * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp|
+ * |-----------------------------------------------------------|
+ * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \|
+ * |-----------------------------------------------------------|
+ * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter |
+ * |-----------------------------------------------------------|
+ * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0|
+ * |-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [0] =
+ KEYMAP(ESC, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSLS,GRV, \
+ TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSPC, \
+ LCTL,A, S, D, F, G, H, J, K, L, FN3, QUOT,FN6, \
+ FN7, Z, X, C, V, B, N, M, COMM,DOT, FN2, RSFT,FN1, \
+ NO, LGUI,LALT, FN4, FN5, RGUI,NO, NO),
+
+ /* Layer 1: HHKB mode (HHKB Fn)
+ * ,-----------------------------------------------------------.
+ * |Pwr| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Caps | | | | | | | |Psc|Slk|Pus|Up | |Backs|
+ * |-----------------------------------------------------------|
+ * | |VoD|VoU|Mut| | | *| /|Hom|PgU|Lef|Rig|Enter |
+ * |-----------------------------------------------------------|
+ * | | | | | | | +| -|End|PgD|Dow| | |
+ * `-----------------------------------------------------------'
+ * | |Gui|Alt | Space |Alt |Gui| | |
+ * `-----------------------------------------------------------'
+ */
+ [1] =
+ KEYMAP(PWR, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ CAPS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,PSCR,SLCK,PAUS, UP, TRNS,BSPC, \
+ LCTL,VOLD,VOLU,MUTE,TRNS,TRNS,PAST,PSLS,HOME,PGUP,LEFT,RGHT,ENT, \
+ LSFT,TRNS,TRNS,TRNS,TRNS,TRNS,PPLS,PMNS,END, PGDN,DOWN,RSFT,TRNS, \
+ TRNS,LGUI,LALT, TRNS, RALT,RGUI,TRNS,TRNS),
+
+ /* Layer 2: Vi mode[Slash]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab |Hom|PgD|Up |PgU|End|Hom|PgD|PgUlEnd| | | |Backs|
+ * |-----------------------------------------------------------|
+ * |Contro| |Lef|Dow|Rig| |Lef|Dow|Up |Rig| | |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | | |Hom|PgD|PgUlEnd|Fn0|Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui|Alt | Space |Alt |Gui|
+ * `-------------------------------------------'
+ */
+ [2] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ TAB, HOME,PGDN,UP, PGUP,END, HOME,PGDN,PGUP,END, NO, NO, NO, BSPC, \
+ LCTL,NO, LEFT,DOWN,RGHT,NO, LEFT,DOWN,UP, RGHT,NO, NO, ENT, \
+ LSFT,NO, NO, NO, NO, NO, HOME,PGDN,PGUP,END, FN2, RSFT,TRNS, \
+ TRNS,LGUI,LALT, SPC, RALT,RGUI,TRNS,TRNS),
+
+ /* Layer 3: Mouse mode(IJKL)[Semicolon]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab | | | | | |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
+ * |-----------------------------------------------------------|
+ * |Contro| | | | | |Mb2|McL|McD|McR|Fn | |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt | Mb1 |Fn |Fn |
+ * `--------------------------------------------'
+ * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
+ */
+ [3] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ FN8, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,FN9, FN10,FN8, \
+ LCTL,ACL0,ACL1,ACL2,ACL2,NO, NO, MS_L,MS_D,MS_R,FN3, NO, ENT, \
+ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,FN9, FN10,NO, RSFT,TRNS, \
+ TRNS,LGUI,LALT, BTN1, TRNS,TRNS,TRNS,TRNS),
+
+ /* Layer 4: Mouse mode(IJKL)[Space]
+ * ,-----------------------------------------------------------.
+ * |Esc| F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12|Ins|Del|
+ * |-----------------------------------------------------------|
+ * |Tab | | | | | |MwL|MwD|McU|MwU|MwR|Wbk|Wfr|Alt-T|
+ * |-----------------------------------------------------------|
+ * |Contro| | | | | |Mb2|McL|McD|McR|Mb1| |Return |
+ * |-----------------------------------------------------------|
+ * |Shift | | | | |Mb3|Mb2|Mb1|Mb4|Mb5| |Shift | |
+ * `-----------------------------------------------------------'
+ * |Gui |Alt | Mb1 |Fn |Fn |
+ * `--------------------------------------------'
+ * Mc: Mouse Cursor / Mb: Mouse Button / Mw: Mouse Wheel
+ */
+ [4] = \
+ KEYMAP(GRV, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, INS, DEL, \
+ FN8, NO, NO, NO, NO, NO, WH_L,WH_D,MS_U,WH_U,WH_R,BTN4,BTN5,FN8, \
+ LCTL,VOLD,VOLU,MUTE,NO, NO, NO, MS_L,MS_D,MS_R,BTN1,NO, ENT, \
+ LSFT,NO, NO, NO, NO, BTN3,BTN2,BTN1,FN9, FN10,NO, RSFT,TRNS, \
+ TRNS,LGUI,LALT, TRNS, TRNS,TRNS,TRNS,TRNS),
+
+};
+
+/* id for user defined functions */
+enum function_id {
+ LSHIFT_LPAREN,
+};
+
+enum macro_id {
+ HELLO,
+ VOLUP,
+ ALT_TAB,
+};
+
+/*
+ * Fn action definition
+ */
+const uint16_t fn_actions[] = {
+ [0] = ACTION_DEFAULT_LAYER_SET(0), // Default layer(not used)
+ [1] = ACTION_LAYER_TAP_TOGGLE(1), // HHKB layer(toggle with 5 taps)
+ [2] = ACTION_LAYER_TAP_KEY(2, KC_SLASH), // Cursor layer with Slash*
+ [3] = ACTION_LAYER_TAP_KEY(3, KC_SCLN), // Mousekey layer with Semicolon*
+ [4] = ACTION_LAYER_TAP_KEY(4, KC_SPC), // Mousekey layer with Space
+ [5] = ACTION_LAYER_MOMENTARY(4), // Mousekey layer(IJKL)
+ [6] = ACTION_MODS_TAP_KEY(MOD_RCTL, KC_ENT), // RControl with tap Enter
+ [7] = ACTION_MODS_ONESHOT(MOD_LSFT), // Oneshot Shift
+ [8] = ACTION_MACRO(ALT_TAB), // Application switching
+ [9] = ACTION_MODS_KEY(MOD_LALT, KC_LEFT),
+ [10] = ACTION_MODS_KEY(MOD_LALT, KC_RIGHT),
+};
+
+/*
+ * Macro definition
+ */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ switch (id) {
+ case HELLO:
+ return (record->event.pressed ?
+ MACRO( I(0), T(H), T(E), T(L), T(L), W(255), T(O), END ) :
+ MACRO_NONE );
+ case VOLUP:
+ return (record->event.pressed ?
+ MACRO( D(VOLU), U(VOLU), END ) :
+ MACRO_NONE );
+ case ALT_TAB:
+ return (record->event.pressed ?
+ MACRO( D(LALT), D(TAB), END ) :
+ MACRO( U(TAB), END ));
+ }
+ return MACRO_NONE;
+}
+
+
+
+/*
+ * user defined action function
+ */
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+ if (record->event.pressed) dprint("P"); else dprint("R");
+ dprintf("%d", record->tap.count);
+ if (record->tap.interrupted) dprint("i");
+ dprint("\n");
+
+ switch (id) {
+ case LSHIFT_LPAREN:
+ // Shift parentheses example: LShft + tap '('
+ // http://stevelosh.com/blog/2012/10/a-modern-space-cadet/#shift-parentheses
+ // http://geekhack.org/index.php?topic=41989.msg1304899#msg1304899
+ if (record->event.pressed) {
+ if (record->tap.count > 0 && !record->tap.interrupted) {
+ if (record->tap.interrupted) {
+ dprint("tap interrupted\n");
+ register_mods(MOD_BIT(KC_LSHIFT));
+ }
+ } else {
+ register_mods(MOD_BIT(KC_LSHIFT));
+ }
+ } else {
+ if (record->tap.count > 0 && !(record->tap.interrupted)) {
+ add_weak_mods(MOD_BIT(KC_LSHIFT));
+ send_keyboard_report();
+ register_code(KC_9);
+ unregister_code(KC_9);
+ del_weak_mods(MOD_BIT(KC_LSHIFT));
+ send_keyboard_report();
+ record->tap.count = 0; // ad hoc: cancel tap
+ } else {
+ unregister_mods(MOD_BIT(KC_LSHIFT));
+ }
+ }
+ break;
+ }
+}
diff --git a/keyboards/infinity_chibios/led.c b/keyboards/infinity_chibios/led.c
new file mode 100644
index 0000000000..aed66c7c03
--- /dev/null
+++ b/keyboards/infinity_chibios/led.c
@@ -0,0 +1,24 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led) {
+}
diff --git a/keyboards/infinity_chibios/matrix.c b/keyboards/infinity_chibios/matrix.c
new file mode 100644
index 0000000000..2c68ea83ab
--- /dev/null
+++ b/keyboards/infinity_chibios/matrix.c
@@ -0,0 +1,128 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include "hal.h"
+#include "timer.h"
+#include "wait.h"
+#include "print.h"
+#include "matrix.h"
+
+
+/*
+ * Infinity Pinusage:
+ * Column pins are input with internal pull-down. Row pins are output and strobe with high.
+ * Key is high or 1 when it turns on.
+ *
+ * col: { PTD1, PTD2, PTD3, PTD4, PTD5, PTD6, PTD7 }
+ * row: { PTB0, PTB1, PTB2, PTB3, PTB16, PTB17, PTC4, PTC5, PTD0 }
+ */
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+static bool debouncing = false;
+static uint16_t debouncing_time = 0;
+
+
+void matrix_init(void)
+{
+ /* Column(sense) */
+ palSetPadMode(GPIOD, 1, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 2, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 3, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 4, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 5, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 6, PAL_MODE_INPUT_PULLDOWN);
+ palSetPadMode(GPIOD, 7, PAL_MODE_INPUT_PULLDOWN);
+
+ /* Row(strobe) */
+ palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 3, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 16, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOB, 17, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 4, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOC, 5, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPadMode(GPIOD, 0, PAL_MODE_OUTPUT_PUSHPULL);
+
+ memset(matrix, 0, MATRIX_ROWS);
+ memset(matrix_debouncing, 0, MATRIX_ROWS);
+}
+
+uint8_t matrix_scan(void)
+{
+ for (int row = 0; row < MATRIX_ROWS; row++) {
+ matrix_row_t data = 0;
+
+ // strobe row
+ switch (row) {
+ case 0: palSetPad(GPIOB, 0); break;
+ case 1: palSetPad(GPIOB, 1); break;
+ case 2: palSetPad(GPIOB, 2); break;
+ case 3: palSetPad(GPIOB, 3); break;
+ case 4: palSetPad(GPIOB, 16); break;
+ case 5: palSetPad(GPIOB, 17); break;
+ case 6: palSetPad(GPIOC, 4); break;
+ case 7: palSetPad(GPIOC, 5); break;
+ case 8: palSetPad(GPIOD, 0); break;
+ }
+
+ wait_us(1); // need wait to settle pin state
+
+ // read col data
+ data = (palReadPort(GPIOD)>>1);
+
+ // un-strobe row
+ switch (row) {
+ case 0: palClearPad(GPIOB, 0); break;
+ case 1: palClearPad(GPIOB, 1); break;
+ case 2: palClearPad(GPIOB, 2); break;
+ case 3: palClearPad(GPIOB, 3); break;
+ case 4: palClearPad(GPIOB, 16); break;
+ case 5: palClearPad(GPIOB, 17); break;
+ case 6: palClearPad(GPIOC, 4); break;
+ case 7: palClearPad(GPIOC, 5); break;
+ case 8: palClearPad(GPIOD, 0); break;
+ }
+
+ if (matrix_debouncing[row] != data) {
+ matrix_debouncing[row] = data;
+ debouncing = true;
+ debouncing_time = timer_read();
+ }
+ }
+
+ if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) {
+ for (int row = 0; row < MATRIX_ROWS; row++) {
+ matrix[row] = matrix_debouncing[row];
+ }
+ debouncing = false;
+ }
+ return 1;
+}
+
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & (1<<col));
+}
+
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ xprintf("\nr/c 01234567\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ xprintf("%02X: ");
+ matrix_row_t data = matrix_get_row(row);
+ for (int col = 0; col < MATRIX_COLS; col++) {
+ if (data & (1<<col))
+ xprintf("1");
+ else
+ xprintf("0");
+ }
+ xprintf("\n");
+ }
+}
diff --git a/keyboards/infinity_chibios/mcuconf.h b/keyboards/infinity_chibios/mcuconf.h
new file mode 100644
index 0000000000..66b6ce25de
--- /dev/null
+++ b/keyboards/infinity_chibios/mcuconf.h
@@ -0,0 +1,55 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define K20x_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+
+/* Select the MCU clocking mode below by enabling the appropriate block. */
+
+#define KINETIS_NO_INIT FALSE
+
+/* FEI mode - 48 MHz with internal 32.768 kHz crystal */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_FEI
+#define KINETIS_MCG_FLL_DMX32 1 /* Fine-tune for 32.768 kHz */
+#define KINETIS_MCG_FLL_DRS 1 /* 1464x FLL factor */
+#define KINETIS_SYSCLK_FREQUENCY 47972352UL /* 32.768 kHz * 1464 (~48 MHz) */
+#define KINETIS_CLKDIV1_OUTDIV1 1
+#define KINETIS_CLKDIV1_OUTDIV2 1
+#define KINETIS_CLKDIV1_OUTDIV4 2
+#define KINETIS_BUSCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY
+#define KINETIS_FLASHCLK_FREQUENCY KINETIS_SYSCLK_FREQUENCY/2
+
+/*
+ * SERIAL driver system settings.
+ */
+#define KINETIS_SERIAL_USE_UART0 TRUE
+
+/*
+ * USB driver settings
+ */
+#define KINETIS_USB_USE_USB0 TRUE
+/* Need to redefine this, since the default is for K20x */
+/* This is for Teensy LC; you should comment it out (or change to 5)
+ * for Teensy 3.x */
+#define KINETIS_USB_USB0_IRQ_PRIORITY 2
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/planck/out.txt b/keyboards/planck/out.txt
new file mode 100644
index 0000000000..644a6a7774
--- /dev/null
+++ b/keyboards/planck/out.txt
@@ -0,0 +1,66 @@
+-------- begin --------
+avr-gcc.exe (AVR_8_bit_GNU_Toolchain_3.5.0_1662) 4.9.2
+Copyright (C) 2014 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+Compiling: ../../keyboards/planck/planck.c [OK]
+Compiling: ../../keyboards/planck/keymaps/experimental/keymap.c [WARNINGS]
+ |
+ | ../../keyboards/planck/keymaps/experimental/keymap.c: In function 'action_get_macro':
+ | ../../keyboards/planck/keymaps/experimental/keymap.c:227:17: warning: implicit declaration of function 'breathing_speed_set' [-Wimplicit-function-declaration]
+ | breathing_speed_set(2);
+ | ^
+ | ../../keyboards/planck/keymaps/experimental/keymap.c:228:17: warning: implicit declaration of function 'breathing_pulse' [-Wimplicit-function-declaration]
+ | breathing_pulse();
+ | ^
+ |
+Compiling: ../../quantum/quantum.c [OK]
+Compiling: ../../quantum/keymap.c [OK]
+Compiling: ../../quantum/keycode_config.c [OK]
+Compiling: ../../quantum/matrix.c [OK]
+Compiling: ../../quantum/audio/audio.c [OK]
+Compiling: ../../quantum/audio/voices.c [OK]
+Compiling: ../../quantum/audio/luts.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/lufa.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/descriptor.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Common/HIDParser.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/ConfigDescriptors.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/DeviceStandardReq.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/Events.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/HostStandardReq.c [OK]
+Compiling: ../../tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Core/USBTask.c [OK]
+Compiling: ../../tmk_core/common/host.c [OK]
+Compiling: ../../tmk_core/common/keyboard.c [OK]
+Compiling: ../../tmk_core/common/action.c [OK]
+Compiling: ../../tmk_core/common/action_tapping.c [OK]
+Compiling: ../../tmk_core/common/action_macro.c [OK]
+Compiling: ../../tmk_core/common/action_layer.c [OK]
+Compiling: ../../tmk_core/common/action_util.c [OK]
+Compiling: ../../tmk_core/common/print.c [OK]
+Compiling: ../../tmk_core/common/debug.c [OK]
+Compiling: ../../tmk_core/common/util.c [OK]
+Compiling: ../../tmk_core/common/avr/suspend.c [OK]
+Assembling: ../../tmk_core/common/avr/xprintf.S [OK]
+Compiling: ../../tmk_core/common/avr/timer.c [OK]
+Compiling: ../../tmk_core/common/avr/bootloader.c [OK]
+Compiling: ../../tmk_core/common/magic.c [OK]
+Compiling: ../../tmk_core/common/avr/eeconfig.c [OK]
+Compiling: ../../tmk_core/common/mousekey.c [OK]
+Compiling: ../../tmk_core/common/command.c [OK]
+Compiling: ../../tmk_core/common/backlight.c [OK]
+Linking: .build/planck_experimental.elf [ERRORS]
+ |
+ | .build/obj_planck_experimental/keyboards/planck/keymaps/experimental/keymap.o: In function `action_get_macro':
+ | C:\Users\Fred Wales\Documents\Programming\qmk_firmware\keyboards\planck/../../keyboards/planck/keymaps/experimental/keymap.c:240: undefined reference to `breathing_speed_set'
+ | C:\Users\Fred Wales\Documents\Programming\qmk_firmware\keyboards\planck/../../keyboards/planck/keymaps/experimental/keymap.c:241: undefined reference to `breathing_pulse'
+ | collect2.exe: error: ld returned 1 exit status
+ |
diff --git a/keyboards/stm32_f072_onekey/Makefile b/keyboards/stm32_f072_onekey/Makefile
new file mode 100644
index 0000000000..24abcb0e09
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/Makefile
@@ -0,0 +1,50 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+MCU_FAMILY = STM32
+MCU_SERIES = STM32F0xx
+# linker script to use
+# it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+MCU_LDSCRIPT = STM32F072xB
+# startup code to use
+# is should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+MCU_STARTUP = stm32f0xx
+# it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+BOARD = ST_STM32F072B_DISCOVERY
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m0
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ARMV = 6
+# If you want to be able to jump to bootloader from firmware on STM32 MCUs,
+# set the correct BOOTLOADER_ADDRESS. Either set it here, or define it in
+# ./bootloader_defs.h or in ./boards/<FOO>/bootloader_defs.h (if you have
+# a custom board definition that you plan to reuse).
+# If you're not setting it here, leave it commented out.
+# It is chip dependent, the correct number can be looked up here (page 175):
+# http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+# This also requires a patch to chibios:
+# <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+#STM32_BOOTLOADER_ADDRESS = 0x1FFFC800
+
+# 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
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/stm32_f072_onekey/bootloader_defs.h b/keyboards/stm32_f072_onekey/bootloader_defs.h
new file mode 100644
index 0000000000..02c48c4e6d
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/bootloader_defs.h
@@ -0,0 +1,7 @@
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up here (page 175):
+ * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+ * This also requires a patch to chibios:
+ * <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+ */
+#define STM32_BOOTLOADER_ADDRESS 0x1FFFC800
diff --git a/keyboards/stm32_f072_onekey/chconf.h b/keyboards/stm32_f072_onekey/chconf.h
new file mode 100644
index 0000000000..99fa8ce398
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 10000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 2
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 0
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE FALSE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP FALSE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS FALSE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/stm32_f072_onekey/config.h b/keyboards/stm32_f072_onekey/config.h
new file mode 100644
index 0000000000..bb5251e1de
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/config.h
@@ -0,0 +1,76 @@
+/*
+Copyright 2015 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
+
+#include "config_common.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "ChibiOS TMK test"
+#define USBSTR_PRODUCT 'C', '\x00', 'h', '\x00', 'i', '\x00', 'b', '\x00', 'i', '\x00', 'O', '\x00', 'S', '\x00', ' ', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', 't', '\x00', 'e', '\x00', 's', '\x00', 't', '\x00'
+#define DESCRIPTION "TMK keyboard firmware over ChibiOS"
+
+/* key matrix size */
+#define MATRIX_ROWS 1
+#define MATRIX_COLS 1
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* 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
diff --git a/keyboards/stm32_f072_onekey/halconf.h b/keyboards/stm32_f072_onekey/halconf.h
new file mode 100644
index 0000000000..1a450d6327
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/stm32_f072_onekey/keymaps/default/keymap.c b/keyboards/stm32_f072_onekey/keymaps/default/keymap.c
new file mode 100644
index 0000000000..6c48149f83
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/keymaps/default/keymap.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2012,2013 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/>.
+*/
+
+#include "stm32_f072_onekey.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ {{KC_CAPS}}, // test with KC_CAPS, KC_A, KC_BTLD
+};
+
+const uint16_t fn_actions[] = {
+};
diff --git a/keyboards/stm32_f072_onekey/led.c b/keyboards/stm32_f072_onekey/led.c
new file mode 100644
index 0000000000..18edb8ba89
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/led.c
@@ -0,0 +1,34 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+ (void)usb_led;
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ palSetPadMode(GPIOC, GPIOC_LED_GREEN, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPad(GPIOC, GPIOC_LED_GREEN);
+ } else {
+ // Hi-Z
+ palSetPadMode(GPIOC, GPIOC_LED_GREEN, PAL_MODE_INPUT);
+ }
+}
diff --git a/keyboards/stm32_f072_onekey/matrix.c b/keyboards/stm32_f072_onekey/matrix.c
new file mode 100644
index 0000000000..a05b38cd4c
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/matrix.c
@@ -0,0 +1,163 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+#define LED_ON() do { palSetPad(GPIOC, GPIOC_LED_BLUE) ;} while (0)
+#define LED_OFF() do { palClearPad(GPIOC, GPIOC_LED_BLUE); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOC, GPIOC_LED_BLUE); } while (0)
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+ // don't need pullup/down, since it's pulled down in hardware
+ palSetPadMode(GPIOA, GPIOA_BUTTON, PAL_MODE_INPUT);
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(GPIOA, GPIOA_BUTTON)==PAL_LOW) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ // switch (row) {
+ // case 0:
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_OUTPUT_PUSHPULL);
+ // palSetPad(GPIOA, GPIOA_PIN10, PAL_LOW);
+ // break;
+ // }
+}
diff --git a/keyboards/stm32_f072_onekey/mcuconf.h b/keyboards/stm32_f072_onekey/mcuconf.h
new file mode 100644
index 0000000000..3d877aaa2b
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/mcuconf.h
@@ -0,0 +1,171 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+/*
+ * STM32F0xx drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 3...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+#define STM32F0xx_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+#define STM32_HSI_ENABLED TRUE
+#define STM32_HSI14_ENABLED TRUE
+#define STM32_HSI48_ENABLED FALSE
+#define STM32_LSI_ENABLED TRUE
+#define STM32_HSE_ENABLED FALSE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSI_DIV2
+#define STM32_PREDIV_VALUE 1
+#define STM32_PLLMUL_VALUE 12
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE STM32_PPRE_DIV1
+#define STM32_ADCSW STM32_ADCSW_HSI14
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_ADCSW STM32_ADCSW_HSI14
+#define STM32_USBSW STM32_USBSW_HSI48
+#define STM32_CECSW STM32_CECSW_HSI
+#define STM32_I2C1SW STM32_I2C1SW_HSI
+#define STM32_USART1SW STM32_USART1SW_PCLK
+#define STM32_RTCSEL STM32_RTCSEL_LSI
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_IRQ_PRIORITY 2
+#define STM32_ADC_ADC1_DMA_IRQ_PRIORITY 2
+
+/*
+ * EXT driver system settings.
+ */
+#define STM32_EXT_EXTI0_1_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI2_3_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI4_15_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 3
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 3
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM14 FALSE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 2
+#define STM32_GPT_TIM2_IRQ_PRIORITY 2
+#define STM32_GPT_TIM3_IRQ_PRIORITY 2
+#define STM32_GPT_TIM14_IRQ_PRIORITY 2
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_IRQ_PRIORITY 3
+#define STM32_I2C_I2C2_IRQ_PRIORITY 3
+#define STM32_I2C_USE_DMA TRUE
+#define STM32_I2C_I2C1_DMA_PRIORITY 1
+#define STM32_I2C_I2C2_DMA_PRIORITY 1
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 3
+#define STM32_ICU_TIM2_IRQ_PRIORITY 3
+#define STM32_ICU_TIM3_IRQ_PRIORITY 3
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 3
+#define STM32_PWM_TIM2_IRQ_PRIORITY 3
+#define STM32_PWM_TIM3_IRQ_PRIORITY 3
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 3
+#define STM32_SERIAL_USART2_PRIORITY 3
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 2
+#define STM32_SPI_SPI2_IRQ_PRIORITY 2
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 2
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USART1_IRQ_PRIORITY 3
+#define STM32_UART_USART2_IRQ_PRIORITY 3
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_USB1 TRUE
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 3
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/stm32_f072_onekey/stm32_f072_onekey.c b/keyboards/stm32_f072_onekey/stm32_f072_onekey.c
new file mode 100644
index 0000000000..820d062ffd
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/stm32_f072_onekey.c
@@ -0,0 +1 @@
+#include "stm32_f072_onekey.h"
diff --git a/keyboards/stm32_f072_onekey/stm32_f072_onekey.h b/keyboards/stm32_f072_onekey/stm32_f072_onekey.h
new file mode 100644
index 0000000000..1f798c8255
--- /dev/null
+++ b/keyboards/stm32_f072_onekey/stm32_f072_onekey.h
@@ -0,0 +1,5 @@
+#ifndef STM32_F072_ONEKEY_H
+#define STM32_F072_ONEKEY_H
+#include "quantum.h"
+#endif
+
diff --git a/keyboards/stm32_f103_onekey/Makefile b/keyboards/stm32_f103_onekey/Makefile
new file mode 100644
index 0000000000..5c1793c867
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/Makefile
@@ -0,0 +1,64 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+# GENERIC STM32F103C8T6 board - stm32duino bootloader
+OPT_DEFS = -DCORTEX_VTOR_INIT=0x2000
+MCU_LDSCRIPT = STM32F103x8_stm32duino_bootloader
+BOARD = GENERIC_STM32_F103
+
+# GENERIC STM32F103C8T6 board - no bootloader (programmer over serial or SWD)
+# OPT_DEFS =
+# MCU_LDSCRIPT = STM32F103x8
+# BOARD = GENERIC_STM32_F103
+
+# MAPLE MINI
+# OPT_DEFS = -DCORTEX_VTOR_INIT=0x5000
+# MCU_LDSCRIPT = STM32F103xB_maplemini_bootloader
+# BOARD = MAPLEMINI_STM32_F103
+
+## chip/board settings
+# the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+MCU_FAMILY = STM32
+MCU_SERIES = STM32F1xx
+# linker script to use
+# it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# startup code to use
+# is should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+MCU_STARTUP = stm32f1xx
+# it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m3
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+ARMV = 7
+# If you want to be able to jump to bootloader from firmware on STM32 MCUs,
+# set the correct BOOTLOADER_ADDRESS. Either set it here, or define it in
+# ./bootloader_defs.h or in ./boards/<FOO>/bootloader_defs.h (if you have
+# a custom board definition that you plan to reuse).
+# If you're not setting it here, leave it commented out.
+# It is chip dependent, the correct number can be looked up here (page 175):
+# http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+# This also requires a patch to chibios:
+# <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+#STM32_BOOTLOADER_ADDRESS = 0x1FFFC800
+
+# Build Options
+# comment out to disable the options.
+#
+#BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+## BOOTMAGIC is not supported on STM32 chips yet.
+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
+SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.c b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.c
new file mode 100644
index 0000000000..31319ef575
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.c
@@ -0,0 +1,49 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+
+/**
+ * @brief PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ * This variable is used by the HAL when initializing the PAL driver.
+ */
+#if HAL_USE_PAL || defined(__DOXYGEN__)
+const PALConfig pal_default_config =
+{
+ {VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH},
+ {VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH},
+ {VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH},
+ {VAL_GPIODODR, VAL_GPIODCRL, VAL_GPIODCRH},
+ {VAL_GPIOEODR, VAL_GPIOECRL, VAL_GPIOECRH},
+};
+#endif
+
+/*
+ * Early initialization code.
+ * This initialization must be performed just after stack setup and before
+ * any other initialization.
+ */
+void __early_init(void) {
+
+ stm32_clock_init();
+}
+
+/*
+ * Board-specific initialization code.
+ */
+void boardInit(void) {
+}
diff --git a/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.h b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.h
new file mode 100644
index 0000000000..7253e77826
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.h
@@ -0,0 +1,166 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+/*
+ * Setup for a Generic STM32F103 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_GENERIC_STM32_F103
+#define BOARD_NAME "Generic STM32F103x board"
+
+/*
+ * Board frequencies.
+ */
+#define STM32_LSECLK 32768
+#define STM32_HSECLK 8000000
+
+/*
+ * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h.
+ */
+#define STM32F103xB
+
+/*
+ * IO pins assignments
+ */
+
+/* on-board */
+
+#define GPIOC_LED 13
+#define GPIOD_OSC_IN 0
+#define GPIOD_OSC_OUT 1
+
+/* In case your board has a "USB enable" hardware
+ controlled by a pin, define it here. (It could be just
+ a 1.5k resistor connected to D+ line.)
+*/
+/*
+#define GPIOB_USB_DISC 10
+*/
+
+/*
+ * I/O ports initial setup, this configuration is established soon after reset
+ * in the initialization code.
+ *
+ * The digits have the following meaning:
+ * 0 - Analog input.
+ * 1 - Push Pull output 10MHz.
+ * 2 - Push Pull output 2MHz.
+ * 3 - Push Pull output 50MHz.
+ * 4 - Digital input.
+ * 5 - Open Drain output 10MHz.
+ * 6 - Open Drain output 2MHz.
+ * 7 - Open Drain output 50MHz.
+ * 8 - Digital input with PullUp or PullDown resistor depending on ODR.
+ * 9 - Alternate Push Pull output 10MHz.
+ * A - Alternate Push Pull output 2MHz.
+ * B - Alternate Push Pull output 50MHz.
+ * C - Reserved.
+ * D - Alternate Open Drain output 10MHz.
+ * E - Alternate Open Drain output 2MHz.
+ * F - Alternate Open Drain output 50MHz.
+ * Please refer to the STM32 Reference Manual for details.
+ */
+
+/*
+ * Port A setup.
+ * Everything input with pull-up except:
+ * PA2 - Alternate output (USART2 TX).
+ * PA3 - Normal input (USART2 RX).
+ * PA9 - Alternate output (USART1 TX).
+ * PA10 - Normal input (USART1 RX).
+ */
+#define VAL_GPIOACRL 0x88884B88 /* PA7...PA0 */
+#define VAL_GPIOACRH 0x888884B8 /* PA15...PA8 */
+#define VAL_GPIOAODR 0xFFFFFFFF
+
+/*
+ * Port B setup.
+ * Everything input with pull-up except:
+ * PB10 - Push Pull output (USB switch).
+ */
+#define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */
+#define VAL_GPIOBCRH 0x88888388 /* PB15...PB8 */
+#define VAL_GPIOBODR 0xFFFFFFFF
+
+/*
+ * Port C setup.
+ * Everything input with pull-up except:
+ * PC13 - Push Pull output (LED).
+ */
+#define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */
+#define VAL_GPIOCCRH 0x88388888 /* PC15...PC8 */
+#define VAL_GPIOCODR 0xFFFFFFFF
+
+/*
+ * Port D setup.
+ * Everything input with pull-up except:
+ * PD0 - Normal input (XTAL).
+ * PD1 - Normal input (XTAL).
+ */
+#define VAL_GPIODCRL 0x88888844 /* PD7...PD0 */
+#define VAL_GPIODCRH 0x88888888 /* PD15...PD8 */
+#define VAL_GPIODODR 0xFFFFFFFF
+
+/*
+ * Port E setup.
+ * Everything input with pull-up except:
+ */
+#define VAL_GPIOECRL 0x88888888 /* PE7...PE0 */
+#define VAL_GPIOECRH 0x88888888 /* PE15...PE8 */
+#define VAL_GPIOEODR 0xFFFFFFFF
+
+/*
+ * USB bus activation macro, required by the USB driver.
+ */
+/* The point is that most of the generic STM32F103* boards
+ have a 1.5k resistor connected on one end to the D+ line
+ and on the other end to some pin. Or even a slightly more
+ complicated "USB enable" circuit, controlled by a pin.
+ That should go here.
+
+ However on some boards (e.g. one that I have), there's no
+ such hardware. In which case it's better to not do anything.
+*/
+/*
+#define usb_lld_connect_bus(usbp) palClearPad(GPIOB, GPIOB_USB_DISC)
+*/
+#define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT);
+
+/*
+ * USB bus de-activation macro, required by the USB driver.
+ */
+/*
+#define usb_lld_disconnect_bus(usbp) palSetPad(GPIOB, GPIOB_USB_DISC)
+*/
+#define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12);
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+ void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
+
+#endif /* _BOARD_H_ */
diff --git a/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.mk b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.mk
new file mode 100644
index 0000000000..d692c0ee46
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(KEYBOARD_PATH)/boards/GENERIC_STM32_F103/board.c
+
+# Required include directories
+BOARDINC = $(KEYBOARD_PATH)/boards/GENERIC_STM32_F103
diff --git a/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/mini_stm32_mapping.png b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/mini_stm32_mapping.png
new file mode 100644
index 0000000000..c44a7d9ebc
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/mini_stm32_mapping.png
Binary files differ
diff --git a/keyboards/stm32_f103_onekey/boards/maple_mini_mapping.png b/keyboards/stm32_f103_onekey/boards/maple_mini_mapping.png
new file mode 100644
index 0000000000..12cfa81db2
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/boards/maple_mini_mapping.png
Binary files differ
diff --git a/keyboards/stm32_f103_onekey/bootloader_defs.h b/keyboards/stm32_f103_onekey/bootloader_defs.h
new file mode 100644
index 0000000000..0f45203cb6
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/bootloader_defs.h
@@ -0,0 +1,10 @@
+/* Address for jumping to bootloader on STM32 chips. */
+/* It is chip dependent, the correct number can be looked up here (page 175):
+ * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf
+ * This also requires a patch to chibios:
+ * <tmk_dir>/tmk_core/tool/chibios/ch-bootloader-jump.patch
+ */
+
+// STM32F103* does NOT have an USB bootloader in ROM (only serial),
+// so setting anything here does not make much sense
+// #define STM32_BOOTLOADER_ADDRESS 0x1FFFC800
diff --git a/keyboards/stm32_f103_onekey/chconf.h b/keyboards/stm32_f103_onekey/chconf.h
new file mode 100644
index 0000000000..dfb1f9dfb9
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 16
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 2000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 2
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 0
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT FALSE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS FALSE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK FALSE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS FALSE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS FALSE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK FALSE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS FALSE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/stm32_f103_onekey/config.h b/keyboards/stm32_f103_onekey/config.h
new file mode 100644
index 0000000000..19b14fe61a
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 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
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "ChibiOS TMK test"
+#define USBSTR_PRODUCT 'C', '\x00', 'h', '\x00', 'i', '\x00', 'b', '\x00', 'i', '\x00', 'O', '\x00', 'S', '\x00', ' ', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', 't', '\x00', 'e', '\x00', 's', '\x00', 't', '\x00'
+#define DESCRIPTION "TMK keyboard firmware over ChibiOS"
+
+/* key matrix size */
+#define MATRIX_ROWS 1
+#define MATRIX_COLS 1
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* 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
diff --git a/keyboards/stm32_f103_onekey/flash.sh b/keyboards/stm32_f103_onekey/flash.sh
new file mode 100755
index 0000000000..15501dfa57
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/flash.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+Arduino_STM32_usb_hid/tools/linux/maple_upload ttyACM0 2 1EAF:0003 build/ch.bin
diff --git a/keyboards/stm32_f103_onekey/halconf.h b/keyboards/stm32_f103_onekey/halconf.h
new file mode 100644
index 0000000000..1a450d6327
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/halconf.h
@@ -0,0 +1,353 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* ADC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
+#define ADC_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define ADC_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* CAN driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Sleep mode related APIs inclusion switch.
+ */
+#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__)
+#define CAN_USE_SLEEP_MODE TRUE
+#endif
+
+/*===========================================================================*/
+/* I2C driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables the mutual exclusion APIs on the I2C bus.
+ */
+#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define I2C_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* MAC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__)
+#define MAC_USE_ZERO_COPY FALSE
+#endif
+
+/**
+ * @brief Enables an event sources for incoming packets.
+ */
+#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__)
+#define MAC_USE_EVENTS TRUE
+#endif
+
+/*===========================================================================*/
+/* MMC_SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ * This option is recommended also if the SPI driver does not
+ * use a DMA channel and heavily loads the CPU.
+ */
+#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__)
+#define MMC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SDC driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Number of initialization attempts before rejecting the card.
+ * @note Attempts are performed at 10mS intervals.
+ */
+#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__)
+#define SDC_INIT_RETRY 100
+#endif
+
+/**
+ * @brief Include support for MMC cards.
+ * @note MMC support is not yet implemented so this option must be kept
+ * at @p FALSE.
+ */
+#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__)
+#define SDC_MMC_SUPPORT FALSE
+#endif
+
+/**
+ * @brief Delays insertions.
+ * @details If enabled this options inserts delays into the MMC waiting
+ * routines releasing some extra CPU time for the threads with
+ * lower priority, this may slow down the driver a bit however.
+ */
+#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__)
+#define SDC_NICE_WAITING TRUE
+#endif
+
+/*===========================================================================*/
+/* SERIAL driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Default bit rate.
+ * @details Configuration parameter, this is the baud rate selected for the
+ * default configuration.
+ */
+#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__)
+#define SERIAL_DEFAULT_BITRATE 38400
+#endif
+
+/**
+ * @brief Serial buffers size.
+ * @details Configuration parameter, you can change the depth of the queue
+ * buffers depending on the requirements of your application.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_BUFFERS_SIZE 16
+#endif
+
+/*===========================================================================*/
+/* SERIAL_USB driver related setting. */
+/*===========================================================================*/
+
+/**
+ * @brief Serial over USB buffers size.
+ * @details Configuration parameter, the buffer size must be a multiple of
+ * the USB data endpoint maximum packet size.
+ * @note The default is 64 bytes for both the transmission and receive
+ * buffers.
+ */
+#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__)
+#define SERIAL_USB_BUFFERS_SIZE 256
+#endif
+
+/*===========================================================================*/
+/* SPI driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)
+#define SPI_USE_WAIT TRUE
+#endif
+
+/**
+ * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
+#define SPI_USE_MUTUAL_EXCLUSION TRUE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/stm32_f103_onekey/keymaps/default/keymap.c b/keyboards/stm32_f103_onekey/keymaps/default/keymap.c
new file mode 100644
index 0000000000..c3b0f08403
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/keymaps/default/keymap.c
@@ -0,0 +1,25 @@
+/*
+Copyright 2012,2013 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/>.
+*/
+
+#include "stm32_f103_onekey.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ {{KC_CAPS}}, // test with KC_CAPS, KC_A, KC_BTLD
+};
+
+const uint16_t fn_actions[] = {
+};
diff --git a/keyboards/stm32_f103_onekey/ld/STM32F103x8_stm32duino_bootloader.ld b/keyboards/stm32_f103_onekey/ld/STM32F103x8_stm32duino_bootloader.ld
new file mode 100644
index 0000000000..00613328ed
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/ld/STM32F103x8_stm32duino_bootloader.ld
@@ -0,0 +1,88 @@
+/*
+ ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/*
+ * ST32F103xB memory setup for use with the maplemini bootloader.
+ * You will have to
+ * #define CORTEX_VTOR_INIT 0x5000
+ * in your projects chconf.h
+ */
+MEMORY
+{
+ flash0 : org = 0x08002000, len = 128k - 0x2000
+ flash1 : org = 0x00000000, len = 0
+ flash2 : org = 0x00000000, len = 0
+ flash3 : org = 0x00000000, len = 0
+ flash4 : org = 0x00000000, len = 0
+ flash5 : org = 0x00000000, len = 0
+ flash6 : org = 0x00000000, len = 0
+ flash7 : org = 0x00000000, len = 0
+ ram0 : org = 0x20000000, len = 20k
+ ram1 : org = 0x00000000, len = 0
+ ram2 : org = 0x00000000, len = 0
+ ram3 : org = 0x00000000, len = 0
+ ram4 : org = 0x00000000, len = 0
+ ram5 : org = 0x00000000, len = 0
+ ram6 : org = 0x00000000, len = 0
+ ram7 : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/keyboards/stm32_f103_onekey/led.c b/keyboards/stm32_f103_onekey/led.c
new file mode 100644
index 0000000000..f5c55f7d9b
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/led.c
@@ -0,0 +1,43 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "hal.h"
+#include "led.h"
+
+
+void led_set(uint8_t usb_led)
+{
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ /* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+ palClearPad(GPIOC, 13);
+#endif
+ /* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ palSetPad(GPIOB, 1);
+#endif
+ } else {
+ /* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+ palSetPad(GPIOC, 13);
+#endif
+ /* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ palClearPad(GPIOB,1);
+#endif
+ }
+}
diff --git a/keyboards/stm32_f103_onekey/matrix.c b/keyboards/stm32_f103_onekey/matrix.c
new file mode 100644
index 0000000000..ea9d8d057b
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/matrix.c
@@ -0,0 +1,177 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+/* generic STM32F103C8T6 board */
+#ifdef BOARD_GENERIC_STM32_F103
+#define LED_ON() do { palClearPad(GPIOC, GPIOC_LED) ;} while (0)
+#define LED_OFF() do { palSetPad(GPIOC, GPIOC_LED); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOC, GPIOC_LED); } while (0)
+#endif
+
+/* Maple Mini */
+#ifdef BOARD_MAPLEMINI_STM32_F103
+#define LED_ON() do { palSetPad(GPIOB, 1) ;} while (0)
+#define LED_OFF() do { palClearPad(GPIOB, 1); } while (0)
+#define LED_TGL() do { palTogglePad(GPIOB, 1); } while (0)
+#endif
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+#ifdef BOARD_MAPLEMINI_STM32_F103
+ // don't need pullup/down, since it's pulled down in hardware
+ palSetPadMode(GPIOB, 8, PAL_MODE_INPUT);
+#else
+ palSetPadMode(GPIOB, 8, PAL_MODE_INPUT_PULLDOWN);
+#endif
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(GPIOB, 8)==PAL_LOW) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ // switch (row) {
+ // case 0:
+ // palSetPadMode(GPIOA, GPIOA_PIN10, PAL_MODE_OUTPUT_PUSHPULL);
+ // palSetPad(GPIOA, GPIOA_PIN10, PAL_LOW);
+ // break;
+ // }
+}
diff --git a/keyboards/stm32_f103_onekey/mcuconf.h b/keyboards/stm32_f103_onekey/mcuconf.h
new file mode 100644
index 0000000000..626332a6aa
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/mcuconf.h
@@ -0,0 +1,209 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define STM32F103_MCUCONF
+
+/*
+ * STM32F103 drivers configuration.
+ * The following settings override the default settings present in
+ * the various device driver implementation headers.
+ * Note that the settings for each driver only have effect if the whole
+ * driver is enabled in halconf.h.
+ *
+ * IRQ priorities:
+ * 15...0 Lowest...Highest.
+ *
+ * DMA priorities:
+ * 0...3 Lowest...Highest.
+ */
+
+/*
+ * HAL driver system settings.
+ */
+#define STM32_NO_INIT FALSE
+#define STM32_HSI_ENABLED TRUE
+#define STM32_LSI_ENABLED FALSE
+#define STM32_HSE_ENABLED TRUE
+#define STM32_LSE_ENABLED FALSE
+#define STM32_SW STM32_SW_PLL
+#define STM32_PLLSRC STM32_PLLSRC_HSE
+#define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1
+#define STM32_PLLMUL_VALUE 9
+#define STM32_HPRE STM32_HPRE_DIV1
+#define STM32_PPRE1 STM32_PPRE1_DIV2
+#define STM32_PPRE2 STM32_PPRE2_DIV2
+#define STM32_ADCPRE STM32_ADCPRE_DIV4
+#define STM32_USB_CLOCK_REQUIRED TRUE
+#define STM32_USBPRE STM32_USBPRE_DIV1P5
+#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
+#define STM32_RTCSEL STM32_RTCSEL_HSEDIV
+#define STM32_PVD_ENABLE FALSE
+#define STM32_PLS STM32_PLS_LEV0
+
+/*
+ * ADC driver system settings.
+ */
+#define STM32_ADC_USE_ADC1 FALSE
+#define STM32_ADC_ADC1_DMA_PRIORITY 2
+#define STM32_ADC_ADC1_IRQ_PRIORITY 6
+
+/*
+ * CAN driver system settings.
+ */
+#define STM32_CAN_USE_CAN1 FALSE
+#define STM32_CAN_CAN1_IRQ_PRIORITY 11
+
+/*
+ * EXT driver system settings.
+ */
+#define STM32_EXT_EXTI0_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI1_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI2_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI3_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI4_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI16_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI17_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI18_IRQ_PRIORITY 6
+#define STM32_EXT_EXTI19_IRQ_PRIORITY 6
+
+/*
+ * GPT driver system settings.
+ */
+#define STM32_GPT_USE_TIM1 FALSE
+#define STM32_GPT_USE_TIM2 FALSE
+#define STM32_GPT_USE_TIM3 FALSE
+#define STM32_GPT_USE_TIM4 FALSE
+#define STM32_GPT_USE_TIM5 FALSE
+#define STM32_GPT_USE_TIM8 FALSE
+#define STM32_GPT_TIM1_IRQ_PRIORITY 7
+#define STM32_GPT_TIM2_IRQ_PRIORITY 7
+#define STM32_GPT_TIM3_IRQ_PRIORITY 7
+#define STM32_GPT_TIM4_IRQ_PRIORITY 7
+#define STM32_GPT_TIM5_IRQ_PRIORITY 7
+#define STM32_GPT_TIM8_IRQ_PRIORITY 7
+
+/*
+ * I2C driver system settings.
+ */
+#define STM32_I2C_USE_I2C1 FALSE
+#define STM32_I2C_USE_I2C2 FALSE
+#define STM32_I2C_BUSY_TIMEOUT 50
+#define STM32_I2C_I2C1_IRQ_PRIORITY 5
+#define STM32_I2C_I2C2_IRQ_PRIORITY 5
+#define STM32_I2C_I2C1_DMA_PRIORITY 3
+#define STM32_I2C_I2C2_DMA_PRIORITY 3
+#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure")
+
+/*
+ * ICU driver system settings.
+ */
+#define STM32_ICU_USE_TIM1 FALSE
+#define STM32_ICU_USE_TIM2 FALSE
+#define STM32_ICU_USE_TIM3 FALSE
+#define STM32_ICU_USE_TIM4 FALSE
+#define STM32_ICU_USE_TIM5 FALSE
+#define STM32_ICU_USE_TIM8 FALSE
+#define STM32_ICU_TIM1_IRQ_PRIORITY 7
+#define STM32_ICU_TIM2_IRQ_PRIORITY 7
+#define STM32_ICU_TIM3_IRQ_PRIORITY 7
+#define STM32_ICU_TIM4_IRQ_PRIORITY 7
+#define STM32_ICU_TIM5_IRQ_PRIORITY 7
+#define STM32_ICU_TIM8_IRQ_PRIORITY 7
+
+/*
+ * PWM driver system settings.
+ */
+#define STM32_PWM_USE_ADVANCED FALSE
+#define STM32_PWM_USE_TIM1 FALSE
+#define STM32_PWM_USE_TIM2 FALSE
+#define STM32_PWM_USE_TIM3 FALSE
+#define STM32_PWM_USE_TIM4 FALSE
+#define STM32_PWM_USE_TIM5 FALSE
+#define STM32_PWM_USE_TIM8 FALSE
+#define STM32_PWM_TIM1_IRQ_PRIORITY 7
+#define STM32_PWM_TIM2_IRQ_PRIORITY 7
+#define STM32_PWM_TIM3_IRQ_PRIORITY 7
+#define STM32_PWM_TIM4_IRQ_PRIORITY 7
+#define STM32_PWM_TIM5_IRQ_PRIORITY 7
+#define STM32_PWM_TIM8_IRQ_PRIORITY 7
+
+/*
+ * RTC driver system settings.
+ */
+#define STM32_RTC_IRQ_PRIORITY 15
+
+/*
+ * SERIAL driver system settings.
+ */
+#define STM32_SERIAL_USE_USART1 FALSE
+#define STM32_SERIAL_USE_USART2 FALSE
+#define STM32_SERIAL_USE_USART3 FALSE
+#define STM32_SERIAL_USE_UART4 FALSE
+#define STM32_SERIAL_USE_UART5 FALSE
+#define STM32_SERIAL_USART1_PRIORITY 12
+#define STM32_SERIAL_USART2_PRIORITY 12
+#define STM32_SERIAL_USART3_PRIORITY 12
+#define STM32_SERIAL_UART4_PRIORITY 12
+#define STM32_SERIAL_UART5_PRIORITY 12
+
+/*
+ * SPI driver system settings.
+ */
+#define STM32_SPI_USE_SPI1 FALSE
+#define STM32_SPI_USE_SPI2 FALSE
+#define STM32_SPI_USE_SPI3 FALSE
+#define STM32_SPI_SPI1_DMA_PRIORITY 1
+#define STM32_SPI_SPI2_DMA_PRIORITY 1
+#define STM32_SPI_SPI3_DMA_PRIORITY 1
+#define STM32_SPI_SPI1_IRQ_PRIORITY 10
+#define STM32_SPI_SPI2_IRQ_PRIORITY 10
+#define STM32_SPI_SPI3_IRQ_PRIORITY 10
+#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure")
+
+/*
+ * ST driver system settings.
+ */
+#define STM32_ST_IRQ_PRIORITY 8
+#define STM32_ST_USE_TIMER 2
+
+/*
+ * UART driver system settings.
+ */
+#define STM32_UART_USE_USART1 FALSE
+#define STM32_UART_USE_USART2 FALSE
+#define STM32_UART_USE_USART3 FALSE
+#define STM32_UART_USART1_IRQ_PRIORITY 12
+#define STM32_UART_USART2_IRQ_PRIORITY 12
+#define STM32_UART_USART3_IRQ_PRIORITY 12
+#define STM32_UART_USART1_DMA_PRIORITY 0
+#define STM32_UART_USART2_DMA_PRIORITY 0
+#define STM32_UART_USART3_DMA_PRIORITY 0
+#define STM32_UART_DMA_ERROR_HOOK(uartp) osalSysHalt("DMA failure")
+
+/*
+ * USB driver system settings.
+ */
+#define STM32_USB_USE_USB1 TRUE
+#define STM32_USB_LOW_POWER_ON_SUSPEND FALSE
+#define STM32_USB_USB1_HP_IRQ_PRIORITY 13
+#define STM32_USB_USB1_LP_IRQ_PRIORITY 14
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/stm32_f103_onekey/stm32_f103_onekey.c b/keyboards/stm32_f103_onekey/stm32_f103_onekey.c
new file mode 100644
index 0000000000..7fa99bb28d
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/stm32_f103_onekey.c
@@ -0,0 +1 @@
+#include "stm32_f103_onekey.h"
diff --git a/keyboards/stm32_f103_onekey/stm32_f103_onekey.h b/keyboards/stm32_f103_onekey/stm32_f103_onekey.h
new file mode 100644
index 0000000000..e4d0dd9c4f
--- /dev/null
+++ b/keyboards/stm32_f103_onekey/stm32_f103_onekey.h
@@ -0,0 +1,4 @@
+#ifndef STM32_F103_ONEKEY_H
+#define STM32_F103_ONEKEY_H
+#include "quantum.h"
+#endif
diff --git a/keyboards/teensy_lc_onekey/Makefile b/keyboards/teensy_lc_onekey/Makefile
new file mode 100644
index 0000000000..064e618159
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/Makefile
@@ -0,0 +1,62 @@
+# project specific files
+SRC = matrix.c \
+ led.c
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = KL2x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MKL26Z64
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = kl2x
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_LC
+
+# Cortex version
+# Teensy LC is cortex-m0plus; Teensy 3.x are cortex-m4
+MCU = cortex-m0plus
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 6
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+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
+SLEEP_LED_ENABLE ?= yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE ?= yes # USB Nkey Rollover
+CUSTOM_MATRIX ?= yes # Custom matrix file
+
+ifndef QUANTUM_DIR
+ include ../../Makefile
+endif
diff --git a/keyboards/teensy_lc_onekey/Makefile.3.0 b/keyboards/teensy_lc_onekey/Makefile.3.0
new file mode 100644
index 0000000000..dbf12c3631
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/Makefile.3.0
@@ -0,0 +1,77 @@
+# Target file name (without extension).
+PROJECT = ch
+
+# Directory common source files exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC = matrix.c \
+ led.c
+
+ifdef KEYMAP
+ SRC := keymap_$(KEYMAP).c $(SRC)
+else
+ SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MK20DX128
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x5
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_3
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+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
+SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes # USB Nkey Rollover
+
+include $(TMK_DIR)/tool/chibios/common.mk
+include $(TMK_DIR)/tool/chibios/chibios.mk
diff --git a/keyboards/teensy_lc_onekey/Makefile.3.2 b/keyboards/teensy_lc_onekey/Makefile.3.2
new file mode 100644
index 0000000000..41bfa41a0c
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/Makefile.3.2
@@ -0,0 +1,77 @@
+# Target file name (without extension).
+PROJECT = ch
+
+# Directory common source files exist
+TMK_DIR = ../../tmk_core
+
+# Directory keyboard dependent files exist
+TARGET_DIR = .
+
+# project specific files
+SRC = matrix.c \
+ led.c
+
+ifdef KEYMAP
+ SRC := keymap_$(KEYMAP).c $(SRC)
+else
+ SRC := keymap_plain.c $(SRC)
+endif
+
+CONFIG_H = config.h
+
+## chip/board settings
+# - the next two should match the directories in
+# <chibios>/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)
+# - For Teensies, FAMILY = KINETIS and SERIES is either
+# KL2x (LC) or K20x (3.0,3.1,3.2).
+MCU_FAMILY = KINETIS
+MCU_SERIES = K20x
+
+# Linker script to use
+# - it should exist either in <chibios>/os/common/ports/ARMCMx/compilers/GCC/ld/
+# or <this_dir>/ld/
+# - NOTE: a custom ld script is needed for EEPROM on Teensy LC
+# - LDSCRIPT =
+# - MKL26Z64 for Teensy LC
+# - MK20DX128 for Teensy 3.0
+# - MK20DX256 for Teensy 3.1 and 3.2
+MCU_LDSCRIPT = MK20DX256
+
+# Startup code to use
+# - it should exist in <chibios>/os/common/ports/ARMCMx/compilers/GCC/mk/
+# - STARTUP =
+# - kl2x for Teensy LC
+# - k20x5 for Teensy 3.0
+# - k20x7 for Teensy 3.1 and 3.2
+MCU_STARTUP = k20x7
+
+# Board: it should exist either in <chibios>/os/hal/boards/
+# or <this_dir>/boards
+# - BOARD =
+# - PJRC_TEENSY_LC for Teensy LC
+# - PJRC_TEENSY_3 for Teensy 3.0
+# - PJRC_TEENSY_3_1 for Teensy 3.1 or 3.2
+BOARD = PJRC_TEENSY_3_1
+
+# Cortex version
+# Teensy LC is cortex-m0; Teensy 3.x are cortex-m4
+MCU = cortex-m4
+
+# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7
+# I.e. 6 for Teensy LC; 7 for Teensy 3.x
+ARMV = 7
+
+# Build Options
+# comment out to disable the options.
+#
+BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration
+## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.)
+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
+SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
+NKRO_ENABLE = yes # USB Nkey Rollover
+
+include $(TMK_DIR)/tool/chibios/common.mk
+include $(TMK_DIR)/tool/chibios/chibios.mk
diff --git a/keyboards/teensy_lc_onekey/chconf.h b/keyboards/teensy_lc_onekey/chconf.h
new file mode 100644
index 0000000000..cb36996c33
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/chconf.h
@@ -0,0 +1,524 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/chconf.h
+ * @brief Configuration file template.
+ * @details A copy of this file must be placed in each project directory, it
+ * contains the application specific kernel settings.
+ *
+ * @addtogroup config
+ * @details Kernel related settings and hooks.
+ * @{
+ */
+
+#ifndef CHCONF_H
+#define CHCONF_H
+
+#define _CHIBIOS_RT_CONF_
+
+/*===========================================================================*/
+/**
+ * @name System timers settings
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief System time counter resolution.
+ * @note Allowed values are 16 or 32 bits.
+ */
+#define CH_CFG_ST_RESOLUTION 32
+
+/**
+ * @brief System tick frequency.
+ * @details Frequency of the system timer that drives the system ticks. This
+ * setting also defines the system tick time unit.
+ */
+#define CH_CFG_ST_FREQUENCY 1000
+
+/**
+ * @brief Time delta constant for the tick-less mode.
+ * @note If this value is zero then the system uses the classic
+ * periodic tick. This value represents the minimum number
+ * of ticks that is safe to specify in a timeout directive.
+ * The value one is not valid, timeouts are rounded up to
+ * this value.
+ */
+#define CH_CFG_ST_TIMEDELTA 0
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel parameters and options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Round robin interval.
+ * @details This constant is the number of system ticks allowed for the
+ * threads before preemption occurs. Setting this value to zero
+ * disables the preemption for threads with equal priority and the
+ * round robin becomes cooperative. Note that higher priority
+ * threads can still preempt, the kernel is always preemptive.
+ * @note Disabling the round robin preemption makes the kernel more compact
+ * and generally faster.
+ * @note The round robin preemption is not supported in tickless mode and
+ * must be set to zero in that case.
+ */
+#define CH_CFG_TIME_QUANTUM 20
+
+/**
+ * @brief Managed RAM size.
+ * @details Size of the RAM area to be managed by the OS. If set to zero
+ * then the whole available RAM is used. The core memory is made
+ * available to the heap allocator and/or can be used directly through
+ * the simplified core memory allocator.
+ *
+ * @note In order to let the OS manage the whole RAM the linker script must
+ * provide the @p __heap_base__ and @p __heap_end__ symbols.
+ * @note Requires @p CH_CFG_USE_MEMCORE.
+ */
+#define CH_CFG_MEMCORE_SIZE 0
+
+/**
+ * @brief Idle thread automatic spawn suppression.
+ * @details When this option is activated the function @p chSysInit()
+ * does not spawn the idle thread. The application @p main()
+ * function becomes the idle thread and must implement an
+ * infinite loop.
+ */
+#define CH_CFG_NO_IDLE_THREAD FALSE
+
+/* Use __WFI in the idle thread for waiting. Does lower the power
+ * consumption. */
+#define CORTEX_ENABLE_WFI_IDLE TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Performance options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief OS optimization.
+ * @details If enabled then time efficient rather than space efficient code
+ * is used when two possible implementations exist.
+ *
+ * @note This is not related to the compiler optimization options.
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_OPTIMIZE_SPEED TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Subsystem options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Time Measurement APIs.
+ * @details If enabled then the time measurement APIs are included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_TM FALSE
+
+/**
+ * @brief Threads registry APIs.
+ * @details If enabled then the registry APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_REGISTRY TRUE
+
+/**
+ * @brief Threads synchronization APIs.
+ * @details If enabled then the @p chThdWait() function is included in
+ * the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_WAITEXIT TRUE
+
+/**
+ * @brief Semaphores APIs.
+ * @details If enabled then the Semaphores APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_SEMAPHORES TRUE
+
+/**
+ * @brief Semaphores queuing mode.
+ * @details If enabled then the threads are enqueued on semaphores by
+ * priority rather than in FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE
+
+/**
+ * @brief Mutexes APIs.
+ * @details If enabled then the mutexes APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MUTEXES TRUE
+
+/**
+ * @brief Enables recursive behavior on mutexes.
+ * @note Recursive mutexes are heavier and have an increased
+ * memory footprint.
+ *
+ * @note The default is @p FALSE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE
+
+/**
+ * @brief Conditional Variables APIs.
+ * @details If enabled then the conditional variables APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MUTEXES.
+ */
+#define CH_CFG_USE_CONDVARS TRUE
+
+/**
+ * @brief Conditional Variables APIs with timeout.
+ * @details If enabled then the conditional variables APIs with timeout
+ * specification are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_CONDVARS.
+ */
+#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE
+
+/**
+ * @brief Events Flags APIs.
+ * @details If enabled then the event flags APIs are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_EVENTS TRUE
+
+/**
+ * @brief Events Flags APIs with timeout.
+ * @details If enabled then the events APIs with timeout specification
+ * are included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_EVENTS.
+ */
+#define CH_CFG_USE_EVENTS_TIMEOUT TRUE
+
+/**
+ * @brief Synchronous Messages APIs.
+ * @details If enabled then the synchronous messages APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MESSAGES TRUE
+
+/**
+ * @brief Synchronous Messages queuing mode.
+ * @details If enabled then messages are served by priority rather than in
+ * FIFO order.
+ *
+ * @note The default is @p FALSE. Enable this if you have special
+ * requirements.
+ * @note Requires @p CH_CFG_USE_MESSAGES.
+ */
+#define CH_CFG_USE_MESSAGES_PRIORITY FALSE
+
+/**
+ * @brief Mailboxes APIs.
+ * @details If enabled then the asynchronous messages (mailboxes) APIs are
+ * included in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_SEMAPHORES.
+ */
+#define CH_CFG_USE_MAILBOXES TRUE
+
+/**
+ * @brief Core Memory Manager APIs.
+ * @details If enabled then the core memory manager APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMCORE TRUE
+
+/**
+ * @brief Heap Allocator APIs.
+ * @details If enabled then the memory heap allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or
+ * @p CH_CFG_USE_SEMAPHORES.
+ * @note Mutexes are recommended.
+ */
+#define CH_CFG_USE_HEAP TRUE
+
+/**
+ * @brief Memory Pools Allocator APIs.
+ * @details If enabled then the memory pools allocator APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ */
+#define CH_CFG_USE_MEMPOOLS TRUE
+
+/**
+ * @brief Dynamic Threads APIs.
+ * @details If enabled then the dynamic threads creation APIs are included
+ * in the kernel.
+ *
+ * @note The default is @p TRUE.
+ * @note Requires @p CH_CFG_USE_WAITEXIT.
+ * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS.
+ */
+#define CH_CFG_USE_DYNAMIC TRUE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Debug options
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Debug option, kernel statistics.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_STATISTICS FALSE
+
+/**
+ * @brief Debug option, system state check.
+ * @details If enabled the correct call protocol for system APIs is checked
+ * at runtime.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_SYSTEM_STATE_CHECK TRUE
+
+/**
+ * @brief Debug option, parameters checks.
+ * @details If enabled then the checks on the API functions input
+ * parameters are activated.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_CHECKS TRUE
+
+/**
+ * @brief Debug option, consistency checks.
+ * @details If enabled then all the assertions in the kernel code are
+ * activated. This includes consistency checks inside the kernel,
+ * runtime anomalies and port-defined checks.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_ENABLE_ASSERTS TRUE
+
+/**
+ * @brief Debug option, trace buffer.
+ * @details If enabled then the trace buffer is activated.
+ *
+ * @note The default is @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED
+
+/**
+ * @brief Trace buffer entries.
+ * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is
+ * different from @p CH_DBG_TRACE_MASK_DISABLED.
+ */
+#define CH_DBG_TRACE_BUFFER_SIZE 128
+
+/**
+ * @brief Debug option, stack checks.
+ * @details If enabled then a runtime stack check is performed.
+ *
+ * @note The default is @p FALSE.
+ * @note The stack check is performed in a architecture/port dependent way.
+ * It may not be implemented or some ports.
+ * @note The default failure mode is to halt the system with the global
+ * @p panic_msg variable set to @p NULL.
+ */
+#define CH_DBG_ENABLE_STACK_CHECK TRUE
+
+/**
+ * @brief Debug option, stacks initialization.
+ * @details If enabled then the threads working area is filled with a byte
+ * value when a thread is created. This can be useful for the
+ * runtime measurement of the used stack.
+ *
+ * @note The default is @p FALSE.
+ */
+#define CH_DBG_FILL_THREADS TRUE
+
+/**
+ * @brief Debug option, threads profiling.
+ * @details If enabled then a field is added to the @p thread_t structure that
+ * counts the system ticks occurred while executing the thread.
+ *
+ * @note The default is @p FALSE.
+ * @note This debug option is not currently compatible with the
+ * tickless mode.
+ */
+#define CH_DBG_THREADS_PROFILING FALSE
+
+/** @} */
+
+/*===========================================================================*/
+/**
+ * @name Kernel hooks
+ * @{
+ */
+/*===========================================================================*/
+
+/**
+ * @brief Threads descriptor structure extension.
+ * @details User fields added to the end of the @p thread_t structure.
+ */
+#define CH_CFG_THREAD_EXTRA_FIELDS \
+ /* Add threads custom fields here.*/
+
+/**
+ * @brief Threads initialization hook.
+ * @details User initialization code added to the @p chThdInit() API.
+ *
+ * @note It is invoked from within @p chThdInit() and implicitly from all
+ * the threads creation APIs.
+ */
+#define CH_CFG_THREAD_INIT_HOOK(tp) { \
+ /* Add threads initialization code here.*/ \
+}
+
+/**
+ * @brief Threads finalization hook.
+ * @details User finalization code added to the @p chThdExit() API.
+ */
+#define CH_CFG_THREAD_EXIT_HOOK(tp) { \
+ /* Add threads finalization code here.*/ \
+}
+
+/**
+ * @brief Context switch hook.
+ * @details This hook is invoked just before switching between threads.
+ */
+#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \
+ /* Context switch code here.*/ \
+}
+
+/**
+ * @brief ISR enter hook.
+ */
+#define CH_CFG_IRQ_PROLOGUE_HOOK() { \
+ /* IRQ prologue code here.*/ \
+}
+
+/**
+ * @brief ISR exit hook.
+ */
+#define CH_CFG_IRQ_EPILOGUE_HOOK() { \
+ /* IRQ epilogue code here.*/ \
+}
+
+/**
+ * @brief Idle thread enter hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to activate a power saving mode.
+ */
+#define CH_CFG_IDLE_ENTER_HOOK() { \
+ /* Idle-enter code here.*/ \
+}
+
+/**
+ * @brief Idle thread leave hook.
+ * @note This hook is invoked within a critical zone, no OS functions
+ * should be invoked from here.
+ * @note This macro can be used to deactivate a power saving mode.
+ */
+#define CH_CFG_IDLE_LEAVE_HOOK() { \
+ /* Idle-leave code here.*/ \
+}
+
+/**
+ * @brief Idle Loop hook.
+ * @details This hook is continuously invoked by the idle thread loop.
+ */
+#define CH_CFG_IDLE_LOOP_HOOK() { \
+ /* Idle loop code here.*/ \
+}
+
+/**
+ * @brief System tick event hook.
+ * @details This hook is invoked in the system tick handler immediately
+ * after processing the virtual timers queue.
+ */
+#define CH_CFG_SYSTEM_TICK_HOOK() { \
+ /* System tick event code here.*/ \
+}
+
+/**
+ * @brief System halt hook.
+ * @details This hook is invoked in case to a system halting error before
+ * the system is halted.
+ */
+#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \
+ /* System halt code here.*/ \
+}
+
+/**
+ * @brief Trace hook.
+ * @details This hook is invoked each time a new record is written in the
+ * trace buffer.
+ */
+#define CH_CFG_TRACE_HOOK(tep) { \
+ /* Trace code here.*/ \
+}
+
+/** @} */
+
+/*===========================================================================*/
+/* Port-specific settings (override port settings defaulted in chcore.h). */
+/*===========================================================================*/
+
+#endif /* CHCONF_H */
+
+/** @} */
diff --git a/keyboards/teensy_lc_onekey/config.h b/keyboards/teensy_lc_onekey/config.h
new file mode 100644
index 0000000000..19b14fe61a
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/config.h
@@ -0,0 +1,75 @@
+/*
+Copyright 2015 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
+
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xFEED
+#define PRODUCT_ID 0x6464
+#define DEVICE_VER 0x0001
+/* in python2: list(u"whatever".encode('utf-16-le')) */
+/* at most 32 characters or the ugly hack in usb_main.c borks */
+#define MANUFACTURER "TMK"
+#define USBSTR_MANUFACTURER 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', '\xc6', '\x00'
+#define PRODUCT "ChibiOS TMK test"
+#define USBSTR_PRODUCT 'C', '\x00', 'h', '\x00', 'i', '\x00', 'b', '\x00', 'i', '\x00', 'O', '\x00', 'S', '\x00', ' ', '\x00', 'T', '\x00', 'M', '\x00', 'K', '\x00', ' ', '\x00', 't', '\x00', 'e', '\x00', 's', '\x00', 't', '\x00'
+#define DESCRIPTION "TMK keyboard firmware over ChibiOS"
+
+/* key matrix size */
+#define MATRIX_ROWS 1
+#define MATRIX_COLS 1
+#define DIODE_DIRECTION COL2ROW
+
+/* define if matrix has ghost */
+//#define MATRIX_HAS_GHOST
+
+/* Set 0 if debouncing isn't needed */
+#define DEBOUNCE 5
+
+/* 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
diff --git a/keyboards/teensy_lc_onekey/halconf.h b/keyboards/teensy_lc_onekey/halconf.h
new file mode 100644
index 0000000000..b1d2cd5502
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/halconf.h
@@ -0,0 +1,187 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file templates/halconf.h
+ * @brief HAL configuration header.
+ * @details HAL configuration file, this file allows to enable or disable the
+ * various device drivers from your application. You may also use
+ * this file in order to override the device drivers default settings.
+ *
+ * @addtogroup HAL_CONF
+ * @{
+ */
+
+#ifndef _HALCONF_H_
+#define _HALCONF_H_
+
+#include "mcuconf.h"
+
+/**
+ * @brief Enables the PAL subsystem.
+ */
+#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__)
+#define HAL_USE_PAL TRUE
+#endif
+
+/**
+ * @brief Enables the ADC subsystem.
+ */
+#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__)
+#define HAL_USE_ADC FALSE
+#endif
+
+/**
+ * @brief Enables the CAN subsystem.
+ */
+#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__)
+#define HAL_USE_CAN FALSE
+#endif
+
+/**
+ * @brief Enables the DAC subsystem.
+ */
+#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__)
+#define HAL_USE_DAC FALSE
+#endif
+
+/**
+ * @brief Enables the EXT subsystem.
+ */
+#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__)
+#define HAL_USE_EXT FALSE
+#endif
+
+/**
+ * @brief Enables the GPT subsystem.
+ */
+#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__)
+#define HAL_USE_GPT FALSE
+#endif
+
+/**
+ * @brief Enables the I2C subsystem.
+ */
+#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__)
+#define HAL_USE_I2C FALSE
+#endif
+
+/**
+ * @brief Enables the I2S subsystem.
+ */
+#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__)
+#define HAL_USE_I2S FALSE
+#endif
+
+/**
+ * @brief Enables the ICU subsystem.
+ */
+#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__)
+#define HAL_USE_ICU FALSE
+#endif
+
+/**
+ * @brief Enables the MAC subsystem.
+ */
+#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__)
+#define HAL_USE_MAC FALSE
+#endif
+
+/**
+ * @brief Enables the MMC_SPI subsystem.
+ */
+#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_MMC_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the PWM subsystem.
+ */
+#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__)
+#define HAL_USE_PWM FALSE
+#endif
+
+/**
+ * @brief Enables the RTC subsystem.
+ */
+#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
+#define HAL_USE_RTC FALSE
+#endif
+
+/**
+ * @brief Enables the SDC subsystem.
+ */
+#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__)
+#define HAL_USE_SDC FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL subsystem.
+ */
+#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL FALSE
+#endif
+
+/**
+ * @brief Enables the SERIAL over USB subsystem.
+ */
+#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__)
+#define HAL_USE_SERIAL_USB FALSE
+#endif
+
+/**
+ * @brief Enables the SPI subsystem.
+ */
+#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__)
+#define HAL_USE_SPI FALSE
+#endif
+
+/**
+ * @brief Enables the UART subsystem.
+ */
+#if !defined(HAL_USE_UART) || defined(__DOXYGEN__)
+#define HAL_USE_UART FALSE
+#endif
+
+/**
+ * @brief Enables the USB subsystem.
+ */
+#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
+#define HAL_USE_USB TRUE
+#endif
+
+/**
+ * @brief Enables the WDG subsystem.
+ */
+#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__)
+#define HAL_USE_WDG FALSE
+#endif
+
+/*===========================================================================*/
+/* USB driver related settings. */
+/*===========================================================================*/
+
+/**
+ * @brief Enables synchronous APIs.
+ * @note Disabling this option saves both code and data space.
+ */
+#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__)
+#define USB_USE_WAIT TRUE
+#endif
+
+#endif /* _HALCONF_H_ */
+
+/** @} */
diff --git a/keyboards/teensy_lc_onekey/instructions.md b/keyboards/teensy_lc_onekey/instructions.md
new file mode 100644
index 0000000000..16886a015c
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/instructions.md
@@ -0,0 +1,82 @@
+# Teensy LC, 3.0, 3.1, 3.2 support
+
+These ARM Teensies are now supported through [ChibiOS](http://chibios.org).
+
+You'll need to install an ARM toolchain, for instance from [gcc ARM embedded](https://launchpad.net/gcc-arm-embedded) website, or using your favourite package manager. After installing, you should be able to run `arm-none-eabi-gcc -v` in the command prompt and get sensible output. This toolchain is used instead of `avr-gcc`, which is only for AVR chips. Naturally you'll also need the usual development tools (e.g. `make`), just as in the AVR setting.
+
+Next, you'll need ChibiOS. For Teensies, you'll need code from two repositories: [chibios-main](https://github.com/ChibiOS/ChibiOS) and [chibios-contrib](https://github.com/ChibiOS/ChibiOS). If you're not using git, you can just download a [zip of chibios from here](https://github.com/ChibiOS/ChibiOS/archive/a7df9a891067621e8e1a5c2a2c0ceada82403afe.zip), unpack the zip, and rename/move the unpacked directory (named `ChibiOS-<long_hash_here>`) to `tmk_core/tool/chibios/chibios` (so that the file `tmk_core/tool/chibios/chibios/license.txt` exists). Now the same procedure with a [zip of chibios-contrib from here](https://github.com/ChibiOS/ChibiOS-Contrib/archive/e1311c4db6cd366cf760673f769e925741ac0ad3.zip): unpack and move `ChibiOS-Contrib-<long_hash_here>` to `tmk_core/tool/chibios/chibios-contrib`.
+
+(If you're using git, you can just clone the two repos: [chibios](https://github.com/ChibiOS/ChibiOS) and [chibios-contrib](https://github.com/ChibiOS/ChibiOS-Contrib). However - be warned that things may be somewhat out-of-sync (updates at different rates), so you may need to hunt a bit for the right commits.)
+
+(Why do we need chibios-contrib? Well, the main repo focuses on STM32 chips, and Freescale/NXP Kinetis chips are supported via the Contrib repository.)
+
+This should be it. Running `make` in `keyboard/teensy_lc_onekey` should create a working firmware in `build/`, called `ch.hex`.
+
+For more notes about the ChibiOS backend in TMK, see `tmk_core/protocol/chibios/README.md`.
+
+## About this onekey example
+
+It's set up for Teensy LC. To use 3.x, you'll need to edit the `Makefile` (and comment out one line in `mcuconf.h`). A sample makefile for Teensy 3.0 is provided as `Makefile.3.0`, can be used without renaming with `make -f Makefile.3.0`. Similarly for Teensy 3.2, there's `Makefile.3.2`.
+
+## Credits
+
+TMK itself is written by hasu, original sources [here](https://github.com/tmk/tmk_keyboard).
+
+The USB support for Kinetis MCUs is due to RedoX. His ChibiOS fork is also [on github](https://github.com/RedoXyde/ChibiOS); but it doesn't include Teensy LC definitions.
+
+## Features that are not implemented yet
+
+Currently only the more fancy suspend features are not there (power saving during suspend). The rest should work fine (reports either way are welcome).
+
+# Matrix programming notes
+
+The notes below explain what commands can be used to examine and set the status of Teensy pins.
+
+## ChibiOS pin manipulation basics
+
+### Pins
+
+Each pin sits on a "port", each of which comprises at most 32 individual pins.
+So for instance "PTC5" from Kinetis manual/datasheet refers to port C (or GPIOA), pin 5. Most functions dealing with pins take 2 parameters which specify the pin -- the first being the port, the second being the pin number.
+
+Within ChibiOS, there are definitions which simplify this a bit for the Teensies. `TEENSY_PINn_IOPORT` represents the port of the MCU's pin connected Teensy's PIN `n`, and `TEENSY_PINn` represents its MCU's pin number.
+
+### Mode
+
+A MCU pin can be in several modes. The basic command to set a pin mode is
+
+ palSetPadMode(TEENSY_PINn_IOPORT, TEENSY_PINn, PAL_MODE_INPUT_PULLUP);
+
+The last parameter is the mode. For keyboards, the usual ones that are used are `PAL_MODE_INPUT_PULLUP` (input with a pullup), `PAL_MODE_INPUT_PULLDOWN` (input with a pulldown), `PAL_MODE_INPUT` (input floating, a.k.a. Hi-Z), `PAL_MODE_OUTPUT_PUSHPULL` (output in the Arduino sense -- can be then set HIGH or LOW).
+
+### Setting
+
+Pins are set HIGH (after they've been put into `OUTPUT_PUSHPULL` mode) by
+
+ palSetPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+or set LOW by
+
+ palClearPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+Toggling can be done with
+
+ palTogglePad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+Alternatively, you can use
+
+ palWritePad(TEENSY_PINn_IOPORT, TEENSY_PINn, bit);
+
+where `bit` is either `PAL_LOW` or `PAL_HIGH` (i.e. `0` or `1`).
+
+### Reading
+
+Reading pin status is done with
+
+ palReadPad(TEENSY_PINn_IOPORT, TEENSY_PINn);
+
+The function returns either `PAL_HIGH` (actually `1`) or `PAL_LOW` (actually `0`).
+
+### Further docs
+
+All the commands that are available for pin manipulation through ChibiOS HAL are documented in [ChibiOS PAL driver docs](http://chibios.sourceforge.net/docs3/hal/group___p_a_l.html).
diff --git a/keyboards/teensy_lc_onekey/keymaps/default/keymap.c b/keyboards/teensy_lc_onekey/keymaps/default/keymap.c
new file mode 100644
index 0000000000..a109b49600
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/keymaps/default/keymap.c
@@ -0,0 +1,32 @@
+/*
+Copyright 2012,2013 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/>.
+*/
+
+#include "keycode.h"
+#include "action.h"
+#include "action_macro.h"
+#include "report.h"
+#include "host.h"
+#include "print.h"
+#include "debug.h"
+#include "keymap.h"
+
+const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ {{KC_A}},
+}; // to test: KC_CAPS, KT_BTLD, KC_A
+
+const uint16_t fn_actions[] = {
+};
diff --git a/keyboards/teensy_lc_onekey/ld/MKL26Z64.ld b/keyboards/teensy_lc_onekey/ld/MKL26Z64.ld
new file mode 100644
index 0000000000..fb141f888c
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/ld/MKL26Z64.ld
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2013-2016 Fabio Utzig, http://fabioutzig.com
+ * (C) 2016 flabbergast <s3+flabbergast@sdfeu.org>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * KL26Z64 memory setup.
+ */
+MEMORY
+{
+ flash0 : org = 0x00000000, len = 0x100
+ flash1 : org = 0x00000400, len = 0x10
+ flash2 : org = 0x00000410, len = 62k - 0x410
+ flash3 : org = 0x0000F800, len = 2k
+ flash4 : org = 0x00000000, len = 0
+ flash5 : org = 0x00000000, len = 0
+ flash6 : org = 0x00000000, len = 0
+ flash7 : org = 0x00000000, len = 0
+ ram0 : org = 0x1FFFF800, len = 8k
+ ram1 : org = 0x00000000, len = 0
+ ram2 : org = 0x00000000, len = 0
+ ram3 : org = 0x00000000, len = 0
+ ram4 : org = 0x00000000, len = 0
+ ram5 : org = 0x00000000, len = 0
+ ram6 : org = 0x00000000, len = 0
+ ram7 : org = 0x00000000, len = 0
+}
+
+/* Flash region for the configuration bytes.*/
+SECTIONS
+{
+ .cfmprotect : ALIGN(4) SUBALIGN(4)
+ {
+ KEEP(*(.cfmconfig))
+ } > flash1
+}
+
+/* For each data/text section two region are defined, a virtual region
+ and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash2);
+REGION_ALIAS("XTORS_FLASH_LMA", flash2);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash2);
+REGION_ALIAS("TEXT_FLASH_LMA", flash2);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash2);
+REGION_ALIAS("RODATA_FLASH_LMA", flash2);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash2);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash2);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash2);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+ of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+ the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash2);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+__eeprom_workarea_start__ = ORIGIN(flash3);
+__eeprom_workarea_size__ = LENGTH(flash3);
+__eeprom_workarea_end__ = __eeprom_workarea_start__ + __eeprom_workarea_size__;
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/keyboards/teensy_lc_onekey/led.c b/keyboards/teensy_lc_onekey/led.c
new file mode 100644
index 0000000000..dfa60c1076
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/led.c
@@ -0,0 +1,32 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "hal.h"
+
+#include "led.h"
+
+
+void led_set(uint8_t usb_led) {
+ if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
+ // output high
+ palSetPadMode(TEENSY_PIN13_IOPORT, TEENSY_PIN13, PAL_MODE_OUTPUT_PUSHPULL);
+ palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+ } else {
+ // Hi-Z
+ palSetPadMode(TEENSY_PIN13_IOPORT, TEENSY_PIN13, PAL_MODE_INPUT);
+ }
+}
diff --git a/keyboards/teensy_lc_onekey/matrix.c b/keyboards/teensy_lc_onekey/matrix.c
new file mode 100644
index 0000000000..7dab04f02b
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/matrix.c
@@ -0,0 +1,163 @@
+/*
+Copyright 2012 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/>.
+*/
+
+#include "ch.h"
+#include "hal.h"
+
+/*
+ * scan matrix
+ */
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "matrix.h"
+#include "wait.h"
+
+#ifndef DEBOUNCE
+# define DEBOUNCE 5
+#endif
+static uint8_t debouncing = DEBOUNCE;
+
+/* matrix state(1:on, 0:off) */
+static matrix_row_t matrix[MATRIX_ROWS];
+static matrix_row_t matrix_debouncing[MATRIX_ROWS];
+
+static matrix_row_t read_cols(void);
+static void init_cols(void);
+static void unselect_rows(void);
+static void select_row(uint8_t row);
+
+
+inline
+uint8_t matrix_rows(void)
+{
+ return MATRIX_ROWS;
+}
+
+inline
+uint8_t matrix_cols(void)
+{
+ return MATRIX_COLS;
+}
+
+#define LED_ON() do { palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13) ;} while (0)
+#define LED_OFF() do { palClearPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13); } while (0)
+#define LED_TGL() do { palTogglePad(TEENSY_PIN13_IOPORT, TEENSY_PIN13); } while (0)
+
+void matrix_init(void)
+{
+ // initialize row and col
+ unselect_rows();
+ init_cols();
+
+ // initialize matrix state: all keys off
+ for (uint8_t i=0; i < MATRIX_ROWS; i++) {
+ matrix[i] = 0;
+ matrix_debouncing[i] = 0;
+ }
+
+ //debug
+ debug_matrix = true;
+ LED_ON();
+ wait_ms(500);
+ LED_OFF();
+}
+
+uint8_t matrix_scan(void)
+{
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ select_row(i);
+ wait_us(30); // without this wait read unstable value.
+ matrix_row_t cols = read_cols();
+ if (matrix_debouncing[i] != cols) {
+ matrix_debouncing[i] = cols;
+ if (debouncing) {
+ debug("bounce!: "); debug_hex(debouncing); debug("\n");
+ }
+ debouncing = DEBOUNCE;
+ }
+ unselect_rows();
+ }
+
+ if (debouncing) {
+ if (--debouncing) {
+ wait_ms(1);
+ } else {
+ for (uint8_t i = 0; i < MATRIX_ROWS; i++) {
+ matrix[i] = matrix_debouncing[i];
+ }
+ }
+ }
+
+ return 1;
+}
+
+inline
+bool matrix_is_on(uint8_t row, uint8_t col)
+{
+ return (matrix[row] & ((matrix_row_t)1<<col));
+}
+
+inline
+matrix_row_t matrix_get_row(uint8_t row)
+{
+ return matrix[row];
+}
+
+void matrix_print(void)
+{
+ print("\nr/c 0123456789ABCDEF\n");
+ for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
+ phex(row); print(": ");
+ pbin_reverse16(matrix_get_row(row));
+ print("\n");
+ }
+}
+
+/* Column pin configuration
+ */
+static void init_cols(void)
+{
+ // internal pull-up
+ palSetPadMode(TEENSY_PIN2_IOPORT, TEENSY_PIN2, PAL_MODE_INPUT_PULLUP);
+}
+
+/* Returns status of switches(1:on, 0:off) */
+static matrix_row_t read_cols(void)
+{
+ return ((palReadPad(TEENSY_PIN2_IOPORT, TEENSY_PIN2)==PAL_HIGH) ? 0 : (1<<0));
+ // | ((palReadPad(...)==PAL_HIGH) ? 0 : (1<<1))
+}
+
+/* Row pin configuration
+ */
+static void unselect_rows(void)
+{
+ palSetPadMode(TEENSY_PIN5_IOPORT, TEENSY_PIN5, PAL_MODE_INPUT); // hi-Z
+}
+
+static void select_row(uint8_t row)
+{
+ (void)row;
+ // Output low to select
+ switch (row) {
+ case 0:
+ palSetPadMode(TEENSY_PIN5_IOPORT, TEENSY_PIN5, PAL_MODE_OUTPUT_PUSHPULL);
+ palClearPad(TEENSY_PIN5_IOPORT, TEENSY_PIN5);
+ break;
+ }
+}
diff --git a/keyboards/teensy_lc_onekey/mcuconf.h b/keyboards/teensy_lc_onekey/mcuconf.h
new file mode 100644
index 0000000000..c636590197
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/mcuconf.h
@@ -0,0 +1,55 @@
+/*
+ ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#ifndef _MCUCONF_H_
+#define _MCUCONF_H_
+
+#define KL2x_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+#if 1
+/* PEE mode - 48MHz system clock driven by (16 MHz) external crystal. */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_PEE
+#define KINETIS_PLLCLK_FREQUENCY 96000000UL
+#define KINETIS_SYSCLK_FREQUENCY 48000000UL
+#endif
+
+#if 0
+/* crystal-less FEI mode - 48 MHz with internal 32.768 kHz crystal */
+#define KINETIS_MCG_MODE KINETIS_MCG_MODE_FEI
+#define KINETIS_MCG_FLL_DMX32 1 /* Fine-tune for 32.768 kHz */
+#define KINETIS_MCG_FLL_DRS 1 /* 1464x FLL factor */
+#define KINETIS_SYSCLK_FREQUENCY 47972352UL /* 32.768 kHz * 1464 (~48 MHz) */
+#define KINETIS_CLKDIV1_OUTDIV1 1 /* do not divide system clock */
+#endif
+
+/*
+ * SERIAL driver system settings.
+ */
+#define KINETIS_SERIAL_USE_UART0 TRUE
+
+/*
+ * USB driver settings
+ */
+#define KINETIS_USB_USE_USB0 TRUE
+/* Need to redefine this, since the default is for K20x */
+/* This is for Teensy LC; you should comment it out (or change to 5)
+ * for Teensy 3.x */
+#define KINETIS_USB_USB0_IRQ_PRIORITY 2
+
+#endif /* _MCUCONF_H_ */
diff --git a/keyboards/teensy_lc_onekey/teensy_lc_onekey.c b/keyboards/teensy_lc_onekey/teensy_lc_onekey.c
new file mode 100644
index 0000000000..b6c4327932
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/teensy_lc_onekey.c
@@ -0,0 +1 @@
+#include "teensy_lc_onekey.h"
diff --git a/keyboards/teensy_lc_onekey/teensy_lc_onekey.h b/keyboards/teensy_lc_onekey/teensy_lc_onekey.h
new file mode 100644
index 0000000000..f598bcf66d
--- /dev/null
+++ b/keyboards/teensy_lc_onekey/teensy_lc_onekey.h
@@ -0,0 +1,4 @@
+#ifndef TEENSY_LC_ONEKEY_H
+#define TEENSY_LC_ONEKEY_H
+#include "quantum.h"
+#endif
diff --git a/lib/chibios b/lib/chibios
new file mode 160000
+Subproject a7df9a891067621e8e1a5c2a2c0ceada82403af
diff --git a/lib/chibios-contrib b/lib/chibios-contrib
new file mode 160000
+Subproject e1311c4db6cd366cf760673f769e925741ac0ad
diff --git a/quantum/keycode_config.h b/quantum/keycode_config.h
index c41c08706c..6216eefc90 100644
--- a/quantum/keycode_config.h
+++ b/quantum/keycode_config.h
@@ -18,4 +18,4 @@ typedef union {
};
} keymap_config_t;
-keymap_config_t keymap_config; \ No newline at end of file
+extern keymap_config_t keymap_config;
diff --git a/quantum/keymap.h b/quantum/keymap.h
index a994f4f2e5..73f99f8211 100644
--- a/quantum/keymap.h
+++ b/quantum/keymap.h
@@ -21,7 +21,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <stdint.h>
#include <stdbool.h>
#include "action.h"
+#if defined(__AVR__)
#include <avr/pgmspace.h>
+#endif
#include "keycode.h"
#include "action_macro.h"
#include "report.h"
@@ -30,12 +32,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "debug.h"
#include "keycode_config.h"
+// ChibiOS uses RESET in its FlagStatus enumeration
+// Therefore define it as QK_RESET here, to avoid name collision
+#if defined(PROTOCOL_CHIBIOS)
+#define RESET QK_RESET
+#endif
+
/* translates key to keycode */
uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
-/* translates Fn keycode to action */
-action_t keymap_fn_to_action(uint16_t keycode);
-
extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS];
extern const uint16_t fn_actions[];
diff --git a/quantum/keymap.c b/quantum/keymap_common.c
index 74fd518c9b..76872ac592 100644
--- a/quantum/keymap.c
+++ b/quantum/keymap_common.c
@@ -19,7 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "report.h"
#include "keycode.h"
#include "action_layer.h"
+#if defined(__AVR__)
#include <util/delay.h>
+#include <stdio.h>
+#endif
#include "action.h"
#include "action_macro.h"
#include "debug.h"
@@ -32,7 +35,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
extern keymap_config_t keymap_config;
-#include <stdio.h>
#include <inttypes.h>
/* converts key to action */
@@ -46,10 +48,12 @@ action_t action_for_key(uint8_t layer, keypos_t key)
action_t action;
uint8_t action_layer, when, mod;
+ // The arm-none-eabi compiler generates out of bounds warnings when using the fn_actions directly for some reason
+ const uint16_t* actions = fn_actions;
switch (keycode) {
case KC_FN0 ... KC_FN31:
- action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
+ action.code = pgm_read_word(&actions[FN_INDEX(keycode)]);
break;
case KC_A ... KC_EXSEL:
case KC_LCTRL ... KC_RGUI:
@@ -75,7 +79,7 @@ action_t action_for_key(uint8_t layer, keypos_t key)
case QK_FUNCTION ... QK_FUNCTION_MAX: ;
// Is a shortcut for function action_layer, pull last 12bits
// This means we have 4,096 FN macros at our disposal
- action.code = pgm_read_word(&fn_actions[(int)keycode & 0xFFF]);
+ action.code = pgm_read_word(&actions[(int)keycode & 0xFFF]);
break;
case QK_MACRO ... QK_MACRO_MAX:
action.code = ACTION_MACRO(keycode & 0xFF);
diff --git a/quantum/matrix.c b/quantum/matrix.c
index f5744658cf..a38c13f15b 100644
--- a/quantum/matrix.c
+++ b/quantum/matrix.c
@@ -17,7 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
+#if defined(__AVR__)
#include <avr/io.h>
+#endif
#include "wait.h"
#include "print.h"
#include "debug.h"
diff --git a/quantum/quantum.c b/quantum/quantum.c
index 270b976e36..d59bd5a3f8 100644
--- a/quantum/quantum.c
+++ b/quantum/quantum.c
@@ -88,7 +88,7 @@ bool process_record_quantum(keyrecord_t *record) {
stop_all_notes();
shutdown_user();
#endif
- _delay_ms(250);
+ wait_ms(250);
#ifdef ATREUS_ASTAR
*(uint16_t *)0x0800 = 0x7777; // these two are a-star-specific
#endif
diff --git a/quantum/quantum.h b/quantum/quantum.h
index 9b5d310bd4..3a0b742028 100644
--- a/quantum/quantum.h
+++ b/quantum/quantum.h
@@ -1,7 +1,12 @@
#ifndef QUANTUM_H
#define QUANTUM_H
+#if defined(__AVR__)
#include <avr/pgmspace.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#endif
+#include "wait.h"
#include "matrix.h"
#include "keymap.h"
#ifdef BACKLIGHT_ENABLE
@@ -14,12 +19,9 @@
#include "action_layer.h"
#include "eeconfig.h"
#include <stddef.h>
-#include <avr/io.h>
-#include <util/delay.h>
#include "bootloader.h"
#include "timer.h"
#include "config_common.h"
-#include <avr/interrupt.h>
#include "led.h"
#include "action_util.h"
#include <stdlib.h>
diff --git a/readme.md b/readme.md
index 6fa67c0474..c24d951d8d 100644
--- a/readme.md
+++ b/readme.md
@@ -24,6 +24,9 @@ The project also includes community support for [lots of other keyboards](/keybo
QMK is developed and maintained by Jack Humbert of OLKB with contributions from the community, and of course, [Hasu](https://github.com/tmk). This repo used to be a fork of [TMK](https://github.com/tmk/tmk_keyboard), and we are incredibly grateful for his founding contributions to the firmware. We've had to break the fork due to purely technical reasons - it simply became too different over time, and we've had to start refactoring some of the basic bits and pieces. We are huge fans of TMK and Hasu :)
This documentation is edited and maintained by Erez Zukerman of ErgoDox EZ. If you spot any typos or inaccuracies, please [open an issue](https://github.com/jackhumbert/qmk_firmware/issues/new).
+#### 2016/02/10
+core: flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios> (@72b1668). See [tmk_core/protocol/chibios/README.md](tmk_core/protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
+
The OLKB product firmwares are maintained by [Jack Humbert](https://github.com/jackhumbert), the Ergodox EZ by [Erez Zukerman](https://github.com/ezuk), and the Clueboard by [Zach White](https://github.com/skullydazed).
diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk
new file mode 100644
index 0000000000..72be5e6da1
--- /dev/null
+++ b/tmk_core/avr.mk
@@ -0,0 +1,185 @@
+# Hey Emacs, this is a -*- makefile -*-
+##############################################################################
+# Compiler settings
+#
+CC = avr-gcc
+OBJCOPY = avr-objcopy
+OBJDUMP = avr-objdump
+SIZE = avr-size
+AR = avr-ar rcs
+NM = avr-nm
+HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature
+EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT)
+
+
+
+COMPILEFLAGS += -funsigned-char
+COMPILEFLAGS += -funsigned-bitfields
+COMPILEFLAGS += -ffunction-sections
+COMPILEFLAGS += -fdata-sections
+COMPILEFLAGS += -fpack-struct
+COMPILEFLAGS += -fshort-enums
+
+CFLAGS += $(COMPILEFLAGS)
+CFLAGS += -fno-inline-small-functions
+CFLAGS += -fno-strict-aliasing
+
+CPPFLAGS += $(COMPILEFLAGS)
+CPPFLAGS += -fno-exceptions
+
+LDFLAGS +=-Wl,--gc-sections
+
+OPT_DEFS += -DF_CPU=$(F_CPU)UL
+
+MCUFLAGS = -mmcu=$(MCU)
+
+# List any extra directories to look for libraries here.
+# Each directory must be seperated by a space.
+# Use forward slashes for directory separators.
+# For a directory that has spaces, enclose it in quotes.
+EXTRALIBDIRS =
+
+
+#---------------- External Memory Options ----------------
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# used for variables (.data/.bss) and heap (malloc()).
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
+
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
+# only used for heap (malloc()).
+#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
+
+EXTMEMOPTS =
+
+#---------------- Debugging Options ----------------
+
+# Debugging format.
+# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
+# AVR Studio 4.10 requires dwarf-2.
+# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
+DEBUG = dwarf-2
+
+# For simulavr only - target MCU frequency.
+DEBUG_MFREQ = $(F_CPU)
+
+# Set the DEBUG_UI to either gdb or insight.
+# DEBUG_UI = gdb
+DEBUG_UI = insight
+
+# Set the debugging back-end to either avarice, simulavr.
+DEBUG_BACKEND = avarice
+#DEBUG_BACKEND = simulavr
+
+# GDB Init Filename.
+GDBINIT_FILE = __avr_gdbinit
+
+# When using avarice settings for the JTAG
+JTAG_DEV = /dev/com1
+
+# Debugging port used to communicate between GDB / avarice / simulavr.
+DEBUG_PORT = 4242
+
+# Debugging host used to communicate between GDB / avarice / simulavr, normally
+# just set to localhost unless doing some sort of crazy debugging when
+# avarice is running on a different computer.
+DEBUG_HOST = localhost
+
+#============================================================================
+# Autodecct teensy loader
+ifneq (, $(shell which teensy-loader-cli 2>/dev/null))
+ TEENSY_LOADER_CLI = teensy-loader-cli
+else
+ TEENSY_LOADER_CLI = teensy_loader_cli
+endif
+
+# Program the device.
+program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ $(PROGRAM_CMD)
+
+teensy: $(BUILD_DIR)/$(TARGET).hex
+ $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
+
+flip: $(BUILD_DIR)/$(TARGET).hex
+ batchisp -hardware usb -device $(MCU) -operation erase f
+ batchisp -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+
+dfu: $(BUILD_DIR)/$(TARGET).hex sizeafter
+ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
+ dfu-programmer $(MCU) erase --force
+else
+ dfu-programmer $(MCU) erase
+endif
+ dfu-programmer $(MCU) flash $(BUILD_DIR)/$(TARGET).hex
+ dfu-programmer $(MCU) reset
+
+dfu-start:
+ dfu-programmer $(MCU) reset
+ dfu-programmer $(MCU) start
+
+flip-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ $(COPY) $(BUILD_DIR)/$(TARGET).eep $(BUILD_DIR)/$(TARGET)eep.hex
+ batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
+ batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(BUILD_DIR)/$(TARGET)eep.hex program
+ batchisp -hardware usb -device $(MCU) -operation start reset 0
+ $(REMOVE) $(BUILD_DIR)/$(TARGET)eep.hex
+
+dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
+ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
+ dfu-programmer $(MCU) flash --eeprom $(BUILD_DIR)/$(TARGET).eep
+else
+ dfu-programmer $(MCU) flash-eeprom $(BUILD_DIR)/$(TARGET).eep
+endif
+ dfu-programmer $(MCU) reset
+
+
+# Generate avr-gdb config/init file which does the following:
+# define the reset signal, load the target file, connect to target, and set
+# a breakpoint at main().
+gdb-config:
+ @$(REMOVE) $(GDBINIT_FILE)
+ @echo define reset >> $(GDBINIT_FILE)
+ @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
+ @echo end >> $(GDBINIT_FILE)
+ @echo file $(BUILD_DIR)/$(TARGET).elf >> $(GDBINIT_FILE)
+ @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
+ifeq ($(DEBUG_BACKEND),simulavr)
+ @echo load >> $(GDBINIT_FILE)
+endif
+ @echo break main >> $(GDBINIT_FILE)
+
+debug: gdb-config $(BUILD_DIR)/$(TARGET).elf
+ifeq ($(DEBUG_BACKEND), avarice)
+ @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
+ @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
+ $(BUILD_DIR)/$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
+ @$(WINSHELL) /c pause
+
+else
+ @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
+ $(DEBUG_MFREQ) --port $(DEBUG_PORT)
+endif
+ @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
+
+
+
+
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
+COFFCONVERT = $(OBJCOPY) --debugging
+COFFCONVERT += --change-section-address .data-0x800000
+COFFCONVERT += --change-section-address .bss-0x800000
+COFFCONVERT += --change-section-address .noinit-0x800000
+COFFCONVERT += --change-section-address .eeprom-0x810000
+
+
+
+coff: $(BUILD_DIR)/$(TARGET).elf
+ @$(SECHO) $(MSG_COFF) $(BUILD_DIR)/$(TARGET).cof
+ $(COFFCONVERT) -O coff-avr $< $(BUILD_DIR)/$(TARGET).cof
+
+
+extcoff: $(BUILD_DIR)/$(TARGET).elf
+ @$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof
+ $(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
+
diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk
new file mode 100644
index 0000000000..0abb933a8d
--- /dev/null
+++ b/tmk_core/chibios.mk
@@ -0,0 +1,154 @@
+# Hey Emacs, this is a -*- makefile -*-
+##############################################################################
+# Architecture or project specific options
+#
+
+# Stack size to be allocated to the Cortex-M process stack. This stack is
+# the stack used by the main() thread.
+ifeq ($(USE_PROCESS_STACKSIZE),)
+ USE_PROCESS_STACKSIZE = 0x200
+endif
+
+# Stack size to the allocated to the Cortex-M main/exceptions stack. This
+# stack is used for processing interrupts and exceptions.
+ifeq ($(USE_EXCEPTIONS_STACKSIZE),)
+ USE_EXCEPTIONS_STACKSIZE = 0x400
+endif
+
+#
+# Architecture or project specific options
+##############################################################################
+
+##############################################################################
+# Project, sources and paths
+#
+
+# Imported source files and paths
+CHIBIOS = $(TOP_DIR)/lib/chibios
+CHIBIOS_CONTRIB = $(TOP_DIR)/lib/chibios-contrib
+# Startup files. Try a few different locations, for compability with old versions and
+# for things hardware in the contrib repository
+STARTUP_MK = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ ifeq ("$(wildcard $(STARTUP_MK))","")
+ STARTUP_MK = $(CHIBIOS_CONTRIB)/os/common/startup/ARMCMx/compilers/GCC/mk/startup_$(MCU_STARTUP).mk
+ endif
+endif
+include $(STARTUP_MK)
+# HAL-OSAL files (optional).
+include $(CHIBIOS)/os/hal/hal.mk
+
+PLATFORM_MK = $(CHIBIOS)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/platform.mk
+ifeq ("$(wildcard $(PLATFORM_MK))","")
+PLATFORM_MK = $(CHIBIOS_CONTRIB)/os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES)/platform.mk
+endif
+include $(PLATFORM_MK)
+
+
+BOARD_MK = $(KEYBOARD_PATH)/boards/$(BOARD)/board.mk
+ifeq ("$(wildcard $(BOARD_MK))","")
+ BOARD_MK = $(CHIBIOS)/os/hal/boards/$(BOARD)/board.mk
+ ifeq ("$(wildcard $(BOARD_MK))","")
+ BOARD_MK = $(CHIBIOS_CONTRIB)/os/hal/boards/$(BOARD)/board.mk
+ endif
+endif
+include $(BOARD_MK)
+include $(CHIBIOS)/os/hal/osal/rt/osal.mk
+# RTOS files (optional).
+include $(CHIBIOS)/os/rt/rt.mk
+# Compability with old version
+PORT_V = $(CHIBIOS)/os/rt/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+ifeq ("$(wildcard $(PORT_V))","")
+PORT_V = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v$(ARMV)m.mk
+endif
+include $(PORT_V)
+# Other files (optional).
+include $(CHIBIOS)/os/hal/lib/streams/streams.mk
+
+RULESPATH = $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC
+ifeq ("$(wildcard $(RULESPATH)/rules.mk)","")
+RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC
+endif
+
+# Define linker script file here
+ifneq ("$(wildcard $(KEYBOARD_PATH)/ld/$(MCU_LDSCRIPT).ld)","")
+LDSCRIPT = $(KEYBOARD_PATH)/ld/$(MCU_LDSCRIPT).ld
+else
+LDSCRIPT = $(STARTUPLD)/$(MCU_LDSCRIPT).ld
+endif
+
+CHIBISRC = $(STARTUPSRC) \
+ $(KERNSRC) \
+ $(PORTSRC) \
+ $(OSALSRC) \
+ $(HALSRC) \
+ $(PLATFORMSRC) \
+ $(BOARDSRC) \
+ $(STREAMSSRC) \
+ $(STARTUPASM) \
+ $(PORTASM) \
+ $(OSALASM)
+
+SRC += $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC))
+
+EXTRAINCDIRS += $(CHIBIOS)/os/license \
+ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
+ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
+ $(STREAMSINC) $(CHIBIOS)/os/various
+
+#
+# Project, sources and paths
+##############################################################################
+
+
+##############################################################################
+# Compiler settings
+#
+CC = arm-none-eabi-gcc
+OBJCOPY = arm-none-eabi-objcopy
+OBJDUMP = arm-none-eabi-objdump
+SIZE = arm-none-eabi-size
+AR = arm-none-eabi-ar
+NM = arm-none-eabi-nm
+HEX = $(OBJCOPY) -O $(FORMAT)
+EEP =
+
+THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB
+
+COMPILEFLAGS += -fomit-frame-pointer
+COMPILEFLAGS += -falign-functions=16
+COMPILEFLAGS += -ffunction-sections
+COMPILEFLAGS += -fdata-sections
+COMPILEFLAGS += -fno-common
+COMPILEFLAGS += $(THUMBFLAGS)
+
+CFLAGS += $(COMPILEFLAGS)
+
+ASFLAGS += $(THUMBFLAGS)
+
+CPPFLAGS += $(COMPILEFLAGS)
+CPPFLAGS += -fno-rtti
+
+LDFLAGS +=-Wl,--gc-sections
+LDFLAGS += -mno-thumb-interwork -mthumb
+LDSYMBOLS =,--defsym=__process_stack_size__=$(USE_PROCESS_STACKSIZE)
+LDSYMBOLS :=$(LDSYMBOLS),--defsym=__main_stack_size__=$(USE_EXCEPTIONS_STACKSIZE)
+LDFLAGS += -Wl,--script=$(LDSCRIPT)$(LDSYMBOLS)
+
+OPT_DEFS += -DPROTOCOL_CHIBIOS
+
+MCUFLAGS = -mcpu=$(MCU)
+
+DEBUG = gdb
+
+# Define ASM defines here
+# bootloader definitions may be used in the startup .s file
+ifneq ("$(wildcard $(KEYBOARD_PATH)/bootloader_defs.h)","")
+ OPT_DEFS += -include $(KEYBOARD_PATH)/bootloader_defs.h
+else ifneq ("$(wildcard $(KEYBOARD_PATH)/boards/$(BOARD)/bootloader_defs.h)","")
+ OPT_DEFS += -include $(KEYBOARD_PATH)/boards/$(BOARD)/bootloader_defs.h
+endif
+
+# List any extra directories to look for libraries here.
+EXTRALIBDIRS = $(RULESPATH)/ld \ No newline at end of file
diff --git a/tmk_core/common.mk b/tmk_core/common.mk
index f2a22e4f8c..d71fba9bc1 100644
--- a/tmk_core/common.mk
+++ b/tmk_core/common.mk
@@ -1,4 +1,10 @@
COMMON_DIR = common
+ifeq ($(PLATFORM),AVR)
+ PLATFORM_COMMON_DIR = $(COMMON_DIR)/avr
+else ifeq ($(PLATFORM),CHIBIOS)
+ PLATFORM_COMMON_DIR = $(COMMON_DIR)/chibios
+endif
+
SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/keyboard.c \
$(COMMON_DIR)/action.c \
@@ -9,21 +15,29 @@ SRC += $(COMMON_DIR)/host.c \
$(COMMON_DIR)/print.c \
$(COMMON_DIR)/debug.c \
$(COMMON_DIR)/util.c \
- $(COMMON_DIR)/avr/suspend.c \
- $(COMMON_DIR)/avr/xprintf.S \
- $(COMMON_DIR)/avr/timer.c \
- $(COMMON_DIR)/avr/bootloader.c
+ $(COMMON_DIR)/eeconfig.c \
+ $(PLATFORM_COMMON_DIR)/suspend.c \
+ $(PLATFORM_COMMON_DIR)/timer.c \
+ $(PLATFORM_COMMON_DIR)/bootloader.c \
+
+ifeq ($(PLATFORM),AVR)
+ SRC += $(PLATFORM_COMMON_DIR)/xprintf.S
+endif
+
+ifeq ($(PLATFORM),CHIBIOS)
+ SRC += $(PLATFORM_COMMON_DIR)/printf.c
+ SRC += $(PLATFORM_COMMON_DIR)/eeprom.c
+endif
+
# Option modules
ifeq ($(strip $(BOOTMAGIC_ENABLE)), yes)
OPT_DEFS += -DBOOTMAGIC_ENABLE
SRC += $(COMMON_DIR)/bootmagic.c
- SRC += $(COMMON_DIR)/avr/eeconfig.c
else
OPT_DEFS += -DMAGIC_ENABLE
SRC += $(COMMON_DIR)/magic.c
- SRC += $(COMMON_DIR)/avr/eeconfig.c
endif
ifeq ($(strip $(MOUSEKEY_ENABLE)), yes)
@@ -57,14 +71,13 @@ ifeq ($(strip $(USB_6KRO_ENABLE)), yes)
endif
ifeq ($(strip $(SLEEP_LED_ENABLE)), yes)
- SRC += $(COMMON_DIR)/sleep_led.c
+ SRC += $(PLATFORM_COMMON_DIR)/sleep_led.c
OPT_DEFS += -DSLEEP_LED_ENABLE
OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
endif
ifeq ($(strip $(BACKLIGHT_ENABLE)), yes)
SRC += $(COMMON_DIR)/backlight.c
- SRC += $(COMMON_DIR)/avr/eeconfig.c
OPT_DEFS += -DBACKLIGHT_ENABLE
endif
@@ -87,6 +100,13 @@ endif
# Version string
OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
+# Bootloader address
+ifdef STM32_BOOTLOADER_ADDRESS
+ OPT_DEFS += -DSTM32_BOOTLOADER_ADDRESS=$(STM32_BOOTLOADER_ADDRESS)
+endif
# Search Path
VPATH += $(TMK_PATH)/$(COMMON_DIR)
+ifeq ($(PLATFORM),CHIBIOS)
+VPATH += $(TMK_PATH)/$(COMMON_DIR)/chibios
+endif \ No newline at end of file
diff --git a/tmk_core/common/action_tapping.c b/tmk_core/common/action_tapping.c
index ff78d7f2ab..e16e11be7f 100644
--- a/tmk_core/common/action_tapping.c
+++ b/tmk_core/common/action_tapping.c
@@ -257,7 +257,7 @@ bool process_tapping(keyrecord_t *keyp)
return true;
}
} else {
- if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
+ if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n") {};
process_record(keyp);
return true;
}
diff --git a/tmk_core/common/sleep_led.c b/tmk_core/common/avr/sleep_led.c
index dab3eb0f3c..dab3eb0f3c 100644
--- a/tmk_core/common/sleep_led.c
+++ b/tmk_core/common/avr/sleep_led.c
diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c
index 30e8a0f20f..90275a18ba 100644
--- a/tmk_core/common/bootmagic.c
+++ b/tmk_core/common/bootmagic.c
@@ -1,6 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include <util/delay.h>
+#include "wait.h"
#include "matrix.h"
#include "bootloader.h"
#include "debug.h"
@@ -10,6 +10,7 @@
#include "eeconfig.h"
#include "bootmagic.h"
+keymap_config_t keymap_config;
void bootmagic(void)
{
@@ -19,9 +20,9 @@ void bootmagic(void)
}
/* do scans in case of bounce */
- print("boogmagic scan: ... ");
+ print("bootmagic scan: ... ");
uint8_t scan = 100;
- while (scan--) { matrix_scan(); _delay_ms(10); }
+ while (scan--) { matrix_scan(); wait_ms(10); }
print("done.\n");
/* bootmagic skip */
diff --git a/tmk_core/common/chibios/bootloader.c b/tmk_core/common/chibios/bootloader.c
new file mode 100644
index 0000000000..8a533ab6f6
--- /dev/null
+++ b/tmk_core/common/chibios/bootloader.c
@@ -0,0 +1,47 @@
+#include "bootloader.h"
+
+#include "ch.h"
+#include "hal.h"
+
+#ifdef STM32_BOOTLOADER_ADDRESS
+/* STM32 */
+
+#if defined(STM32F0XX)
+/* This code should be checked whether it runs correctly on platforms */
+#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
+extern uint32_t __ram0_end__;
+
+void bootloader_jump(void) {
+ *((unsigned long *)(SYMVAL(__ram0_end__) - 4)) = 0xDEADBEEF; // set magic flag => reset handler will jump into boot loader
+ NVIC_SystemReset();
+}
+
+#else /* defined(STM32F0XX) */
+#error Check that the bootloader code works on your platform and add it to bootloader.c!
+#endif /* defined(STM32F0XX) */
+
+#elif defined(KL2x) || defined(K20x) /* STM32_BOOTLOADER_ADDRESS */
+/* Kinetis */
+
+#if defined(KIIBOHD_BOOTLOADER)
+/* Kiibohd Bootloader (MCHCK and Infinity KB) */
+#define SCB_AIRCR_VECTKEY_WRITEMAGIC 0x05FA0000
+const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff";
+void bootloader_jump(void) {
+ __builtin_memcpy((void *)VBAT, (const void *)sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic));
+ // request reset
+ SCB->AIRCR = SCB_AIRCR_VECTKEY_WRITEMAGIC | SCB_AIRCR_SYSRESETREQ_Msk;
+}
+
+#else /* defined(KIIBOHD_BOOTLOADER) */
+/* Default for Kinetis - expecting an ARM Teensy */
+void bootloader_jump(void) {
+ chThdSleepMilliseconds(100);
+ __BKPT(0);
+}
+#endif /* defined(KIIBOHD_BOOTLOADER) */
+
+#else /* neither STM32 nor KINETIS */
+__attribute__((weak))
+void bootloader_jump(void) {}
+#endif \ No newline at end of file
diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom.c
new file mode 100644
index 0000000000..5ff8ee86f4
--- /dev/null
+++ b/tmk_core/common/chibios/eeprom.c
@@ -0,0 +1,588 @@
+#include "ch.h"
+#include "hal.h"
+
+#include "eeconfig.h"
+
+/*************************************/
+/* Hardware backend */
+/* */
+/* Code from PJRC/Teensyduino */
+/*************************************/
+
+/* Teensyduino Core Library
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2013 PJRC.COM, LLC.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 2. If the Software is incorporated into a build system that allows
+ * selection among a list of target devices, then similar target
+ * devices manufactured by PJRC.COM must be included in the list of
+ * target devices and selectable in the same manner.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+
+#if defined(K20x) /* chip selection */
+/* Teensy 3.0, 3.1, 3.2; mchck; infinity keyboard */
+
+// The EEPROM is really RAM with a hardware-based backup system to
+// flash memory. Selecting a smaller size EEPROM allows more wear
+// leveling, for higher write endurance. If you edit this file,
+// set this to the smallest size your application can use. Also,
+// due to Freescale's implementation, writing 16 or 32 bit words
+// (aligned to 2 or 4 byte boundaries) has twice the endurance
+// compared to writing 8 bit bytes.
+//
+#define EEPROM_SIZE 32
+
+// Writing unaligned 16 or 32 bit data is handled automatically when
+// this is defined, but at a cost of extra code size. Without this,
+// any unaligned write will cause a hard fault exception! If you're
+// absolutely sure all 16 and 32 bit writes will be aligned, you can
+// remove the extra unnecessary code.
+//
+#define HANDLE_UNALIGNED_WRITES
+
+// Minimum EEPROM Endurance
+// ------------------------
+#if (EEPROM_SIZE == 2048) // 35000 writes/byte or 70000 writes/word
+ #define EEESIZE 0x33
+#elif (EEPROM_SIZE == 1024) // 75000 writes/byte or 150000 writes/word
+ #define EEESIZE 0x34
+#elif (EEPROM_SIZE == 512) // 155000 writes/byte or 310000 writes/word
+ #define EEESIZE 0x35
+#elif (EEPROM_SIZE == 256) // 315000 writes/byte or 630000 writes/word
+ #define EEESIZE 0x36
+#elif (EEPROM_SIZE == 128) // 635000 writes/byte or 1270000 writes/word
+ #define EEESIZE 0x37
+#elif (EEPROM_SIZE == 64) // 1275000 writes/byte or 2550000 writes/word
+ #define EEESIZE 0x38
+#elif (EEPROM_SIZE == 32) // 2555000 writes/byte or 5110000 writes/word
+ #define EEESIZE 0x39
+#endif
+
+void eeprom_initialize(void)
+{
+ uint32_t count=0;
+ uint16_t do_flash_cmd[] = {
+ 0xf06f, 0x037f, 0x7003, 0x7803,
+ 0xf013, 0x0f80, 0xd0fb, 0x4770};
+ uint8_t status;
+
+ if (FTFL->FCNFG & FTFL_FCNFG_RAMRDY) {
+ // FlexRAM is configured as traditional RAM
+ // We need to reconfigure for EEPROM usage
+ FTFL->FCCOB0 = 0x80; // PGMPART = Program Partition Command
+ FTFL->FCCOB4 = EEESIZE; // EEPROM Size
+ FTFL->FCCOB5 = 0x03; // 0K for Dataflash, 32K for EEPROM backup
+ __disable_irq();
+ // do_flash_cmd() must execute from RAM. Luckily the C syntax is simple...
+ (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFL->FSTAT));
+ __enable_irq();
+ status = FTFL->FSTAT;
+ if (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL)) {
+ FTFL->FSTAT = (status & (FTFL_FSTAT_RDCOLERR|FTFL_FSTAT_ACCERR|FTFL_FSTAT_FPVIOL));
+ return; // error
+ }
+ }
+ // wait for eeprom to become ready (is this really necessary?)
+ while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
+ if (++count > 20000) break;
+ }
+}
+
+#define FlexRAM ((uint8_t *)0x14000000)
+
+uint8_t eeprom_read_byte(const uint8_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return FlexRAM[offset];
+}
+
+uint16_t eeprom_read_word(const uint16_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE-1) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return *(uint16_t *)(&FlexRAM[offset]);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ if (offset >= EEPROM_SIZE-3) return 0;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ return *(uint32_t *)(&FlexRAM[offset]);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len)
+{
+ uint32_t offset = (uint32_t)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ uint32_t end = offset + len;
+
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (end > EEPROM_SIZE) end = EEPROM_SIZE;
+ while (offset < end) {
+ *dest++ = FlexRAM[offset++];
+ }
+}
+
+int eeprom_is_ready(void)
+{
+ return (FTFL->FCNFG & FTFL_FCNFG_EEERDY) ? 1 : 0;
+}
+
+static void flexram_wait(void)
+{
+ while (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) {
+ // TODO: timeout
+ }
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE-1) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+#ifdef HANDLE_UNALIGNED_WRITES
+ if ((offset & 1) == 0) {
+#endif
+ if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ *(uint16_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+#ifdef HANDLE_UNALIGNED_WRITES
+ } else {
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+ if (FlexRAM[offset + 1] != (value >> 8)) {
+ FlexRAM[offset + 1] = value >> 8;
+ flexram_wait();
+ }
+ }
+#endif
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value)
+{
+ uint32_t offset = (uint32_t)addr;
+
+ if (offset >= EEPROM_SIZE-3) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+#ifdef HANDLE_UNALIGNED_WRITES
+ switch (offset & 3) {
+ case 0:
+#endif
+ if (*(uint32_t *)(&FlexRAM[offset]) != value) {
+ *(uint32_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+ return;
+#ifdef HANDLE_UNALIGNED_WRITES
+ case 2:
+ if (*(uint16_t *)(&FlexRAM[offset]) != value) {
+ *(uint16_t *)(&FlexRAM[offset]) = value;
+ flexram_wait();
+ }
+ if (*(uint16_t *)(&FlexRAM[offset + 2]) != (value >> 16)) {
+ *(uint16_t *)(&FlexRAM[offset + 2]) = value >> 16;
+ flexram_wait();
+ }
+ return;
+ default:
+ if (FlexRAM[offset] != value) {
+ FlexRAM[offset] = value;
+ flexram_wait();
+ }
+ if (*(uint16_t *)(&FlexRAM[offset + 1]) != (value >> 8)) {
+ *(uint16_t *)(&FlexRAM[offset + 1]) = value >> 8;
+ flexram_wait();
+ }
+ if (FlexRAM[offset + 3] != (value >> 24)) {
+ FlexRAM[offset + 3] = value >> 24;
+ flexram_wait();
+ }
+ }
+#endif
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!(FTFL->FCNFG & FTFL_FCNFG_EEERDY)) eeprom_initialize();
+ if (len >= EEPROM_SIZE) len = EEPROM_SIZE;
+ if (offset + len >= EEPROM_SIZE) len = EEPROM_SIZE - offset;
+ while (len > 0) {
+ uint32_t lsb = offset & 3;
+ if (lsb == 0 && len >= 4) {
+ // write aligned 32 bits
+ uint32_t val32;
+ val32 = *src++;
+ val32 |= (*src++ << 8);
+ val32 |= (*src++ << 16);
+ val32 |= (*src++ << 24);
+ if (*(uint32_t *)(&FlexRAM[offset]) != val32) {
+ *(uint32_t *)(&FlexRAM[offset]) = val32;
+ flexram_wait();
+ }
+ offset += 4;
+ len -= 4;
+ } else if ((lsb == 0 || lsb == 2) && len >= 2) {
+ // write aligned 16 bits
+ uint16_t val16;
+ val16 = *src++;
+ val16 |= (*src++ << 8);
+ if (*(uint16_t *)(&FlexRAM[offset]) != val16) {
+ *(uint16_t *)(&FlexRAM[offset]) = val16;
+ flexram_wait();
+ }
+ offset += 2;
+ len -= 2;
+ } else {
+ // write 8 bits
+ uint8_t val8 = *src++;
+ if (FlexRAM[offset] != val8) {
+ FlexRAM[offset] = val8;
+ flexram_wait();
+ }
+ offset++;
+ len--;
+ }
+ }
+}
+
+/*
+void do_flash_cmd(volatile uint8_t *fstat)
+{
+ *fstat = 0x80;
+ while ((*fstat & 0x80) == 0) ; // wait
+}
+00000000 <do_flash_cmd>:
+ 0: f06f 037f mvn.w r3, #127 ; 0x7f
+ 4: 7003 strb r3, [r0, #0]
+ 6: 7803 ldrb r3, [r0, #0]
+ 8: f013 0f80 tst.w r3, #128 ; 0x80
+ c: d0fb beq.n 6 <do_flash_cmd+0x6>
+ e: 4770 bx lr
+*/
+
+#elif defined(KL2x) /* chip selection */
+/* Teensy LC (emulated) */
+
+#define SYMVAL(sym) (uint32_t)(((uint8_t *)&(sym)) - ((uint8_t *)0))
+
+extern uint32_t __eeprom_workarea_start__;
+extern uint32_t __eeprom_workarea_end__;
+
+#define EEPROM_SIZE 128
+
+static uint32_t flashend = 0;
+
+void eeprom_initialize(void)
+{
+ const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
+
+ do {
+ if (*p++ == 0xFFFF) {
+ flashend = (uint32_t)(p - 2);
+ return;
+ }
+ } while (p < (uint16_t *)SYMVAL(__eeprom_workarea_end__));
+ flashend = (uint32_t)((uint16_t *)SYMVAL(__eeprom_workarea_end__) - 1);
+}
+
+uint8_t eeprom_read_byte(const uint8_t *addr)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint16_t *p = (uint16_t *)SYMVAL(__eeprom_workarea_start__);
+ const uint16_t *end = (const uint16_t *)((uint32_t)flashend);
+ uint16_t val;
+ uint8_t data=0xFF;
+
+ if (!end) {
+ eeprom_initialize();
+ end = (const uint16_t *)((uint32_t)flashend);
+ }
+ if (offset < EEPROM_SIZE) {
+ while (p <= end) {
+ val = *p++;
+ if ((val & 255) == offset) data = val >> 8;
+ }
+ }
+ return data;
+}
+
+static void flash_write(const uint16_t *code, uint32_t addr, uint32_t data)
+{
+ // with great power comes great responsibility....
+ uint32_t stat;
+ *(uint32_t *)&(FTFA->FCCOB3) = 0x06000000 | (addr & 0x00FFFFFC);
+ *(uint32_t *)&(FTFA->FCCOB7) = data;
+ __disable_irq();
+ (*((void (*)(volatile uint8_t *))((uint32_t)code | 1)))(&(FTFA->FSTAT));
+ __enable_irq();
+ stat = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);
+ if (stat) {
+ FTFA->FSTAT = stat;
+ }
+ MCM->PLACR |= MCM_PLACR_CFCC;
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t data)
+{
+ uint32_t offset = (uint32_t)addr;
+ const uint16_t *p, *end = (const uint16_t *)((uint32_t)flashend);
+ uint32_t i, val, flashaddr;
+ uint16_t do_flash_cmd[] = {
+ 0x2380, 0x7003, 0x7803, 0xb25b, 0x2b00, 0xdafb, 0x4770};
+ uint8_t buf[EEPROM_SIZE];
+
+ if (offset >= EEPROM_SIZE) return;
+ if (!end) {
+ eeprom_initialize();
+ end = (const uint16_t *)((uint32_t)flashend);
+ }
+ if (++end < (uint16_t *)SYMVAL(__eeprom_workarea_end__)) {
+ val = (data << 8) | offset;
+ flashaddr = (uint32_t)end;
+ flashend = flashaddr;
+ if ((flashaddr & 2) == 0) {
+ val |= 0xFFFF0000;
+ } else {
+ val <<= 16;
+ val |= 0x0000FFFF;
+ }
+ flash_write(do_flash_cmd, flashaddr, val);
+ } else {
+ for (i=0; i < EEPROM_SIZE; i++) {
+ buf[i] = 0xFF;
+ }
+ val = 0;
+ for (p = (uint16_t *)SYMVAL(__eeprom_workarea_start__); p < (uint16_t *)SYMVAL(__eeprom_workarea_end__); p++) {
+ val = *p;
+ if ((val & 255) < EEPROM_SIZE) {
+ buf[val & 255] = val >> 8;
+ }
+ }
+ buf[offset] = data;
+ for (flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__); flashaddr < (uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_end__); flashaddr += 1024) {
+ *(uint32_t *)&(FTFA->FCCOB3) = 0x09000000 | flashaddr;
+ __disable_irq();
+ (*((void (*)(volatile uint8_t *))((uint32_t)do_flash_cmd | 1)))(&(FTFA->FSTAT));
+ __enable_irq();
+ val = FTFA->FSTAT & (FTFA_FSTAT_RDCOLERR|FTFA_FSTAT_ACCERR|FTFA_FSTAT_FPVIOL);;
+ if (val) FTFA->FSTAT = val;
+ MCM->PLACR |= MCM_PLACR_CFCC;
+ }
+ flashaddr=(uint32_t)(uint16_t *)SYMVAL(__eeprom_workarea_start__);
+ for (i=0; i < EEPROM_SIZE; i++) {
+ if (buf[i] == 0xFF) continue;
+ if ((flashaddr & 2) == 0) {
+ val = (buf[i] << 8) | i;
+ } else {
+ val = val | (buf[i] << 24) | (i << 16);
+ flash_write(do_flash_cmd, flashaddr, val);
+ }
+ flashaddr += 2;
+ }
+ flashend = flashaddr;
+ if ((flashaddr & 2)) {
+ val |= 0xFFFF0000;
+ flash_write(do_flash_cmd, flashaddr, val);
+ }
+ }
+}
+
+/*
+void do_flash_cmd(volatile uint8_t *fstat)
+{
+ *fstat = 0x80;
+ while ((*fstat & 0x80) == 0) ; // wait
+}
+00000000 <do_flash_cmd>:
+ 0: 2380 movs r3, #128 ; 0x80
+ 2: 7003 strb r3, [r0, #0]
+ 4: 7803 ldrb r3, [r0, #0]
+ 6: b25b sxtb r3, r3
+ 8: 2b00 cmp r3, #0
+ a: dafb bge.n 4 <do_flash_cmd+0x4>
+ c: 4770 bx lr
+*/
+
+
+uint16_t eeprom_read_word(const uint16_t *addr)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
+ | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len)
+{
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+int eeprom_is_ready(void)
+{
+ return 1;
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value)
+{
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value)
+{
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len)
+{
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+#else
+// No EEPROM supported, so emulate it
+
+#define EEPROM_SIZE 32
+static uint8_t buffer[EEPROM_SIZE];
+
+uint8_t eeprom_read_byte(const uint8_t *addr) {
+ uint32_t offset = (uint32_t)addr;
+ return buffer[offset];
+}
+
+void eeprom_write_byte(uint8_t *addr, uint8_t value) {
+ uint32_t offset = (uint32_t)addr;
+ buffer[offset] = value;
+}
+
+uint16_t eeprom_read_word(const uint16_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8);
+}
+
+uint32_t eeprom_read_dword(const uint32_t *addr) {
+ const uint8_t *p = (const uint8_t *)addr;
+ return eeprom_read_byte(p) | (eeprom_read_byte(p+1) << 8)
+ | (eeprom_read_byte(p+2) << 16) | (eeprom_read_byte(p+3) << 24);
+}
+
+void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
+ const uint8_t *p = (const uint8_t *)addr;
+ uint8_t *dest = (uint8_t *)buf;
+ while (len--) {
+ *dest++ = eeprom_read_byte(p++);
+ }
+}
+
+void eeprom_write_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_write_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
+
+#endif /* chip selection */
+// The update functions just calls write for now, but could probably be optimized
+
+void eeprom_update_byte(uint8_t *addr, uint8_t value) {
+ eeprom_write_byte(addr, value);
+}
+
+void eeprom_update_word(uint16_t *addr, uint16_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p, value >> 8);
+}
+
+void eeprom_update_dword(uint32_t *addr, uint32_t value) {
+ uint8_t *p = (uint8_t *)addr;
+ eeprom_write_byte(p++, value);
+ eeprom_write_byte(p++, value >> 8);
+ eeprom_write_byte(p++, value >> 16);
+ eeprom_write_byte(p, value >> 24);
+}
+
+void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
+ uint8_t *p = (uint8_t *)addr;
+ const uint8_t *src = (const uint8_t *)buf;
+ while (len--) {
+ eeprom_write_byte(p++, *src++);
+ }
+}
diff --git a/tmk_core/common/chibios/printf.c b/tmk_core/common/chibios/printf.c
new file mode 100644
index 0000000000..72e3d4f8c4
--- /dev/null
+++ b/tmk_core/common/chibios/printf.c
@@ -0,0 +1,240 @@
+/*
+ * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
+ * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
+ */
+
+/*
+File: printf.c
+
+Copyright (C) 2004 Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+*/
+
+#include "printf.h"
+
+typedef void (*putcf) (void*,char);
+static putcf stdout_putf;
+static void* stdout_putp;
+
+// this adds cca 400 bytes
+#define PRINTF_LONG_SUPPORT
+
+#ifdef PRINTF_LONG_SUPPORT
+
+static void uli2a(unsigned long int num, unsigned int base, int uc,char * bf)
+ {
+ int n=0;
+ unsigned int d=1;
+ while (num/d >= base)
+ d*=base;
+ while (d!=0) {
+ int dgt = num / d;
+ num%=d;
+ d/=base;
+ if (n || dgt>0|| d==0) {
+ *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
+ ++n;
+ }
+ }
+ *bf=0;
+ }
+
+static void li2a (long num, char * bf)
+ {
+ if (num<0) {
+ num=-num;
+ *bf++ = '-';
+ }
+ uli2a(num,10,0,bf);
+ }
+
+#endif
+
+static void ui2a(unsigned int num, unsigned int base, int uc,char * bf)
+ {
+ int n=0;
+ unsigned int d=1;
+ while (num/d >= base)
+ d*=base;
+ while (d!=0) {
+ int dgt = num / d;
+ num%= d;
+ d/=base;
+ if (n || dgt>0 || d==0) {
+ *bf++ = dgt+(dgt<10 ? '0' : (uc ? 'A' : 'a')-10);
+ ++n;
+ }
+ }
+ *bf=0;
+ }
+
+static void i2a (int num, char * bf)
+ {
+ if (num<0) {
+ num=-num;
+ *bf++ = '-';
+ }
+ ui2a(num,10,0,bf);
+ }
+
+static int a2d(char ch)
+ {
+ if (ch>='0' && ch<='9')
+ return ch-'0';
+ else if (ch>='a' && ch<='f')
+ return ch-'a'+10;
+ else if (ch>='A' && ch<='F')
+ return ch-'A'+10;
+ else return -1;
+ }
+
+static char a2i(char ch, char** src,int base,int* nump)
+ {
+ char* p= *src;
+ int num=0;
+ int digit;
+ while ((digit=a2d(ch))>=0) {
+ if (digit>base) break;
+ num=num*base+digit;
+ ch=*p++;
+ }
+ *src=p;
+ *nump=num;
+ return ch;
+ }
+
+static void putchw(void* putp,putcf putf,int n, char z, char* bf)
+ {
+ char fc=z? '0' : ' ';
+ char ch;
+ char* p=bf;
+ while (*p++ && n > 0)
+ n--;
+ while (n-- > 0)
+ putf(putp,fc);
+ while ((ch= *bf++))
+ putf(putp,ch);
+ }
+
+void tfp_format(void* putp,putcf putf,char *fmt, va_list va)
+ {
+ char bf[12];
+
+ char ch;
+
+
+ while ((ch=*(fmt++))) {
+ if (ch!='%')
+ putf(putp,ch);
+ else {
+ char lz=0;
+#ifdef PRINTF_LONG_SUPPORT
+ char lng=0;
+#endif
+ int w=0;
+ ch=*(fmt++);
+ if (ch=='0') {
+ ch=*(fmt++);
+ lz=1;
+ }
+ if (ch>='0' && ch<='9') {
+ ch=a2i(ch,&fmt,10,&w);
+ }
+#ifdef PRINTF_LONG_SUPPORT
+ if (ch=='l') {
+ ch=*(fmt++);
+ lng=1;
+ }
+#endif
+ switch (ch) {
+ case 0:
+ goto abort;
+ case 'u' : {
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ uli2a(va_arg(va, unsigned long int),10,0,bf);
+ else
+#endif
+ ui2a(va_arg(va, unsigned int),10,0,bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ }
+ case 'd' : {
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ li2a(va_arg(va, unsigned long int),bf);
+ else
+#endif
+ i2a(va_arg(va, int),bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ }
+ case 'x': case 'X' :
+#ifdef PRINTF_LONG_SUPPORT
+ if (lng)
+ uli2a(va_arg(va, unsigned long int),16,(ch=='X'),bf);
+ else
+#endif
+ ui2a(va_arg(va, unsigned int),16,(ch=='X'),bf);
+ putchw(putp,putf,w,lz,bf);
+ break;
+ case 'c' :
+ putf(putp,(char)(va_arg(va, int)));
+ break;
+ case 's' :
+ putchw(putp,putf,w,0,va_arg(va, char*));
+ break;
+ case '%' :
+ putf(putp,ch);
+ default:
+ break;
+ }
+ }
+ }
+ abort:;
+ }
+
+
+void init_printf(void* putp,void (*putf) (void*,char))
+ {
+ stdout_putf=putf;
+ stdout_putp=putp;
+ }
+
+void tfp_printf(char *fmt, ...)
+ {
+ va_list va;
+ va_start(va,fmt);
+ tfp_format(stdout_putp,stdout_putf,fmt,va);
+ va_end(va);
+ }
+
+static void putcp(void* p,char c)
+ {
+ *(*((char**)p))++ = c;
+ }
+
+
+
+void tfp_sprintf(char* s,char *fmt, ...)
+ {
+ va_list va;
+ va_start(va,fmt);
+ tfp_format(&s,putcp,fmt,va);
+ putcp(&s,0);
+ va_end(va);
+ }
diff --git a/tmk_core/common/chibios/printf.h b/tmk_core/common/chibios/printf.h
new file mode 100644
index 0000000000..678a100c6e
--- /dev/null
+++ b/tmk_core/common/chibios/printf.h
@@ -0,0 +1,111 @@
+/*
+ * found at: http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
+ * and: http://www.sparetimelabs.com/printfrevisited/printfrevisited.php
+ */
+
+/*
+File: printf.h
+
+Copyright (C) 2004 Kustaa Nyholm
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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 Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+This library is realy just two files: 'printf.h' and 'printf.c'.
+
+They provide a simple and small (+200 loc) printf functionality to
+be used in embedded systems.
+
+I've found them so usefull in debugging that I do not bother with a
+debugger at all.
+
+They are distributed in source form, so to use them, just compile them
+into your project.
+
+Two printf variants are provided: printf and sprintf.
+
+The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
+
+Zero padding and field width are also supported.
+
+If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
+long specifier is also
+supported. Note that this will pull in some long math routines (pun intended!)
+and thus make your executable noticably longer.
+
+The memory foot print of course depends on the target cpu, compiler and
+compiler options, but a rough guestimate (based on a H8S target) is about
+1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
+Not too bad. Your milage may vary. By hacking the source code you can
+get rid of some hunred bytes, I'm sure, but personally I feel the balance of
+functionality and flexibility versus code size is close to optimal for
+many embedded systems.
+
+To use the printf you need to supply your own character output function,
+something like :
+
+ void putc ( void* p, char c)
+ {
+ while (!SERIAL_PORT_EMPTY) ;
+ SERIAL_PORT_TX_REGISTER = c;
+ }
+
+Before you can call printf you need to initialize it to use your
+character output function with something like:
+
+ init_printf(NULL,putc);
+
+Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
+the NULL (or any pointer) you pass into the 'init_printf' will eventually be
+passed to your 'putc' routine. This allows you to pass some storage space (or
+anything realy) to the character output function, if necessary.
+This is not often needed but it was implemented like that because it made
+implementing the sprintf function so neat (look at the source code).
+
+The code is re-entrant, except for the 'init_printf' function, so it
+is safe to call it from interupts too, although this may result in mixed output.
+If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
+
+The printf and sprintf functions are actually macros that translate to
+'tfp_printf' and 'tfp_sprintf'. This makes it possible
+to use them along with 'stdio.h' printf's in a single source file.
+You just need to undef the names before you include the 'stdio.h'.
+Note that these are not function like macros, so if you have variables
+or struct members with these names, things will explode in your face.
+Without variadic macros this is the best we can do to wrap these
+fucnction. If it is a problem just give up the macros and use the
+functions directly or rename them.
+
+For further details see source code.
+
+regs Kusti, 23.10.2004
+*/
+
+
+#ifndef __TFP_PRINTF__
+#define __TFP_PRINTF__
+
+#include <stdarg.h>
+
+void init_printf(void* putp,void (*putf) (void*,char));
+
+void tfp_printf(char *fmt, ...);
+void tfp_sprintf(char* s,char *fmt, ...);
+
+void tfp_format(void* putp,void (*putf) (void*,char),char *fmt, va_list va);
+
+#define printf tfp_printf
+#define sprintf tfp_sprintf
+
+#endif
diff --git a/tmk_core/common/chibios/sleep_led.c b/tmk_core/common/chibios/sleep_led.c
new file mode 100644
index 0000000000..4c35cfcbac
--- /dev/null
+++ b/tmk_core/common/chibios/sleep_led.c
@@ -0,0 +1,226 @@
+#include "ch.h"
+#include "hal.h"
+
+#include "led.h"
+#include "sleep_led.h"
+
+/* All right, we go the "software" way: timer, toggle LED in interrupt.
+ * Based on hasu's code for AVRs.
+ * Use LP timer on Kinetises, TIM14 on STM32F0.
+ */
+
+#if defined(KL2x) || defined(K20x)
+
+/* Use Low Power Timer (LPTMR) */
+#define TIMER_INTERRUPT_VECTOR KINETIS_LPTMR0_IRQ_VECTOR
+#define RESET_COUNTER LPTMR0->CSR |= LPTMRx_CSR_TCF
+
+#elif defined(STM32F0XX)
+
+/* Use TIM14 manually */
+#define TIMER_INTERRUPT_VECTOR STM32_TIM14_HANDLER
+#define RESET_COUNTER STM32_TIM14->SR &= ~STM32_TIM_SR_UIF
+
+#endif
+
+#if defined(KL2x) || defined(K20x) || defined(STM32F0XX) /* common parts for timers/interrupts */
+
+/* Breathing Sleep LED brighness(PWM On period) table
+ * (64[steps] * 4[duration]) / 64[PWM periods/s] = 4 second breath cycle
+ *
+ * http://www.wolframalpha.com/input/?i=%28sin%28+x%2F64*pi%29**8+*+255%2C+x%3D0+to+63
+ * (0..63).each {|x| p ((sin(x/64.0*PI)**8)*255).to_i }
+ */
+static const uint8_t breathing_table[64] = {
+0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 10,
+15, 23, 32, 44, 58, 74, 93, 113, 135, 157, 179, 199, 218, 233, 245, 252,
+255, 252, 245, 233, 218, 199, 179, 157, 135, 113, 93, 74, 58, 44, 32, 23,
+15, 10, 6, 4, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* interrupt handler */
+OSAL_IRQ_HANDLER(TIMER_INTERRUPT_VECTOR) {
+ OSAL_IRQ_PROLOGUE();
+
+ /* Software PWM
+ * timer:1111 1111 1111 1111
+ * \_____/\/ \_______/____ count(0-255)
+ * \ \______________ duration of step(4)
+ * \__________________ index of step table(0-63)
+ */
+
+ // this works for cca 65536 irqs/sec
+ static union {
+ uint16_t row;
+ struct {
+ uint8_t count:8;
+ uint8_t duration:2;
+ uint8_t index:6;
+ } pwm;
+ } timer = { .row = 0 };
+
+ timer.row++;
+
+ // LED on
+ if (timer.pwm.count == 0) {
+ led_set(1<<USB_LED_CAPS_LOCK);
+ }
+ // LED off
+ if (timer.pwm.count == breathing_table[timer.pwm.index]) {
+ led_set(0);
+ }
+
+ /* Reset the counter */
+ RESET_COUNTER;
+
+ OSAL_IRQ_EPILOGUE();
+}
+
+#endif /* common parts for known platforms */
+
+
+#if defined(KL2x) || defined(K20x) /* platform selection: familiar Kinetis chips */
+
+/* LPTMR clock options */
+#define LPTMR_CLOCK_MCGIRCLK 0 /* 4MHz clock */
+#define LPTMR_CLOCK_LPO 1 /* 1kHz clock */
+#define LPTMR_CLOCK_ERCLK32K 2 /* external 32kHz crystal */
+#define LPTMR_CLOCK_OSCERCLK 3 /* output from OSC */
+
+/* Work around inconsistencies in Freescale naming */
+#if !defined(SIM_SCGC5_LPTMR)
+#define SIM_SCGC5_LPTMR SIM_SCGC5_LPTIMER
+#endif
+
+/* Initialise the timer */
+void sleep_led_init(void) {
+ /* Make sure the clock to the LPTMR is enabled */
+ SIM->SCGC5 |= SIM_SCGC5_LPTMR;
+ /* Reset LPTMR settings */
+ LPTMR0->CSR = 0;
+ /* Set the compare value */
+ LPTMR0->CMR = 0; // trigger on counter value (i.e. every time)
+
+ /* Set up clock source and prescaler */
+ /* Software PWM
+ * ______ ______ __
+ * | ON |___OFF___| ON |___OFF___| ....
+ * |<-------------->|<-------------->|<- ....
+ * PWM period PWM period
+ *
+ * R interrupts/period[resolution]
+ * F periods/second[frequency]
+ * R * F interrupts/second
+ */
+
+ /* === OPTION 1 === */
+ #if 0
+ // 1kHz LPO
+ // No prescaler => 1024 irqs/sec
+ // Note: this is too slow for a smooth breathe
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_LPO)|LPTMRx_PSR_PBYP;
+ #endif /* OPTION 1 */
+
+ /* === OPTION 2 === */
+ #if 1
+ // nMHz IRC (n=4 on KL25Z, KL26Z and K20x; n=2 or 8 on KL27Z)
+ MCG->C2 |= MCG_C2_IRCS; // fast (4MHz) internal ref clock
+ #if defined(KL27) // divide the 8MHz IRC by 2, to have the same MCGIRCLK speed as others
+ MCG->MC |= MCG_MC_LIRC_DIV2_DIV2;
+ #endif /* KL27 */
+ MCG->C1 |= MCG_C1_IRCLKEN; // enable internal ref clock
+ // to work in stop mode, also MCG_C1_IREFSTEN
+ // Divide 4MHz by 2^N (N=6) => 62500 irqs/sec =>
+ // => approx F=61, R=256, duration = 4
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_MCGIRCLK)|LPTMRx_PSR_PRESCALE(6);
+ #endif /* OPTION 2 */
+
+ /* === OPTION 3 === */
+ #if 0
+ // OSC output (external crystal), usually 8MHz or 16MHz
+ OSC0->CR |= OSC_CR_ERCLKEN; // enable ext ref clock
+ // to work in stop mode, also OSC_CR_EREFSTEN
+ // Divide by 2^N
+ LPTMR0->PSR = LPTMRx_PSR_PCS(LPTMR_CLOCK_OSCERCLK)|LPTMRx_PSR_PRESCALE(7);
+ #endif /* OPTION 3 */
+ /* === END OPTIONS === */
+
+ /* Interrupt on TCF set (compare flag) */
+ nvicEnableVector(LPTMR0_IRQn, 2); // vector, priority
+ LPTMR0->CSR |= LPTMRx_CSR_TIE;
+}
+
+void sleep_led_enable(void) {
+ /* Enable the timer */
+ LPTMR0->CSR |= LPTMRx_CSR_TEN;
+}
+
+void sleep_led_disable(void) {
+ /* Disable the timer */
+ LPTMR0->CSR &= ~LPTMRx_CSR_TEN;
+}
+
+void sleep_led_toggle(void) {
+ /* Toggle the timer */
+ LPTMR0->CSR ^= LPTMRx_CSR_TEN;
+}
+
+#elif defined(STM32F0XX) /* platform selection: STM32F0XX */
+
+/* Initialise the timer */
+void sleep_led_init(void) {
+ /* enable clock */
+ rccEnableTIM14(FALSE); /* low power enable = FALSE */
+ rccResetTIM14();
+
+ /* prescale */
+ /* Assuming 48MHz internal clock */
+ /* getting cca 65484 irqs/sec */
+ STM32_TIM14->PSC = 733;
+
+ /* auto-reload */
+ /* 0 => interrupt every time */
+ STM32_TIM14->ARR = 3;
+
+ /* enable counter update event interrupt */
+ STM32_TIM14->DIER |= STM32_TIM_DIER_UIE;
+
+ /* register interrupt vector */
+ nvicEnableVector(STM32_TIM14_NUMBER, 2); /* vector, priority */
+}
+
+void sleep_led_enable(void) {
+ /* Enable the timer */
+ STM32_TIM14->CR1 = STM32_TIM_CR1_CEN | STM32_TIM_CR1_URS;
+ /* URS => update event only on overflow; setting UG bit disabled */
+}
+
+void sleep_led_disable(void) {
+ /* Disable the timer */
+ STM32_TIM14->CR1 = 0;
+}
+
+void sleep_led_toggle(void) {
+ /* Toggle the timer */
+ STM32_TIM14->CR1 ^= STM32_TIM_CR1_CEN;
+}
+
+
+#else /* platform selection: not on familiar chips */
+
+void sleep_led_init(void) {
+}
+
+void sleep_led_enable(void) {
+ led_set(1<<USB_LED_CAPS_LOCK);
+}
+
+void sleep_led_disable(void) {
+ led_set(0);
+}
+
+void sleep_led_toggle(void) {
+ // not implemented
+}
+
+#endif /* platform selection */ \ No newline at end of file
diff --git a/tmk_core/common/chibios/suspend.c b/tmk_core/common/chibios/suspend.c
new file mode 100644
index 0000000000..6ca16034f3
--- /dev/null
+++ b/tmk_core/common/chibios/suspend.c
@@ -0,0 +1,65 @@
+/* TODO */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "matrix.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "host.h"
+#include "backlight.h"
+#include "suspend.h"
+
+void suspend_idle(uint8_t time) {
+ // TODO: this is not used anywhere - what units is 'time' in?
+ chThdSleepMilliseconds(time);
+}
+
+void suspend_power_down(void) {
+ // TODO: figure out what to power down and how
+ // shouldn't power down TPM/FTM if we want a breathing LED
+ // also shouldn't power down USB
+
+ // on AVR, this enables the watchdog for 15ms (max), and goes to
+ // SLEEP_MODE_PWR_DOWN
+
+ chThdSleepMilliseconds(17);
+}
+
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
+bool suspend_wakeup_condition(void)
+{
+ matrix_power_up();
+ matrix_scan();
+ matrix_power_down();
+ for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+ if (matrix_get_row(r)) return true;
+ }
+ return false;
+}
+
+// run immediately after wakeup
+void suspend_wakeup_init(void)
+{
+ // clear keyboard state
+ // need to do it manually, because we're running from ISR
+ // and clear_keyboard() calls print
+ // so only clear the variables in memory
+ // the reports will be sent from main.c afterwards
+ // or if the PC asks for GET_REPORT
+ clear_mods();
+ clear_weak_mods();
+ clear_keys();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_clear();
+#endif /* MOUSEKEY_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ host_system_send(0);
+ host_consumer_send(0);
+#endif /* EXTRAKEY_ENABLE */
+#ifdef BACKLIGHT_ENABLE
+ backlight_init();
+#endif /* BACKLIGHT_ENABLE */
+}
diff --git a/tmk_core/common/chibios/timer.c b/tmk_core/common/chibios/timer.c
new file mode 100644
index 0000000000..3de4cc368b
--- /dev/null
+++ b/tmk_core/common/chibios/timer.c
@@ -0,0 +1,27 @@
+#include "ch.h"
+
+#include "timer.h"
+
+void timer_init(void) {}
+
+void timer_clear(void) {}
+
+uint16_t timer_read(void)
+{
+ return (uint16_t)ST2MS(chVTGetSystemTime());
+}
+
+uint32_t timer_read32(void)
+{
+ return ST2MS(chVTGetSystemTime());
+}
+
+uint16_t timer_elapsed(uint16_t last)
+{
+ return (uint16_t)(ST2MS(chVTTimeElapsedSinceX(MS2ST(last))));
+}
+
+uint32_t timer_elapsed32(uint32_t last)
+{
+ return ST2MS(chVTTimeElapsedSinceX(MS2ST(last)));
+}
diff --git a/tmk_core/common/command.c b/tmk_core/common/command.c
index 187a2b9496..084c9fe155 100644
--- a/tmk_core/common/command.c
+++ b/tmk_core/common/command.c
@@ -16,7 +16,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdbool.h>
-#include <util/delay.h>
+#include "wait.h"
#include "keycode.h"
#include "host.h"
#include "keymap.h"
@@ -103,12 +103,14 @@ bool command_proc(uint8_t code)
bool command_extra(uint8_t code) __attribute__ ((weak));
bool command_extra(uint8_t code)
{
+ (void)code;
return false;
}
bool command_console_extra(uint8_t code) __attribute__ ((weak));
bool command_console_extra(uint8_t code)
{
+ (void)code;
return false;
}
@@ -217,8 +219,11 @@ static void print_version(void)
" " STR(BOOTLOADER_SIZE) "\n");
print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
+#if defined(__AVR__)
" AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
- " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
+ " AVR_ARCH: avr" STR(__AVR_ARCH__)
+#endif
+ "\n");
return;
}
@@ -234,7 +239,7 @@ static void print_status(void)
#ifdef NKRO_ENABLE
print_val_hex8(keyboard_nkro);
#endif
- print_val_hex32(timer_count);
+ print_val_hex32(timer_read32());
#ifdef PROTOCOL_PJRC
print_val_hex8(UDCON);
@@ -360,7 +365,7 @@ static bool command_common(uint8_t code)
stop_all_notes();
shutdown_user();
#else
- _delay_ms(1000);
+ wait_ms(1000);
#endif
bootloader_jump(); // not return
break;
@@ -430,10 +435,11 @@ static bool command_common(uint8_t code)
case MAGIC_KC(MAGIC_KEY_NKRO):
clear_keyboard(); // clear to prevent stuck keys
keyboard_nkro = !keyboard_nkro;
- if (keyboard_nkro)
+ if (keyboard_nkro) {
print("NKRO: on\n");
- else
+ } else {
print("NKRO: off\n");
+ }
break;
#endif
@@ -750,10 +756,11 @@ static bool mousekey_console(uint8_t code)
print("?");
return false;
}
- if (mousekey_param)
+ if (mousekey_param) {
xprintf("M%d> ", mousekey_param);
- else
+ } else {
print("M>" );
+ }
return true;
}
#endif
diff --git a/tmk_core/common/avr/eeconfig.c b/tmk_core/common/eeconfig.c
index 656938fb33..140d2b85bb 100644
--- a/tmk_core/common/avr/eeconfig.c
+++ b/tmk_core/common/eeconfig.c
@@ -1,6 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include <avr/eeprom.h>
+#include "eeprom.h"
#include "eeconfig.h"
void eeconfig_init(void)
diff --git a/tmk_core/common/eeprom.h b/tmk_core/common/eeprom.h
new file mode 100644
index 0000000000..2cc2ccee3f
--- /dev/null
+++ b/tmk_core/common/eeprom.h
@@ -0,0 +1,22 @@
+#ifndef TMK_CORE_COMMON_EEPROM_H_
+#define TMK_CORE_COMMON_EEPROM_H_
+
+#if defined(__AVR__)
+#include <avr/eeprom.h>
+#else
+uint8_t eeprom_read_byte (const uint8_t *__p);
+uint16_t eeprom_read_word (const uint16_t *__p);
+uint32_t eeprom_read_dword (const uint32_t *__p);
+void eeprom_read_block (void *__dst, const void *__src, uint32_t __n);
+void eeprom_write_byte (uint8_t *__p, uint8_t __value);
+void eeprom_write_word (uint16_t *__p, uint16_t __value);
+void eeprom_write_dword (uint32_t *__p, uint32_t __value);
+void eeprom_write_block (const void *__src, void *__dst, uint32_t __n);
+void eeprom_update_byte (uint8_t *__p, uint8_t __value);
+void eeprom_update_word (uint16_t *__p, uint16_t __value);
+void eeprom_update_dword (uint32_t *__p, uint32_t __value);
+void eeprom_update_block (const void *__src, void *__dst, uint32_t __n);
+#endif
+
+
+#endif /* TMK_CORE_COMMON_EEPROM_H_ */
diff --git a/tmk_core/common/magic.c b/tmk_core/common/magic.c
index f21d1346c7..194e4cc026 100644
--- a/tmk_core/common/magic.c
+++ b/tmk_core/common/magic.c
@@ -1,6 +1,8 @@
#include <stdint.h>
#include <stdbool.h>
+#if defined(__AVR__)
#include <util/delay.h>
+#endif
#include "matrix.h"
#include "bootloader.h"
#include "debug.h"
@@ -33,4 +35,4 @@ void magic(void)
default_layer = eeconfig_read_default_layer();
default_layer_set((uint32_t)default_layer);
-} \ No newline at end of file
+}
diff --git a/tmk_core/common/print.c b/tmk_core/common/print.c
index ca94e1e5d6..00489557f2 100644
--- a/tmk_core/common/print.c
+++ b/tmk_core/common/print.c
@@ -38,11 +38,15 @@ void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
xdev_out(sendchar_func);
}
-#elif defined(__arm__)
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+
+// don't need anything extra
+
+#elif defined(__arm__) /* __AVR__ */
// TODO
//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
-#endif
+#endif /* __AVR__ */
#endif
diff --git a/tmk_core/common/print.h b/tmk_core/common/print.h
index 4f3dde65aa..0368bcd4a1 100644
--- a/tmk_core/common/print.h
+++ b/tmk_core/common/print.h
@@ -47,7 +47,15 @@ extern "C"
/* function pointer of sendchar to be used by print utility */
void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
-#elif defined(__arm__)
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+
+#include "chibios/printf.h"
+
+#define print(s) printf(s)
+#define println(s) printf(s "\r\n")
+#define xprintf printf
+
+#elif defined(__arm__) /* __AVR__ */
#include "mbed/xprintf.h"
diff --git a/tmk_core/common/progmem.h b/tmk_core/common/progmem.h
index 199b1bedfe..5b27656250 100644
--- a/tmk_core/common/progmem.h
+++ b/tmk_core/common/progmem.h
@@ -5,8 +5,8 @@
# include <avr/pgmspace.h>
#elif defined(__arm__)
# define PROGMEM
-# define pgm_read_byte(p) *(p)
-# define pgm_read_word(p) *(p)
+# define pgm_read_byte(p) *((unsigned char*)p)
+# define pgm_read_word(p) *((uint16_t*)p)
#endif
#endif
diff --git a/tmk_core/common/report.h b/tmk_core/common/report.h
index f6c0a315de..0c799eca39 100644
--- a/tmk_core/common/report.h
+++ b/tmk_core/common/report.h
@@ -84,6 +84,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
+#elif defined(PROTOCOL_CHIBIOS) && defined(NKRO_ENABLE)
+# include "protocol/chibios/usb_main.h"
+# define KEYBOARD_REPORT_SIZE NKRO_EPSIZE
+# define KEYBOARD_REPORT_KEYS (NKRO_EPSIZE - 2)
+# define KEYBOARD_REPORT_BITS (NKRO_EPSIZE - 1)
#else
# define KEYBOARD_REPORT_SIZE 8
diff --git a/tmk_core/common/wait.h b/tmk_core/common/wait.h
index 40d00b0c75..82727be012 100644
--- a/tmk_core/common/wait.h
+++ b/tmk_core/common/wait.h
@@ -9,9 +9,13 @@ extern "C" {
# include <util/delay.h>
# define wait_ms(ms) _delay_ms(ms)
# define wait_us(us) _delay_us(us)
-#elif defined(__arm__)
+#elif defined(PROTOCOL_CHIBIOS) /* __AVR__ */
+# include "ch.h"
+# define wait_ms(ms) chThdSleepMilliseconds(ms)
+# define wait_us(us) chThdSleepMicroseconds(us)
+#elif defined(__arm__) /* __AVR__ */
# include "wait_api.h"
-#endif
+#endif /* __AVR__ */
#ifdef __cplusplus
}
diff --git a/tmk_core/protocol/chibios.mk b/tmk_core/protocol/chibios.mk
new file mode 100644
index 0000000000..3f4e0a71fc
--- /dev/null
+++ b/tmk_core/protocol/chibios.mk
@@ -0,0 +1,10 @@
+PROTOCOL_DIR = protocol
+CHIBIOS_DIR = $(PROTOCOL_DIR)/chibios
+
+
+SRC += $(CHIBIOS_DIR)/usb_main.c
+SRC += $(CHIBIOS_DIR)/main.c
+
+VPATH += $(TMK_PATH)/$(PROTOCOL_DIR)
+VPATH += $(TMK_PATH)/$(CHIBIOS_DIR)
+
diff --git a/tmk_core/protocol/chibios/README.md b/tmk_core/protocol/chibios/README.md
new file mode 100644
index 0000000000..63e6641f82
--- /dev/null
+++ b/tmk_core/protocol/chibios/README.md
@@ -0,0 +1,55 @@
+## TMK running on top of ChibiOS
+
+This code can be used to run TMK keyboard logic on top of [ChibiOS], meaning that you can run TMK on whatever [ChibiOS] supports. The notable examples are ARM-based Teensies (3.x and LC) and on the boards with STM32 MCUs.
+
+### Usage
+
+- To use, [get a zip of chibios](https://github.com/ChibiOS/ChibiOS/archive/a7df9a891067621e8e1a5c2a2c0ceada82403afe.zip) and unpack/rename it to `tmk_core/tool/chibios/chibios`; or you can just clone [the repo](https://github.com/ChibiOS/ChibiOS) there. For Freescale/NXP Kinetis support (meaning ARM Teensies and the Infinity keyboard), you'll also need [a zip of chibios-contrib](https://github.com/ChibiOS/ChibiOS-Contrib/archive/e1311c4db6cd366cf760673f769e925741ac0ad3.zip), unpacked/renamed to `tmk_core/tool/chibios/chibios-contrib`. Likewise, for git-savvy people, just clone [the repo](https://github.com/ChibiOS/ChibiOS-Contrib) there.
+- Note: the abovementioned directories are the defaults. You can have the two chibios repositories wherever you want, just define their location in `CHIBIOS` and `CHIBIOS_CONTRIB` variables in your `Makefile`.
+- You will also need to install an ARM toolchain, for instance from [here](https://launchpad.net/gcc-arm-embedded). On linux, this is usually also present as a package for your distribution (as `gcc-arm` or something similar). On OS X, you can use [homebrew](http://brew.sh/) with an appropriate tap.
+
+### Notes
+
+- Some comments about ChibiOS syntax and the most commonly used GPIO functions are, as well as an example for ARM Teensies, is [here](https://github.com/tmk/tmk_keyboard/blob/master/keyboard/teensy_lc_onekey/instructions.md).
+- For gcc options, inspect `tmk_core/tool/chibios/chibios.mk`. For instance, I enabled `-Wno-missing-field-initializers`, because TMK common bits generated a lot of warnings on that.
+- For debugging, it is sometimes useful disable gcc optimisations, you can do that by adding `-O0` to `OPT_DEFS` in your `Makefile`.
+- USB string descriptors are messy. I did not find a way to cleanly generate the right structures from actual strings, so the definitions in individual keyboards' `config.h` are ugly as heck.
+- It is easy to add some code for testing (e.g. blink LED, do stuff on button press, etc...) - just create another thread in `main.c`, it will run independently of the keyboard business.
+- Jumping to (the built-in) bootloaders on STM32 works, but it is not entirely pleasant, since it is very much MCU dependent. So, one needs to dig out the right address to jump to, and either pass it to the compiler in the `Makefile`, or better, define it in `<your_kb>/bootloader_defs.h`. An additional startup code is also needed; the best way to deal with this is to define custom board files. (Example forthcoming.) In any case, there are no problems for Teensies.
+
+
+### Immediate todo
+
+- power saving for suspend
+
+### Not tested, but possibly working
+
+- backlight
+
+### Missing / not working (TMK vs ChibiOS bits)
+
+- eeprom / bootmagic for STM32 (will be chip dependent; eeprom needs to be emulated in flash, which means less writes; wear-levelling?) There is a semi-official ST "driver" for eeprom, with wear-levelling, but I think it consumes a lot of RAM (like 2 pages, i.e. 1kB or so).
+
+### Tried with
+
+- Infinity, WhiteFox keyboards
+- all ARM-based Teensies
+- some STM32-based boards (e.g. ST-F072RB-DISCOVERY board, STM32F042 breakout board, Maple Mini (STM32F103-based))
+
+## ChibiOS-supported MCUs
+
+- Pretty much all STM32 chips.
+- K20x and KL2x Freescale/NXP chips (i.e. Teensy 3.x/LC, mchck, FRDM-KL2{5,6}Z, FRDM-K20D50M), via the [ChibiOS-Contrib](https://github.com/ChibiOS/ChibiOS-Contrib) repository.
+- There is also support for AVR8, but the USB stack is not implemented for them yet (some news on that front recently though), and also the kernel itself takes about 1k of RAM. I think people managed to get ChibiOS running on atmega32[8p/u4] though.
+- There is also support for Nordic NRF51822 (the chip in Adafruit's Bluefruit bluetooth-low-energy boards), but be aware that that chip does *not* have USB, and the BLE softdevice (i.e. Bluetooth) is not supported directly at the moment.
+
+## STM32-based keyboard design considerations
+
+- STM32F0x2 chips can do crystal-less USB, but they still need a 3.3V voltage regulator.
+- The BOOT0 pin should be tied to GND.
+- For a hardware way of accessing the in-built DFU bootloader, in addition to the reset button, put another button between the BOOT0 pin and 3V3.
+- There is a working example of a STM32F042-based keyboard: [firmware here](https://github.com/flabbergast/flabber_kbs/tree/master/kb45p) and [hardware (kicad) here](https://github.com/flabbergast/kicad/tree/master/kb45p). You can check this example firmware for custom board files, and a more complicated matrix than just one key.
+
+
+
+[ChibiOS]: http://chibios.org
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c
new file mode 100644
index 0000000000..54bb6a8f55
--- /dev/null
+++ b/tmk_core/protocol/chibios/main.c
@@ -0,0 +1,147 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "usb_main.h"
+
+/* TMK includes */
+#include "report.h"
+#include "host.h"
+#include "host_driver.h"
+#include "keyboard.h"
+#include "action.h"
+#include "action_util.h"
+#include "mousekey.h"
+#include "led.h"
+#include "sendchar.h"
+#include "debug.h"
+#include "printf.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#endif
+#include "suspend.h"
+
+
+/* -------------------------
+ * TMK host driver defs
+ * -------------------------
+ */
+
+/* declarations */
+uint8_t keyboard_leds(void);
+void send_keyboard(report_keyboard_t *report);
+void send_mouse(report_mouse_t *report);
+void send_system(uint16_t data);
+void send_consumer(uint16_t data);
+
+/* host struct */
+host_driver_t chibios_driver = {
+ keyboard_leds,
+ send_keyboard,
+ send_mouse,
+ send_system,
+ send_consumer
+};
+
+
+/* TESTING
+ * Amber LED blinker thread, times are in milliseconds.
+ */
+/* set this variable to non-zero anywhere to blink once */
+// uint8_t blinkLed = 0;
+// static THD_WORKING_AREA(waBlinkerThread, 128);
+// static THD_FUNCTION(blinkerThread, arg) {
+// (void)arg;
+// chRegSetThreadName("blinkOrange");
+// while(true) {
+// if(blinkLed) {
+// blinkLed = 0;
+// palSetPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+// chThdSleepMilliseconds(100);
+// palClearPad(TEENSY_PIN13_IOPORT, TEENSY_PIN13);
+// }
+// chThdSleepMilliseconds(100);
+// }
+// }
+
+
+
+/* Main thread
+ */
+int main(void) {
+ /* ChibiOS/RT init */
+ halInit();
+ chSysInit();
+
+ // TESTING
+ // chThdCreateStatic(waBlinkerThread, sizeof(waBlinkerThread), NORMALPRIO, blinkerThread, NULL);
+
+ /* Init USB */
+ init_usb_driver(&USB_DRIVER);
+
+ /* init printf */
+ init_printf(NULL,sendchar_pf);
+
+ /* Wait until the USB is active */
+ while(USB_DRIVER.state != USB_ACTIVE)
+ chThdSleepMilliseconds(50);
+
+ /* Do need to wait here!
+ * Otherwise the next print might start a transfer on console EP
+ * before the USB is completely ready, which sometimes causes
+ * HardFaults.
+ */
+ chThdSleepMilliseconds(50);
+
+ print("USB configured.\n");
+
+ /* init TMK modules */
+ keyboard_init();
+ host_set_driver(&chibios_driver);
+
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_init();
+#endif
+
+ print("Keyboard start.\n");
+
+ /* Main loop */
+ while(true) {
+
+ if(USB_DRIVER.state == USB_SUSPENDED) {
+ print("[s]");
+ while(USB_DRIVER.state == USB_SUSPENDED) {
+ /* Do this in the suspended state */
+ suspend_power_down(); // on AVR this deep sleeps for 15ms
+ /* Remote wakeup */
+ if((USB_DRIVER.status & 2) && suspend_wakeup_condition()) {
+ send_remote_wakeup(&USB_DRIVER);
+ }
+ }
+ /* Woken up */
+ // variables has been already cleared by the wakeup hook
+ send_keyboard_report();
+#ifdef MOUSEKEY_ENABLE
+ mousekey_send();
+#endif /* MOUSEKEY_ENABLE */
+ }
+
+ keyboard_task();
+ }
+}
diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c
new file mode 100644
index 0000000000..e2c9d9bf14
--- /dev/null
+++ b/tmk_core/protocol/chibios/usb_main.c
@@ -0,0 +1,1372 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+#include "ch.h"
+#include "hal.h"
+
+#include "usb_main.h"
+
+#include "host.h"
+#include "debug.h"
+#include "suspend.h"
+#ifdef SLEEP_LED_ENABLE
+#include "sleep_led.h"
+#include "led.h"
+#endif
+
+/* ---------------------------------------------------------
+ * Global interface variables and declarations
+ * ---------------------------------------------------------
+ */
+
+uint8_t keyboard_idle __attribute__((aligned(2))) = 0;
+uint8_t keyboard_protocol __attribute__((aligned(2))) = 1;
+uint16_t keyboard_led_stats __attribute__((aligned(2))) = 0;
+volatile uint16_t keyboard_idle_count = 0;
+static virtual_timer_t keyboard_idle_timer;
+static void keyboard_idle_timer_cb(void *arg);
+#ifdef NKRO_ENABLE
+extern bool keyboard_nkro;
+#endif /* NKRO_ENABLE */
+
+report_keyboard_t keyboard_report_sent = {{0}};
+#ifdef MOUSE_ENABLE
+report_mouse_t mouse_report_blank = {0};
+#endif /* MOUSE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+uint8_t extra_report_blank[3] = {0};
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+/* The emission buffers queue */
+output_buffers_queue_t console_buf_queue;
+static uint8_t console_queue_buffer[BQ_BUFFER_SIZE(CONSOLE_QUEUE_CAPACITY, CONSOLE_EPSIZE)];
+
+static virtual_timer_t console_flush_timer;
+void console_queue_onotify(io_buffers_queue_t *bqp);
+static void console_flush_cb(void *arg);
+#endif /* CONSOLE_ENABLE */
+
+/* ---------------------------------------------------------
+ * Descriptors and USB driver objects
+ * ---------------------------------------------------------
+ */
+
+/* HID specific constants */
+#define USB_DESCRIPTOR_HID 0x21
+#define USB_DESCRIPTOR_HID_REPORT 0x22
+#define HID_GET_REPORT 0x01
+#define HID_GET_IDLE 0x02
+#define HID_GET_PROTOCOL 0x03
+#define HID_SET_REPORT 0x09
+#define HID_SET_IDLE 0x0A
+#define HID_SET_PROTOCOL 0x0B
+
+/* USB Device Descriptor */
+static const uint8_t usb_device_descriptor_data[] = {
+ USB_DESC_DEVICE(0x0200, // bcdUSB (1.1)
+ 0, // bDeviceClass (defined in later in interface)
+ 0, // bDeviceSubClass
+ 0, // bDeviceProtocol
+ 64, // bMaxPacketSize (64 bytes) (the driver didn't work with 32)
+ VENDOR_ID, // idVendor
+ PRODUCT_ID, // idProduct
+ DEVICE_VER, // bcdDevice
+ 1, // iManufacturer
+ 2, // iProduct
+ 3, // iSerialNumber
+ 1) // bNumConfigurations
+};
+
+/* Device Descriptor wrapper */
+static const USBDescriptor usb_device_descriptor = {
+ sizeof usb_device_descriptor_data,
+ usb_device_descriptor_data
+};
+
+/*
+ * HID Report Descriptor
+ *
+ * See "Device Class Definition for Human Interface Devices (HID)"
+ * (http://www.usb.org/developers/hidpage/HID1_11.pdf) for the
+ * detailed descrition of all the fields
+ */
+
+/* Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60 */
+static const uint8_t keyboard_hid_report_desc_data[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x08, // Report Size (8),
+ 0x81, 0x03, // Input (Constant), ;Reserved byte
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute), ;LED report
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant), ;LED report padding
+ 0x95, KBD_REPORT_KEYS, // Report Count (),
+ 0x75, 0x08, // Report Size (8),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0xFF, // Logical Maximum(255),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, 0xFF, // Usage Maximum (255),
+ 0x81, 0x00, // Input (Data, Array),
+ 0xc0 // End Collection
+};
+/* wrapper */
+static const USBDescriptor keyboard_hid_report_descriptor = {
+ sizeof keyboard_hid_report_desc_data,
+ keyboard_hid_report_desc_data
+};
+
+#ifdef NKRO_ENABLE
+static const uint8_t nkro_hid_report_desc_data[] = {
+ 0x05, 0x01, // Usage Page (Generic Desktop),
+ 0x09, 0x06, // Usage (Keyboard),
+ 0xA1, 0x01, // Collection (Application),
+ // bitmap of modifiers
+ 0x75, 0x01, // Report Size (1),
+ 0x95, 0x08, // Report Count (8),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0xE0, // Usage Minimum (224),
+ 0x29, 0xE7, // Usage Maximum (231),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum (1),
+ 0x81, 0x02, // Input (Data, Variable, Absolute), ;Modifier byte
+ // LED output report
+ 0x95, 0x05, // Report Count (5),
+ 0x75, 0x01, // Report Size (1),
+ 0x05, 0x08, // Usage Page (LEDs),
+ 0x19, 0x01, // Usage Minimum (1),
+ 0x29, 0x05, // Usage Maximum (5),
+ 0x91, 0x02, // Output (Data, Variable, Absolute),
+ 0x95, 0x01, // Report Count (1),
+ 0x75, 0x03, // Report Size (3),
+ 0x91, 0x03, // Output (Constant),
+ // bitmap of keys
+ 0x95, NKRO_REPORT_KEYS * 8, // Report Count (),
+ 0x75, 0x01, // Report Size (1),
+ 0x15, 0x00, // Logical Minimum (0),
+ 0x25, 0x01, // Logical Maximum(1),
+ 0x05, 0x07, // Usage Page (Key Codes),
+ 0x19, 0x00, // Usage Minimum (0),
+ 0x29, NKRO_REPORT_KEYS * 8 - 1, // Usage Maximum (),
+ 0x81, 0x02, // Input (Data, Variable, Absolute),
+ 0xc0 // End Collection
+};
+/* wrapper */
+static const USBDescriptor nkro_hid_report_descriptor = {
+ sizeof nkro_hid_report_desc_data,
+ nkro_hid_report_desc_data
+};
+#endif /* NKRO_ENABLE */
+
+#ifdef MOUSE_ENABLE
+/* Mouse Protocol 1, HID 1.11 spec, Appendix B, page 59-60, with wheel extension
+ * http://www.microchip.com/forums/tm.aspx?high=&m=391435&mpage=1#391521
+ * http://www.keil.com/forum/15671/
+ * http://www.microsoft.com/whdc/device/input/wheel.mspx */
+static const uint8_t mouse_hid_report_desc_data[] = {
+ /* mouse */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x02, // USAGE (Mouse)
+ 0xa1, 0x01, // COLLECTION (Application)
+ //0x85, REPORT_ID_MOUSE, // REPORT_ID (1)
+ 0x09, 0x01, // USAGE (Pointer)
+ 0xa1, 0x00, // COLLECTION (Physical)
+ // ---------------------------- Buttons
+ 0x05, 0x09, // USAGE_PAGE (Button)
+ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
+ 0x29, 0x05, // USAGE_MAXIMUM (Button 5)
+ 0x15, 0x00, // LOGICAL_MINIMUM (0)
+ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
+ 0x75, 0x01, // REPORT_SIZE (1)
+ 0x95, 0x05, // REPORT_COUNT (5)
+ 0x81, 0x02, // INPUT (Data,Var,Abs)
+ 0x75, 0x03, // REPORT_SIZE (3)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
+ // ---------------------------- X,Y position
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x30, // USAGE (X)
+ 0x09, 0x31, // USAGE (Y)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x02, // REPORT_COUNT (2)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Vertical wheel
+ 0x09, 0x38, // USAGE (Wheel)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x35, 0x00, // PHYSICAL_MINIMUM (0) - reset physical
+ 0x45, 0x00, // PHYSICAL_MAXIMUM (0)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ // ---------------------------- Horizontal wheel
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x0a, 0x38, 0x02, // USAGE (AC Pan)
+ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
+ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
+ 0x75, 0x08, // REPORT_SIZE (8)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x06, // INPUT (Data,Var,Rel)
+ 0xc0, // END_COLLECTION
+ 0xc0, // END_COLLECTION
+};
+/* wrapper */
+static const USBDescriptor mouse_hid_report_descriptor = {
+ sizeof mouse_hid_report_desc_data,
+ mouse_hid_report_desc_data
+};
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+static const uint8_t console_hid_report_desc_data[] = {
+ 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined)
+ 0x09, 0x74, // Usage 0x74
+ 0xA1, 0x53, // Collection 0x53
+ 0x75, 0x08, // report size = 8 bits
+ 0x15, 0x00, // logical minimum = 0
+ 0x26, 0xFF, 0x00, // logical maximum = 255
+ 0x95, CONSOLE_EPSIZE, // report count
+ 0x09, 0x75, // usage
+ 0x81, 0x02, // Input (array)
+ 0xC0 // end collection
+};
+/* wrapper */
+static const USBDescriptor console_hid_report_descriptor = {
+ sizeof console_hid_report_desc_data,
+ console_hid_report_desc_data
+};
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+/* audio controls & system controls
+ * http://www.microsoft.com/whdc/archive/w2kbd.mspx */
+static const uint8_t extra_hid_report_desc_data[] = {
+ /* system control */
+ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
+ 0x09, 0x80, // USAGE (System Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_SYSTEM, // REPORT_ID (2)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x25, 0xb7, // LOGICAL_MAXIMUM (0xb7)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x29, 0xb7, // USAGE_MAXIMUM (0xb7)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+ /* consumer */
+ 0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
+ 0x09, 0x01, // USAGE (Consumer Control)
+ 0xa1, 0x01, // COLLECTION (Application)
+ 0x85, REPORT_ID_CONSUMER, // REPORT_ID (3)
+ 0x15, 0x01, // LOGICAL_MINIMUM (0x1)
+ 0x26, 0x9c, 0x02, // LOGICAL_MAXIMUM (0x29c)
+ 0x19, 0x01, // USAGE_MINIMUM (0x1)
+ 0x2a, 0x9c, 0x02, // USAGE_MAXIMUM (0x29c)
+ 0x75, 0x10, // REPORT_SIZE (16)
+ 0x95, 0x01, // REPORT_COUNT (1)
+ 0x81, 0x00, // INPUT (Data,Array,Abs)
+ 0xc0, // END_COLLECTION
+};
+/* wrapper */
+static const USBDescriptor extra_hid_report_descriptor = {
+ sizeof extra_hid_report_desc_data,
+ extra_hid_report_desc_data
+};
+#endif /* EXTRAKEY_ENABLE */
+
+
+/*
+ * Configuration Descriptor tree for a HID device
+ *
+ * The HID Specifications version 1.11 require the following order:
+ * - Configuration Descriptor
+ * - Interface Descriptor
+ * - HID Descriptor
+ * - Endpoints Descriptors
+ */
+#define KBD_HID_DESC_NUM 0
+#define KBD_HID_DESC_OFFSET (9 + (9 + 9 + 7) * KBD_HID_DESC_NUM + 9)
+
+#ifdef MOUSE_ENABLE
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 1)
+# define MOUSE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * MOUSE_HID_DESC_NUM + 9)
+#else /* MOUSE_ENABLE */
+# define MOUSE_HID_DESC_NUM (KBD_HID_DESC_NUM + 0)
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+#define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 1)
+#define CONSOLE_HID_DESC_OFFSET (9 + (9 + 9 + 7) * CONSOLE_HID_DESC_NUM + 9)
+#else /* CONSOLE_ENABLE */
+# define CONSOLE_HID_DESC_NUM (MOUSE_HID_DESC_NUM + 0)
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 1)
+# define EXTRA_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
+#else /* EXTRAKEY_ENABLE */
+# define EXTRA_HID_DESC_NUM (CONSOLE_HID_DESC_NUM + 0)
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef NKRO_ENABLE
+# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 1)
+# define NKRO_HID_DESC_OFFSET (9 + (9 + 9 + 7) * EXTRA_HID_DESC_NUM + 9)
+#else /* NKRO_ENABLE */
+# define NKRO_HID_DESC_NUM (EXTRA_HID_DESC_NUM + 0)
+#endif /* NKRO_ENABLE */
+
+#define NUM_INTERFACES (NKRO_HID_DESC_NUM + 1)
+#define CONFIG1_DESC_SIZE (9 + (9 + 9 + 7) * NUM_INTERFACES)
+
+static const uint8_t hid_configuration_descriptor_data[] = {
+ /* Configuration Descriptor (9 bytes) USB spec 9.6.3, page 264-266, Table 9-10 */
+ USB_DESC_CONFIGURATION(CONFIG1_DESC_SIZE, // wTotalLength
+ NUM_INTERFACES, // bNumInterfaces
+ 1, // bConfigurationValue
+ 0, // iConfiguration
+ 0xA0, // bmAttributes (RESERVED|REMOTEWAKEUP)
+ 50), // bMaxPower (50mA)
+
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(KBD_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x01, // bInterfaceSubClass: Boot
+ 0x01, // bInterfaceProtocol: Keyboard
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(keyboard_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(KBD_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ KBD_EPSIZE,// wMaxPacketSize
+ 10), // bInterval
+
+ #ifdef MOUSE_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(MOUSE_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass (0x03 = HID)
+ // ThinkPad T23 BIOS doesn't work with boot mouse.
+ 0x00, // bInterfaceSubClass (0x01 = Boot)
+ 0x00, // bInterfaceProtocol (0x02 = Mouse)
+ /*
+ 0x01, // bInterfaceSubClass (0x01 = Boot)
+ 0x02, // bInterfaceProtocol (0x02 = Mouse)
+ */
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(mouse_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(MOUSE_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ MOUSE_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* MOUSE_ENABLE */
+
+ #ifdef CONSOLE_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(CONSOLE_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(console_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(CONSOLE_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ CONSOLE_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* CONSOLE_ENABLE */
+
+ #ifdef EXTRAKEY_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(EXTRA_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(extra_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(EXTRA_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ EXTRA_EPSIZE, // wMaxPacketSize
+ 10), // bInterval
+ #endif /* EXTRAKEY_ENABLE */
+
+ #ifdef NKRO_ENABLE
+ /* Interface Descriptor (9 bytes) USB spec 9.6.5, page 267-269, Table 9-12 */
+ USB_DESC_INTERFACE(NKRO_INTERFACE, // bInterfaceNumber
+ 0, // bAlternateSetting
+ 1, // bNumEndpoints
+ 0x03, // bInterfaceClass: HID
+ 0x00, // bInterfaceSubClass: None
+ 0x00, // bInterfaceProtocol: None
+ 0), // iInterface
+
+ /* HID descriptor (9 bytes) HID 1.11 spec, section 6.2.1 */
+ USB_DESC_BYTE(9), // bLength
+ USB_DESC_BYTE(0x21), // bDescriptorType (HID class)
+ USB_DESC_BCD(0x0111), // bcdHID: HID version 1.11
+ USB_DESC_BYTE(0), // bCountryCode
+ USB_DESC_BYTE(1), // bNumDescriptors
+ USB_DESC_BYTE(0x22), // bDescriptorType (report desc)
+ USB_DESC_WORD(sizeof(nkro_hid_report_desc_data)), // wDescriptorLength
+
+ /* Endpoint Descriptor (7 bytes) USB spec 9.6.6, page 269-271, Table 9-13 */
+ USB_DESC_ENDPOINT(NKRO_ENDPOINT | 0x80, // bEndpointAddress
+ 0x03, // bmAttributes (Interrupt)
+ NKRO_EPSIZE, // wMaxPacketSize
+ 1), // bInterval
+ #endif /* NKRO_ENABLE */
+};
+
+/* Configuration Descriptor wrapper */
+static const USBDescriptor hid_configuration_descriptor = {
+ sizeof hid_configuration_descriptor_data,
+ hid_configuration_descriptor_data
+};
+
+/* wrappers */
+#define HID_DESCRIPTOR_SIZE 9
+static const USBDescriptor keyboard_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[KBD_HID_DESC_OFFSET]
+};
+#ifdef MOUSE_ENABLE
+static const USBDescriptor mouse_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[MOUSE_HID_DESC_OFFSET]
+};
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+static const USBDescriptor console_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[CONSOLE_HID_DESC_OFFSET]
+};
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+static const USBDescriptor extra_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[EXTRA_HID_DESC_OFFSET]
+};
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+static const USBDescriptor nkro_hid_descriptor = {
+ HID_DESCRIPTOR_SIZE,
+ &hid_configuration_descriptor_data[NKRO_HID_DESC_OFFSET]
+};
+#endif /* NKRO_ENABLE */
+
+
+/* U.S. English language identifier */
+static const uint8_t usb_string_langid[] = {
+ USB_DESC_BYTE(4), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USB_DESC_WORD(0x0409) // wLANGID (U.S. English)
+};
+
+/* ugly ugly hack */
+#define PP_NARG(...) \
+ PP_NARG_(__VA_ARGS__,PP_RSEQ_N())
+#define PP_NARG_(...) \
+ PP_ARG_N(__VA_ARGS__)
+#define PP_ARG_N( \
+ _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
+ _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
+ _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
+ _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
+ _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
+ _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
+ _61,_62,_63,N,...) N
+#define PP_RSEQ_N() \
+ 63,62,61,60, \
+ 59,58,57,56,55,54,53,52,51,50, \
+ 49,48,47,46,45,44,43,42,41,40, \
+ 39,38,37,36,35,34,33,32,31,30, \
+ 29,28,27,26,25,24,23,22,21,20, \
+ 19,18,17,16,15,14,13,12,11,10, \
+ 9,8,7,6,5,4,3,2,1,0
+
+/* Vendor string = manufacturer */
+static const uint8_t usb_string_vendor[] = {
+ USB_DESC_BYTE(PP_NARG(USBSTR_MANUFACTURER)+2), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USBSTR_MANUFACTURER
+};
+
+/* Device Description string = product */
+static const uint8_t usb_string_description[] = {
+ USB_DESC_BYTE(PP_NARG(USBSTR_PRODUCT)+2), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ USBSTR_PRODUCT
+};
+
+/* Serial Number string (will be filled by the function init_usb_serial_string) */
+static uint8_t usb_string_serial[] = {
+ USB_DESC_BYTE(22), // bLength
+ USB_DESC_BYTE(USB_DESCRIPTOR_STRING), // bDescriptorType
+ '0', 0, 'x', 0, 'D', 0, 'E', 0, 'A', 0, 'D', 0, 'B', 0, 'E', 0, 'E', 0, 'F', 0
+};
+
+/* Strings wrappers array */
+static const USBDescriptor usb_strings[] = {
+ { sizeof usb_string_langid, usb_string_langid }
+ ,
+ { sizeof usb_string_vendor, usb_string_vendor }
+ ,
+ { sizeof usb_string_description, usb_string_description }
+ ,
+ { sizeof usb_string_serial, usb_string_serial }
+};
+
+/*
+ * Handles the GET_DESCRIPTOR callback
+ *
+ * Returns the proper descriptor
+ */
+static const USBDescriptor *usb_get_descriptor_cb(USBDriver *usbp, uint8_t dtype, uint8_t dindex, uint16_t lang) {
+ (void)usbp;
+ (void)lang;
+ switch(dtype) {
+ /* Generic descriptors */
+ case USB_DESCRIPTOR_DEVICE: /* Device Descriptor */
+ return &usb_device_descriptor;
+
+ case USB_DESCRIPTOR_CONFIGURATION: /* Configuration Descriptor */
+ return &hid_configuration_descriptor;
+
+ case USB_DESCRIPTOR_STRING: /* Strings */
+ if(dindex < 4)
+ return &usb_strings[dindex];
+ break;
+
+ /* HID specific descriptors */
+ case USB_DESCRIPTOR_HID: /* HID Descriptors */
+ switch(lang) { /* yea, poor label, it's actually wIndex from the setup packet */
+ case KBD_INTERFACE:
+ return &keyboard_hid_descriptor;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ return &mouse_hid_descriptor;
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ return &console_hid_descriptor;
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ return &extra_hid_descriptor;
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ return &nkro_hid_descriptor;
+#endif /* NKRO_ENABLE */
+ }
+
+ case USB_DESCRIPTOR_HID_REPORT: /* HID Report Descriptor */
+ switch(lang) {
+ case KBD_INTERFACE:
+ return &keyboard_hid_report_descriptor;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ return &mouse_hid_report_descriptor;
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ return &console_hid_report_descriptor;
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ return &extra_hid_report_descriptor;
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+ return &nkro_hid_report_descriptor;
+#endif /* NKRO_ENABLE */
+ }
+ }
+ return NULL;
+}
+
+/* keyboard endpoint state structure */
+static USBInEndpointState kbd_ep_state;
+/* keyboard endpoint initialization structure (IN) */
+static const USBEndpointConfig kbd_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ kbd_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ KBD_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &kbd_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+
+#ifdef MOUSE_ENABLE
+/* mouse endpoint state structure */
+static USBInEndpointState mouse_ep_state;
+
+/* mouse endpoint initialization structure (IN) */
+static const USBEndpointConfig mouse_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ mouse_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ MOUSE_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &mouse_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+/* console endpoint state structure */
+static USBInEndpointState console_ep_state;
+
+/* console endpoint initialization structure (IN) */
+static const USBEndpointConfig console_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ console_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ CONSOLE_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &console_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+/* extrakey endpoint state structure */
+static USBInEndpointState extra_ep_state;
+
+/* extrakey endpoint initialization structure (IN) */
+static const USBEndpointConfig extra_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ extra_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ EXTRA_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &extra_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* EXTRAKEY_ENABLE */
+
+#ifdef NKRO_ENABLE
+/* nkro endpoint state structure */
+static USBInEndpointState nkro_ep_state;
+
+/* nkro endpoint initialization structure (IN) */
+static const USBEndpointConfig nkro_ep_config = {
+ USB_EP_MODE_TYPE_INTR, /* Interrupt EP */
+ NULL, /* SETUP packet notification callback */
+ nkro_in_cb, /* IN notification callback */
+ NULL, /* OUT notification callback */
+ NKRO_EPSIZE, /* IN maximum packet size */
+ 0, /* OUT maximum packet size */
+ &nkro_ep_state, /* IN Endpoint state */
+ NULL, /* OUT endpoint state */
+ 2, /* IN multiplier */
+ NULL /* SETUP buffer (not a SETUP endpoint) */
+};
+#endif /* NKRO_ENABLE */
+
+/* ---------------------------------------------------------
+ * USB driver functions
+ * ---------------------------------------------------------
+ */
+
+/* Handles the USB driver global events
+ * TODO: maybe disable some things when connection is lost? */
+static void usb_event_cb(USBDriver *usbp, usbevent_t event) {
+ switch(event) {
+ case USB_EVENT_RESET:
+ //TODO: from ISR! print("[R]");
+ return;
+
+ case USB_EVENT_ADDRESS:
+ return;
+
+ case USB_EVENT_CONFIGURED:
+ osalSysLockFromISR();
+ /* Enable the endpoints specified into the configuration. */
+ usbInitEndpointI(usbp, KBD_ENDPOINT, &kbd_ep_config);
+#ifdef MOUSE_ENABLE
+ usbInitEndpointI(usbp, MOUSE_ENDPOINT, &mouse_ep_config);
+#endif /* MOUSE_ENABLE */
+#ifdef CONSOLE_ENABLE
+ usbInitEndpointI(usbp, CONSOLE_ENDPOINT, &console_ep_config);
+ /* don't need to start the flush timer, it starts from console_in_cb automatically */
+#endif /* CONSOLE_ENABLE */
+#ifdef EXTRAKEY_ENABLE
+ usbInitEndpointI(usbp, EXTRA_ENDPOINT, &extra_ep_config);
+#endif /* EXTRAKEY_ENABLE */
+#ifdef NKRO_ENABLE
+ usbInitEndpointI(usbp, NKRO_ENDPOINT, &nkro_ep_config);
+#endif /* NKRO_ENABLE */
+ osalSysUnlockFromISR();
+ return;
+
+ case USB_EVENT_SUSPEND:
+ //TODO: from ISR! print("[S]");
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_enable();
+#endif /* SLEEP_LED_ENABLE */
+ return;
+
+ case USB_EVENT_WAKEUP:
+ //TODO: from ISR! print("[W]");
+ suspend_wakeup_init();
+#ifdef SLEEP_LED_ENABLE
+ sleep_led_disable();
+ // NOTE: converters may not accept this
+ led_set(host_keyboard_leds());
+#endif /* SLEEP_LED_ENABLE */
+ return;
+
+ case USB_EVENT_STALLED:
+ return;
+ }
+}
+
+/* Function used locally in os/hal/src/usb.c for getting descriptors
+ * need it here for HID descriptor */
+static uint16_t get_hword(uint8_t *p) {
+ uint16_t hw;
+
+ hw = (uint16_t)*p++;
+ hw |= (uint16_t)*p << 8U;
+ return hw;
+}
+
+/*
+ * Appendix G: HID Request Support Requirements
+ *
+ * The following table enumerates the requests that need to be supported by various types of HID class devices.
+ * Device type GetReport SetReport GetIdle SetIdle GetProtocol SetProtocol
+ * ------------------------------------------------------------------------------------------
+ * Boot Mouse Required Optional Optional Optional Required Required
+ * Non-Boot Mouse Required Optional Optional Optional Optional Optional
+ * Boot Keyboard Required Optional Required Required Required Required
+ * Non-Boot Keybrd Required Optional Required Required Optional Optional
+ * Other Device Required Optional Optional Optional Optional Optional
+ */
+
+/* Callback for SETUP request on the endpoint 0 (control) */
+static bool usb_request_hook_cb(USBDriver *usbp) {
+ const USBDescriptor *dp;
+
+ /* usbp->setup fields:
+ * 0: bmRequestType (bitmask)
+ * 1: bRequest
+ * 2,3: (LSB,MSB) wValue
+ * 4,5: (LSB,MSB) wIndex
+ * 6,7: (LSB,MSB) wLength (number of bytes to transfer if there is a data phase) */
+
+ /* Handle HID class specific requests */
+ if(((usbp->setup[0] & USB_RTYPE_TYPE_MASK) == USB_RTYPE_TYPE_CLASS) &&
+ ((usbp->setup[0] & USB_RTYPE_RECIPIENT_MASK) == USB_RTYPE_RECIPIENT_INTERFACE)) {
+ switch(usbp->setup[0] & USB_RTYPE_DIR_MASK) {
+ case USB_RTYPE_DIR_DEV2HOST:
+ switch(usbp->setup[1]) { /* bRequest */
+ case HID_GET_REPORT:
+ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0?) */
+ case KBD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif /* NKRO_ENABLE */
+ usbSetupTransfer(usbp, (uint8_t *)&keyboard_report_sent, sizeof(keyboard_report_sent), NULL);
+ return TRUE;
+ break;
+
+#ifdef MOUSE_ENABLE
+ case MOUSE_INTERFACE:
+ usbSetupTransfer(usbp, (uint8_t *)&mouse_report_blank, sizeof(mouse_report_blank), NULL);
+ return TRUE;
+ break;
+#endif /* MOUSE_ENABLE */
+
+#ifdef CONSOLE_ENABLE
+ case CONSOLE_INTERFACE:
+ usbSetupTransfer(usbp, console_queue_buffer, CONSOLE_EPSIZE, NULL);
+ return TRUE;
+ break;
+#endif /* CONSOLE_ENABLE */
+
+#ifdef EXTRAKEY_ENABLE
+ case EXTRA_INTERFACE:
+ if(usbp->setup[3] == 1) { /* MSB(wValue) [Report Type] == 1 [Input Report] */
+ switch(usbp->setup[2]) { /* LSB(wValue) [Report ID] */
+ case REPORT_ID_SYSTEM:
+ extra_report_blank[0] = REPORT_ID_SYSTEM;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ case REPORT_ID_CONSUMER:
+ extra_report_blank[0] = REPORT_ID_CONSUMER;
+ usbSetupTransfer(usbp, (uint8_t *)extra_report_blank, sizeof(extra_report_blank), NULL);
+ return TRUE;
+ break;
+ default:
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+ break;
+#endif /* EXTRAKEY_ENABLE */
+
+ default:
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case HID_GET_PROTOCOL:
+ if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
+ usbSetupTransfer(usbp, &keyboard_protocol, 1, NULL);
+ return TRUE;
+ }
+ break;
+
+ case HID_GET_IDLE:
+ usbSetupTransfer(usbp, &keyboard_idle, 1, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case USB_RTYPE_DIR_HOST2DEV:
+ switch(usbp->setup[1]) { /* bRequest */
+ case HID_SET_REPORT:
+ switch(usbp->setup[4]) { /* LSB(wIndex) (check MSB==0 and wLength==1?) */
+ case KBD_INTERFACE:
+#ifdef NKRO_ENABLE
+ case NKRO_INTERFACE:
+#endif /* NKRO_ENABLE */
+ /* keyboard_led_stats = <read byte from next OUT report>
+ * keyboard_led_stats needs be word (or dword), otherwise we get an exception on F0 */
+ usbSetupTransfer(usbp, (uint8_t *)&keyboard_led_stats, 1, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+
+ case HID_SET_PROTOCOL:
+ if((usbp->setup[4] == KBD_INTERFACE) && (usbp->setup[5] == 0)) { /* wIndex */
+ keyboard_protocol = ((usbp->setup[2]) != 0x00); /* LSB(wValue) */
+#ifdef NKRO_ENABLE
+ keyboard_nkro = !!keyboard_protocol;
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ /* arm the idle timer if boot protocol & idle */
+ osalSysLockFromISR();
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ }
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+
+ case HID_SET_IDLE:
+ keyboard_idle = usbp->setup[3]; /* MSB(wValue) */
+ /* arm the timer */
+#ifdef NKRO_ENABLE
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ osalSysLockFromISR();
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ }
+ usbSetupTransfer(usbp, NULL, 0, NULL);
+ return TRUE;
+ break;
+ }
+ break;
+ }
+ }
+
+ /* Handle the Get_Descriptor Request for HID class (not handled by the default hook) */
+ if((usbp->setup[0] == 0x81) && (usbp->setup[1] == USB_REQ_GET_DESCRIPTOR)) {
+ dp = usbp->config->get_descriptor_cb(usbp, usbp->setup[3], usbp->setup[2], get_hword(&usbp->setup[4]));
+ if(dp == NULL)
+ return FALSE;
+ usbSetupTransfer(usbp, (uint8_t *)dp->ud_string, dp->ud_size, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Start-of-frame callback */
+static void usb_sof_cb(USBDriver *usbp) {
+ kbd_sof_cb(usbp);
+}
+
+
+/* USB driver configuration */
+static const USBConfig usbcfg = {
+ usb_event_cb, /* USB events callback */
+ usb_get_descriptor_cb, /* Device GET_DESCRIPTOR request callback */
+ usb_request_hook_cb, /* Requests hook callback */
+ usb_sof_cb /* Start Of Frame callback */
+};
+
+/*
+ * Initialize the USB driver
+ */
+void init_usb_driver(USBDriver *usbp) {
+ /*
+ * Activates the USB driver and then the USB bus pull-up on D+.
+ * Note, a delay is inserted in order to not have to disconnect the cable
+ * after a reset.
+ */
+ usbDisconnectBus(usbp);
+ chThdSleepMilliseconds(1500);
+ usbStart(usbp, &usbcfg);
+ usbConnectBus(usbp);
+
+ chVTObjectInit(&keyboard_idle_timer);
+#ifdef CONSOLE_ENABLE
+ obqObjectInit(&console_buf_queue, console_queue_buffer, CONSOLE_EPSIZE, CONSOLE_QUEUE_CAPACITY, console_queue_onotify, (void*)usbp);
+ chVTObjectInit(&console_flush_timer);
+#endif
+}
+
+/*
+ * Send remote wakeup packet
+ * Note: should not be called from ISR
+ */
+void send_remote_wakeup(USBDriver *usbp) {
+ (void)usbp;
+#if defined(K20x) || defined(KL2x)
+#if KINETIS_USB_USE_USB0
+ USB0->CTL |= USBx_CTL_RESUME;
+ chThdSleepMilliseconds(15);
+ USB0->CTL &= ~USBx_CTL_RESUME;
+#endif /* KINETIS_USB_USE_USB0 */
+#elif defined(STM32F0XX) || defined(STM32F1XX) /* K20x || KL2x */
+ STM32_USB->CNTR |= CNTR_RESUME;
+ chThdSleepMilliseconds(15);
+ STM32_USB->CNTR &= ~CNTR_RESUME;
+#else /* STM32F0XX || STM32F1XX */
+#warning Sending remote wakeup packet not implemented for your platform.
+#endif /* K20x || KL2x */
+}
+
+/* ---------------------------------------------------------
+ * Keyboard functions
+ * ---------------------------------------------------------
+ */
+
+/* keyboard IN callback hander (a kbd report has made it IN) */
+void kbd_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+
+#ifdef NKRO_ENABLE
+/* nkro IN callback hander (a nkro report has made it IN) */
+void nkro_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+#endif /* NKRO_ENABLE */
+
+/* start-of-frame handler
+ * TODO: i guess it would be better to re-implement using timers,
+ * so that this is not going to have to be checked every 1ms */
+void kbd_sof_cb(USBDriver *usbp) {
+ (void)usbp;
+}
+
+/* Idle requests timer code
+ * callback (called from ISR, unlocked state) */
+static void keyboard_idle_timer_cb(void *arg) {
+ USBDriver *usbp = (USBDriver *)arg;
+
+ osalSysLockFromISR();
+
+ /* check that the states of things are as they're supposed to */
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ /* do not rearm the timer, should be enabled on IDLE request */
+ osalSysUnlockFromISR();
+ return;
+ }
+
+#ifdef NKRO_ENABLE
+ if(!keyboard_nkro && keyboard_idle) {
+#else /* NKRO_ENABLE */
+ if(keyboard_idle) {
+#endif /* NKRO_ENABLE */
+ /* TODO: are we sure we want the KBD_ENDPOINT? */
+ if(!usbGetTransmitStatusI(usbp, KBD_ENDPOINT)) {
+ usbStartTransmitI(usbp, KBD_ENDPOINT, (uint8_t *)&keyboard_report_sent, KBD_EPSIZE);
+ }
+ /* rearm the timer */
+ chVTSetI(&keyboard_idle_timer, 4*MS2ST(keyboard_idle), keyboard_idle_timer_cb, (void *)usbp);
+ }
+
+ /* do not rearm the timer if the condition above fails
+ * it should be enabled again on either IDLE or SET_PROTOCOL requests */
+ osalSysUnlockFromISR();
+}
+
+/* LED status */
+uint8_t keyboard_leds(void) {
+ return (uint8_t)(keyboard_led_stats & 0xFF);
+}
+
+/* prepare and start sending a report IN
+ * not callable from ISR or locked state */
+void send_keyboard(report_keyboard_t *report) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+ osalSysUnlock();
+
+#ifdef NKRO_ENABLE
+ if(keyboard_nkro) { /* NKRO protocol */
+ /* need to wait until the previous packet has made it through */
+ /* can rewrite this using the synchronous API, then would wait
+ * until *after* the packet has been transmitted. I think
+ * this is more efficient */
+ /* busy wait, should be short and not very common */
+ osalSysLock();
+ if(usbGetTransmitStatusI(&USB_DRIVER, NKRO_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[NKRO_ENDPOINT]->in_state->thread);
+ }
+ usbStartTransmitI(&USB_DRIVER, NKRO_ENDPOINT, (uint8_t *)report, sizeof(report_keyboard_t));
+ osalSysUnlock();
+ } else
+#endif /* NKRO_ENABLE */
+ { /* boot protocol */
+ /* need to wait until the previous packet has made it through */
+ /* busy wait, should be short and not very common */
+ osalSysLock();
+ if(usbGetTransmitStatusI(&USB_DRIVER, KBD_ENDPOINT)) {
+ /* Need to either suspend, or loop and call unlock/lock during
+ * every iteration - otherwise the system will remain locked,
+ * no interrupts served, so USB not going through as well.
+ * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */
+ osalThreadSuspendS(&(&USB_DRIVER)->epc[KBD_ENDPOINT]->in_state->thread);
+ }
+ usbStartTransmitI(&USB_DRIVER, KBD_ENDPOINT, (uint8_t *)report, KBD_EPSIZE);
+ osalSysUnlock();
+ }
+ keyboard_report_sent = *report;
+}
+
+/* ---------------------------------------------------------
+ * Mouse functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef MOUSE_ENABLE
+
+/* mouse IN callback hander (a mouse report has made it IN) */
+void mouse_in_cb(USBDriver *usbp, usbep_t ep) {
+ (void)usbp;
+ (void)ep;
+}
+
+void send_mouse(report_mouse_t *report) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+ osalSysUnlock();
+
+ /* TODO: LUFA manually waits for the endpoint to become ready
+ * for about 10ms for mouse, kbd, system; 1ms for nkro
+ * is this really needed?
+ */
+
+ osalSysLock();
+ usbStartTransmitI(&USB_DRIVER, MOUSE_ENDPOINT, (uint8_t *)report, sizeof(report_mouse_t));
+ osalSysUnlock();
+}
+
+#else /* MOUSE_ENABLE */
+void send_mouse(report_mouse_t *report) {
+ (void)report;
+}
+#endif /* MOUSE_ENABLE */
+
+/* ---------------------------------------------------------
+ * Extrakey functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef EXTRAKEY_ENABLE
+
+/* extrakey IN callback hander */
+void extra_in_cb(USBDriver *usbp, usbep_t ep) {
+ /* STUB */
+ (void)usbp;
+ (void)ep;
+}
+
+static void send_extra_report(uint8_t report_id, uint16_t data) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return;
+ }
+
+ report_extra_t report = {
+ .report_id = report_id,
+ .usage = data
+ };
+
+ usbStartTransmitI(&USB_DRIVER, EXTRA_ENDPOINT, (uint8_t *)&report, sizeof(report_extra_t));
+ osalSysUnlock();
+}
+
+void send_system(uint16_t data) {
+ send_extra_report(REPORT_ID_SYSTEM, data);
+}
+
+void send_consumer(uint16_t data) {
+ send_extra_report(REPORT_ID_CONSUMER, data);
+}
+
+#else /* EXTRAKEY_ENABLE */
+void send_system(uint16_t data) {
+ (void)data;
+}
+void send_consumer(uint16_t data) {
+ (void)data;
+}
+#endif /* EXTRAKEY_ENABLE */
+
+/* ---------------------------------------------------------
+ * Console functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef CONSOLE_ENABLE
+
+/* console IN callback hander */
+void console_in_cb(USBDriver *usbp, usbep_t ep) {
+ (void)ep; /* should have ep == CONSOLE_ENDPOINT, so use that to save time/space */
+ uint8_t *buf;
+ size_t n;
+
+ osalSysLockFromISR();
+
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+
+ /* Freeing the buffer just transmitted, if it was not a zero size packet.*/
+ if (usbp->epc[CONSOLE_ENDPOINT]->in_state->txsize > 0U) {
+ obqReleaseEmptyBufferI(&console_buf_queue);
+ }
+
+ /* Checking if there is a buffer ready for transmission.*/
+ buf = obqGetFullBufferI(&console_buf_queue, &n);
+
+ if (buf != NULL) {
+ /* The endpoint cannot be busy, we are in the context of the callback,
+ so it is safe to transmit without a check.*/
+ /* Should have n == CONSOLE_EPSIZE; check it? */
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ } else {
+ /* Nothing to transmit.*/
+ }
+
+ osalSysUnlockFromISR();
+}
+
+/* Callback when data is inserted into the output queue
+ * Called from a locked state */
+void console_queue_onotify(io_buffers_queue_t *bqp) {
+ size_t n;
+ USBDriver *usbp = bqGetLinkX(bqp);
+
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE)
+ return;
+
+ /* Checking if there is already a transaction ongoing on the endpoint.*/
+ if (!usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
+ /* Trying to get a full buffer.*/
+ uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
+ if (buf != NULL) {
+ /* Buffer found, starting a new transaction.*/
+ /* Should have n == CONSOLE_EPSIZE; check this? */
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ }
+ }
+}
+
+/* Flush timer code
+ * callback (called from ISR, unlocked state) */
+static void console_flush_cb(void *arg) {
+ USBDriver *usbp = (USBDriver *)arg;
+ osalSysLockFromISR();
+
+ /* check that the states of things are as they're supposed to */
+ if(usbGetDriverStateI(usbp) != USB_ACTIVE) {
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ return;
+ }
+
+ /* If there is already a transaction ongoing then another one cannot be
+ started.*/
+ if (usbGetTransmitStatusI(usbp, CONSOLE_ENDPOINT)) {
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+ return;
+ }
+
+ /* Checking if there only a buffer partially filled, if so then it is
+ enforced in the queue and transmitted.*/
+ if(obqTryFlushI(&console_buf_queue)) {
+ size_t n,i;
+ uint8_t *buf = obqGetFullBufferI(&console_buf_queue, &n);
+
+ osalDbgAssert(buf != NULL, "queue is empty");
+
+ /* zero the rest of the buffer (buf should point to allocated space) */
+ for(i=n; i<CONSOLE_EPSIZE; i++)
+ buf[i]=0;
+ usbStartTransmitI(usbp, CONSOLE_ENDPOINT, buf, CONSOLE_EPSIZE);
+ }
+
+ /* rearm the timer */
+ chVTSetI(&console_flush_timer, MS2ST(CONSOLE_FLUSH_MS), console_flush_cb, (void *)usbp);
+ osalSysUnlockFromISR();
+}
+
+
+int8_t sendchar(uint8_t c) {
+ osalSysLock();
+ if(usbGetDriverStateI(&USB_DRIVER) != USB_ACTIVE) {
+ osalSysUnlock();
+ return 0;
+ }
+ osalSysUnlock();
+ /* Timeout after 100us if the queue is full.
+ * Increase this timeout if too much stuff is getting
+ * dropped (i.e. the buffer is getting full too fast
+ * for USB/HIDRAW to dequeue). Another possibility
+ * for fixing this kind of thing is to increase
+ * CONSOLE_QUEUE_CAPACITY. */
+ return(obqPutTimeout(&console_buf_queue, c, US2ST(100)));
+}
+
+#else /* CONSOLE_ENABLE */
+int8_t sendchar(uint8_t c) {
+ (void)c;
+ return 0;
+}
+#endif /* CONSOLE_ENABLE */
+
+void sendchar_pf(void *p, char c) {
+ (void)p;
+ sendchar((uint8_t)c);
+}
diff --git a/tmk_core/protocol/chibios/usb_main.h b/tmk_core/protocol/chibios/usb_main.h
new file mode 100644
index 0000000000..30d8fcaef7
--- /dev/null
+++ b/tmk_core/protocol/chibios/usb_main.h
@@ -0,0 +1,139 @@
+/*
+ * (c) 2015 flabberast <s3+flabbergast@sdfeu.org>
+ *
+ * Based on the following work:
+ * - Guillaume Duc's raw hid example (MIT License)
+ * https://github.com/guiduc/usb-hid-chibios-example
+ * - PJRC Teensy examples (MIT License)
+ * https://www.pjrc.com/teensy/usb_keyboard.html
+ * - hasu's TMK keyboard code (GPL v2 and some code Modified BSD)
+ * https://github.com/tmk/tmk_keyboard/
+ * - ChibiOS demo code (Apache 2.0 License)
+ * http://www.chibios.org
+ *
+ * Since some GPL'd code is used, this work is licensed under
+ * GPL v2 or later.
+ */
+
+
+#ifndef _USB_MAIN_H_
+#define _USB_MAIN_H_
+
+// TESTING
+// extern uint8_t blinkLed;
+
+#include "ch.h"
+#include "hal.h"
+
+/* -------------------------
+ * General USB driver header
+ * -------------------------
+ */
+
+/* The USB driver to use */
+#define USB_DRIVER USBD1
+
+/* Initialize the USB driver and bus */
+void init_usb_driver(USBDriver *usbp);
+
+/* Send remote wakeup packet */
+void send_remote_wakeup(USBDriver *usbp);
+
+/* ---------------
+ * Keyboard header
+ * ---------------
+ */
+
+/* main keyboard (6kro) */
+#define KBD_INTERFACE 0
+#define KBD_ENDPOINT 1
+#define KBD_EPSIZE 8
+#define KBD_REPORT_KEYS (KBD_EPSIZE - 2)
+
+/* secondary keyboard */
+#ifdef NKRO_ENABLE
+#define NKRO_INTERFACE 4
+#define NKRO_ENDPOINT 5
+#define NKRO_EPSIZE 16
+#define NKRO_REPORT_KEYS (NKRO_EPSIZE - 1)
+#endif
+
+/* extern report_keyboard_t keyboard_report_sent; */
+
+/* keyboard IN request callback handler */
+void kbd_in_cb(USBDriver *usbp, usbep_t ep);
+
+/* start-of-frame handler */
+void kbd_sof_cb(USBDriver *usbp);
+
+#ifdef NKRO_ENABLE
+/* nkro IN callback hander */
+void nkro_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* NKRO_ENABLE */
+
+/* ------------
+ * Mouse header
+ * ------------
+ */
+
+#ifdef MOUSE_ENABLE
+
+#define MOUSE_INTERFACE 1
+#define MOUSE_ENDPOINT 2
+#define MOUSE_EPSIZE 8
+
+/* mouse IN request callback handler */
+void mouse_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* MOUSE_ENABLE */
+
+/* ---------------
+ * Extrakey header
+ * ---------------
+ */
+
+#ifdef EXTRAKEY_ENABLE
+
+#define EXTRA_INTERFACE 3
+#define EXTRA_ENDPOINT 4
+#define EXTRA_EPSIZE 8
+
+/* extrakey IN request callback handler */
+void extra_in_cb(USBDriver *usbp, usbep_t ep);
+
+/* extra report structure */
+typedef struct {
+ uint8_t report_id;
+ uint16_t usage;
+} __attribute__ ((packed)) report_extra_t;
+#endif /* EXTRAKEY_ENABLE */
+
+/* --------------
+ * Console header
+ * --------------
+ */
+
+#ifdef CONSOLE_ENABLE
+
+#define CONSOLE_INTERFACE 2
+#define CONSOLE_ENDPOINT 3
+#define CONSOLE_EPSIZE 16
+
+/* Number of IN reports that can be stored inside the output queue */
+#define CONSOLE_QUEUE_CAPACITY 4
+
+/* Console flush time */
+#define CONSOLE_FLUSH_MS 50
+
+/* Putchar over the USB console */
+int8_t sendchar(uint8_t c);
+
+/* Flush output (send everything immediately) */
+void console_flush_output(void);
+
+/* console IN request callback handler */
+void console_in_cb(USBDriver *usbp, usbep_t ep);
+#endif /* CONSOLE_ENABLE */
+
+void sendchar_pf(void *p, char c);
+
+#endif /* _USB_MAIN_H_ */
diff --git a/tmk_core/readme.md b/tmk_core/readme.md
index 6b6714a6a2..f460d0ed44 100644
--- a/tmk_core/readme.md
+++ b/tmk_core/readme.md
@@ -5,6 +5,16 @@ This is a keyboard firmware library with some useful features for Atmel AVR and
Source code is available here: <https://github.com/tmk/tmk_keyboard/tree/core>
+Updates
+-------
+#### 2016/02/10
+flabbergast's Chibios protocol was merged from <https://github.com/flabbergast/tmk_keyboard/tree/chibios>. See [protocol/chibios/README.md](protocol/chibios/README.md). Chibios protocol supports Cortex-M such as STM32 and Kinetis.
+
+#### 2015/04/22
+separated with TMK Keyboard Firmware Collection
+
+
+
Features
--------
These features can be used in your keyboard.
@@ -27,12 +37,6 @@ These features can be used in your keyboard.
-Updates
--------
-2015/04/22 separated with TMK Keyboard Firmware Collection
-
-
-
TMK Keyboard Firmware Collection
--------------------------------
Complete firmwares for various keyboards and protocol converters.
diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk
index f8f77e892e..96eba24d67 100644
--- a/tmk_core/rules.mk
+++ b/tmk_core/rules.mk
@@ -20,26 +20,11 @@
# Output format. (can be srec, ihex, binary)
FORMAT = ihex
-BUILD_DIR = .build
-
-# Object files directory
-# To put object files in current directory, use a dot (.), do NOT make
-# this an empty or blank macro!
-OBJDIR = $(BUILD_DIR)/obj_$(TARGET)
-
-
# Optimization level, can be [0, 1, 2, 3, s].
# 0 = turn off optimization. s = optimize for size.
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
OPT = s
-
-# Debugging format.
-# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
-# AVR Studio 4.10 requires dwarf-2.
-# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
-DEBUG = dwarf-2
-
COLOR ?= true
ifeq ($(COLOR),true)
@@ -87,7 +72,7 @@ BUILD_CMD = LOG=$$($(CMD) 2>&1) ; if [ $$? -gt 0 ]; then $(PRINT_ERROR); elif [
# Each directory must be seperated by a space.
# Use forward slashes for directory separators.
# For a directory that has spaces, enclose it in quotes.
-EXTRAINCDIRS = $(subst :, ,$(VPATH))
+EXTRAINCDIRS += $(subst :, ,$(VPATH))
# Compiler flag to set the C Standard level.
@@ -99,17 +84,14 @@ CSTANDARD = -std=gnu99
# Place -D or -U options here for C sources
-CDEFS = -DF_CPU=$(F_CPU)UL
CDEFS += $(OPT_DEFS)
# Place -D or -U options here for ASM sources
-ADEFS = -DF_CPU=$(F_CPU)
ADEFS += $(OPT_DEFS)
# Place -D or -U options here for C++ sources
-CPPDEFS = -DF_CPU=$(F_CPU)UL
#CPPDEFS += -D__STDC_LIMIT_MACROS
#CPPDEFS += -D__STDC_CONSTANT_MACROS
CPPDEFS += $(OPT_DEFS)
@@ -123,17 +105,9 @@ CPPDEFS += $(OPT_DEFS)
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
-CFLAGS = -g$(DEBUG)
+CFLAGS += -g$(DEBUG)
CFLAGS += $(CDEFS)
CFLAGS += -O$(OPT)
-CFLAGS += -funsigned-char
-CFLAGS += -funsigned-bitfields
-CFLAGS += -ffunction-sections
-CFLAGS += -fdata-sections
-CFLAGS += -fno-inline-small-functions
-CFLAGS += -fpack-struct
-CFLAGS += -fshort-enums
-CFLAGS += -fno-strict-aliasing
# add color
ifeq ($(COLOR),true)
ifeq ("$(shell echo "int main(){}" | $(CC) -fdiagnostics-color -x c - -o /dev/null 2>&1)", "")
@@ -162,16 +136,9 @@ endif
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -adhlns...: create assembler listing
-CPPFLAGS = -g$(DEBUG)
+CPPFLAGS += -g$(DEBUG)
CPPFLAGS += $(CPPDEFS)
CPPFLAGS += -O$(OPT)
-CPPFLAGS += -funsigned-char
-CPPFLAGS += -funsigned-bitfields
-CPPFLAGS += -fpack-struct
-CPPFLAGS += -fshort-enums
-CPPFLAGS += -fno-exceptions
-CPPFLAGS += -ffunction-sections
-CPPFLAGS += -fdata-sections
# to supress "warning: only initialized variables can be placed into program memory area"
CPPFLAGS += -w
CPPFLAGS += -Wall
@@ -198,7 +165,7 @@ endif
# files -- see avr-libc docs [FIXME: not yet described there]
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
# dump that will be displayed for a given single line of source input.
-ASFLAGS = $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
+ASFLAGS += $(ADEFS) -Wa,-adhlns=$(@:%.o=%.lst),-gstabs,--listing-cont-lines=100
ASFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
ifdef CONFIG_H
ASFLAGS += -include $(CONFIG_H)
@@ -232,28 +199,6 @@ SCANF_LIB =
MATH_LIB = -lm
-# List any extra directories to look for libraries here.
-# Each directory must be seperated by a space.
-# Use forward slashes for directory separators.
-# For a directory that has spaces, enclose it in quotes.
-EXTRALIBDIRS =
-
-
-
-#---------------- External Memory Options ----------------
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# used for variables (.data/.bss) and heap (malloc()).
-#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
-
-# 64 KB of external RAM, starting after internal RAM (ATmega128!),
-# only used for heap (malloc()).
-#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
-
-EXTMEMOPTS =
-
-
-
#---------------- Linker Options ----------------
# -Wl,...: tell GCC to pass this to linker.
# -Map: create map file
@@ -262,9 +207,8 @@ EXTMEMOPTS =
# Comennt out "--relax" option to avoid a error such:
# (.vectors+0x30): relocation truncated to fit: R_AVR_13_PCREL against symbol `__vector_12'
#
-LDFLAGS = -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
+LDFLAGS += -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref
#LDFLAGS += -Wl,--relax
-LDFLAGS += -Wl,--gc-sections
LDFLAGS += $(EXTMEMOPTS)
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
@@ -272,59 +216,13 @@ LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
# You can give EXTRALDFLAGS at 'make' command line.
LDFLAGS += $(EXTRALDFLAGS)
-
-
-#---------------- Debugging Options ----------------
-
-# For simulavr only - target MCU frequency.
-DEBUG_MFREQ = $(F_CPU)
-
-# Set the DEBUG_UI to either gdb or insight.
-# DEBUG_UI = gdb
-DEBUG_UI = insight
-
-# Set the debugging back-end to either avarice, simulavr.
-DEBUG_BACKEND = avarice
-#DEBUG_BACKEND = simulavr
-
-# GDB Init Filename.
-GDBINIT_FILE = __avr_gdbinit
-
-# When using avarice settings for the JTAG
-JTAG_DEV = /dev/com1
-
-# Debugging port used to communicate between GDB / avarice / simulavr.
-DEBUG_PORT = 4242
-
-# Debugging host used to communicate between GDB / avarice / simulavr, normally
-# just set to localhost unless doing some sort of crazy debugging when
-# avarice is running on a different computer.
-DEBUG_HOST = localhost
-
-
-
-#============================================================================
-
-
# Define programs and commands.
SHELL = sh
-CC = avr-gcc
-OBJCOPY = avr-objcopy
-OBJDUMP = avr-objdump
-SIZE = avr-size
-AR = avr-ar rcs
-NM = avr-nm
REMOVE = rm -f
REMOVEDIR = rmdir
COPY = cp
WINSHELL = cmd
SECHO = $(SILENT) || echo
-# Autodecct teensy loader
-ifneq (, $(shell which teensy-loader-cli 2>/dev/null))
- TEENSY_LOADER_CLI = teensy-loader-cli
-else
- TEENSY_LOADER_CLI = teensy_loader_cli
-endif
# Define Messages
# English
@@ -347,8 +245,6 @@ MSG_CLEANING = Cleaning project:
MSG_CREATING_LIBRARY = Creating library:
-
-
# Define all object files.
OBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(patsubst %.cpp,$(OBJDIR)/%.o,$(patsubst %.S,$(OBJDIR)/%.o,$(SRC))))
@@ -364,9 +260,9 @@ GENDEPFLAGS = -MMD -MP -MF $(BUILD_DIR)/.dep/$(subst /,_,$@).d
# Combine all necessary flags and optional flags.
# Add target processor to flags.
# You can give extra flags at 'make' command line like: make EXTRAFLAGS=-DFOO=bar
-ALL_CFLAGS = -mmcu=$(MCU) $(CFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
-ALL_CPPFLAGS = -mmcu=$(MCU) -x c++ $(CPPFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
-ALL_ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
+ALL_CFLAGS = $(MCUFLAGS) $(CFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
+ALL_CPPFLAGS = $(MCUFLAGS) -x c++ $(CPPFLAGS) $(GENDEPFLAGS) $(EXTRAFLAGS)
+ALL_ASFLAGS = $(MCUFLAGS) -x assembler-with-cpp $(ASFLAGS) $(EXTRAFLAGS)
# Default target.
all:
@@ -432,104 +328,10 @@ sizeafter:
gccversion :
@$(SILENT) || $(CC) --version
-
-
-# Program the device.
-program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
- $(PROGRAM_CMD)
-
-teensy: $(BUILD_DIR)/$(TARGET).hex
- $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex
-
-flip: $(BUILD_DIR)/$(TARGET).hex
- batchisp -hardware usb -device $(MCU) -operation erase f
- batchisp -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program
- batchisp -hardware usb -device $(MCU) -operation start reset 0
-
-dfu: $(BUILD_DIR)/$(TARGET).hex sizeafter
-ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
- dfu-programmer $(MCU) erase --force
-else
- dfu-programmer $(MCU) erase
-endif
- dfu-programmer $(MCU) flash $(BUILD_DIR)/$(TARGET).hex
- dfu-programmer $(MCU) reset
-
-dfu-start:
- dfu-programmer $(MCU) reset
- dfu-programmer $(MCU) start
-
-flip-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
- $(COPY) $(BUILD_DIR)/$(TARGET).eep $(BUILD_DIR)/$(TARGET)eep.hex
- batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
- batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(BUILD_DIR)/$(TARGET)eep.hex program
- batchisp -hardware usb -device $(MCU) -operation start reset 0
- $(REMOVE) $(BUILD_DIR)/$(TARGET)eep.hex
-
-dfu-ee: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep
-ifneq (, $(findstring 0.7, $(shell dfu-programmer --version 2>&1)))
- dfu-programmer $(MCU) flash --eeprom $(BUILD_DIR)/$(TARGET).eep
-else
- dfu-programmer $(MCU) flash-eeprom $(BUILD_DIR)/$(TARGET).eep
-endif
- dfu-programmer $(MCU) reset
-
-
-# Generate avr-gdb config/init file which does the following:
-# define the reset signal, load the target file, connect to target, and set
-# a breakpoint at main().
-gdb-config:
- @$(REMOVE) $(GDBINIT_FILE)
- @echo define reset >> $(GDBINIT_FILE)
- @echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
- @echo end >> $(GDBINIT_FILE)
- @echo file $(BUILD_DIR)/$(TARGET).elf >> $(GDBINIT_FILE)
- @echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
-ifeq ($(DEBUG_BACKEND),simulavr)
- @echo load >> $(GDBINIT_FILE)
-endif
- @echo break main >> $(GDBINIT_FILE)
-
-debug: gdb-config $(BUILD_DIR)/$(TARGET).elf
-ifeq ($(DEBUG_BACKEND), avarice)
- @echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
- @$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
- $(BUILD_DIR)/$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
- @$(WINSHELL) /c pause
-
-else
- @$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
- $(DEBUG_MFREQ) --port $(DEBUG_PORT)
-endif
- @$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
-
-
-
-
-# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
-COFFCONVERT = $(OBJCOPY) --debugging
-COFFCONVERT += --change-section-address .data-0x800000
-COFFCONVERT += --change-section-address .bss-0x800000
-COFFCONVERT += --change-section-address .noinit-0x800000
-COFFCONVERT += --change-section-address .eeprom-0x810000
-
-
-
-coff: $(BUILD_DIR)/$(TARGET).elf
- @$(SECHO) $(MSG_COFF) $(BUILD_DIR)/$(TARGET).cof
- $(COFFCONVERT) -O coff-avr $< $(BUILD_DIR)/$(TARGET).cof
-
-
-extcoff: $(BUILD_DIR)/$(TARGET).elf
- @$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof
- $(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof
-
-
-
# Create final output files (.hex, .eep) from ELF output file.
%.hex: %.elf
@$(SILENT) || printf "$(MSG_FLASH) $@" | $(AWK_CMD)
- $(eval CMD=$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@)
+ $(eval CMD=$(HEX) $< $@)
@$(BUILD_CMD)
@if $(AUTOGEN); then \
$(SILENT) || printf "Copying $(TARGET).hex to keymaps/$(KEYMAP)/$(KEYBOARD)_$(KEYMAP).hex\n"; \
@@ -540,7 +342,7 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf
%.eep: %.elf
@$(SILENT) || printf "$(MSG_EEPROM) $@" | $(AWK_CMD)
- $(eval CMD=$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0)
+ $(eval CMD=$(EEP) $< $@ || exit 0)
@$(BUILD_CMD)
# Create extended listing file from ELF output file.
@@ -622,7 +424,7 @@ show_path:
@echo VPATH=$(VPATH)
@echo SRC=$(SRC)
-SUBDIRS := $(filter-out %/util/ %/doc/ %/keymaps/ %/old_keymap_files/,$(dir $(wildcard $(TOP_DIR)/keyboards/**/*/.)))
+SUBDIRS := $(filter-out %/util/ %/doc/ %/keymaps/ %/old_keymap_files/,$(dir $(wildcard $(TOP_DIR)/keyboards/**/*/Makefile)))
SUBDIRS := $(SUBDIRS) $(dir $(wildcard $(TOP_DIR)/keyboards/*/.))
SUBDIRS := $(sort $(SUBDIRS))
# $(error $(SUBDIRS))
diff --git a/tmk_core/tool/chibios/.gitignore b/tmk_core/tool/chibios/.gitignore
new file mode 100644
index 0000000000..88bbafe34f
--- /dev/null
+++ b/tmk_core/tool/chibios/.gitignore
@@ -0,0 +1,2 @@
+chibios
+chibios-contrib
diff --git a/tmk_core/tool/chibios/ch-bootloader-jump.patch b/tmk_core/tool/chibios/ch-bootloader-jump.patch
new file mode 100644
index 0000000000..d886576214
--- /dev/null
+++ b/tmk_core/tool/chibios/ch-bootloader-jump.patch
@@ -0,0 +1,116 @@
+diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
+index 51a79bb..42d07bd 100644
+--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
++++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v6m.s
+@@ -105,6 +105,13 @@
+ #define CRT0_CALL_DESTRUCTORS TRUE
+ #endif
+
++/**
++ * @brief Magic number for jumping to bootloader.
++ */
++#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
++#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
++#endif
++
+ /*===========================================================================*/
+ /* Code section. */
+ /*===========================================================================*/
+@@ -124,6 +131,17 @@
+ .thumb_func
+ .global Reset_Handler
+ Reset_Handler:
++
++#ifdef STM32_BOOTLOADER_ADDRESS
++ /* jump to bootloader code */
++ ldr r0, =__ram0_end__-4
++ ldr r1, =MAGIC_BOOTLOADER_NUMBER
++ ldr r2, [r0, #0]
++ str r0, [r0, #0] /* erase stored magic */
++ cmp r2, r1
++ beq Bootloader_Jump
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+@@ -242,6 +260,21 @@ endfiniloop:
+ ldr r1, =__default_exit
+ bx r1
+
++#ifdef STM32_BOOTLOADER_ADDRESS
++/*
++ * Jump-to-bootloader function.
++ */
++
++ .align 2
++ .thumb_func
++Bootloader_Jump:
++ ldr r0, =STM32_BOOTLOADER_ADDRESS
++ ldr r1, [r0, #0]
++ mov sp, r1
++ ldr r0, [r0, #4]
++ bx r0
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ #endif
+
+ /** @} */
+diff --git a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
+index 4812a29..dca9f88 100644
+--- a/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
++++ b/os/common/ports/ARMCMx/compilers/GCC/crt0_v7m.s
+@@ -140,6 +140,13 @@
+ #define CRT0_CPACR_INIT 0x00F00000
+ #endif
+
++/**
++ * @brief Magic number for jumping to bootloader.
++ */
++#if !defined(MAGIC_BOOTLOADER_NUMBER) || defined(__DOXYGEN__)
++#define MAGIC_BOOTLOADER_NUMBER 0xDEADBEEF
++#endif
++
+ /*===========================================================================*/
+ /* Code section. */
+ /*===========================================================================*/
+@@ -164,6 +171,17 @@
+ .thumb_func
+ .global Reset_Handler
+ Reset_Handler:
++
++#ifdef STM32_BOOTLOADER_ADDRESS
++ /* jump to bootloader code */
++ ldr r0, =__ram0_end__-4
++ ldr r1, =MAGIC_BOOTLOADER_NUMBER
++ ldr r2, [r0, #0]
++ str r0, [r0, #0] /* erase stored magic */
++ cmp r2, r1
++ beq Bootloader_Jump
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ /* Interrupts are globally masked initially.*/
+ cpsid i
+
+@@ -305,6 +323,21 @@ endfiniloop:
+ /* Branching to the defined exit handler.*/
+ b __default_exit
+
++#ifdef STM32_BOOTLOADER_ADDRESS
++/*
++ * Jump-to-bootloader function.
++ */
++
++ .align 2
++ .thumb_func
++Bootloader_Jump:
++ ldr r0, =STM32_BOOTLOADER_ADDRESS
++ ldr r1, [r0, #0]
++ mov sp, r1
++ ldr r0, [r0, #4]
++ bx r0
++#endif /* STM32_BOOTLOADER_ADDRESS */
++
+ #endif /* !defined(__DOXYGEN__) */
+
+ /** @} */