From 4d4f7684e684bec319f166121463a88cd4a62703 Mon Sep 17 00:00:00 2001 From: fredizzimo Date: Fri, 1 Jul 2016 17:04:53 +0300 Subject: [PATCH 01/10] 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 --- .gitmodules | 6 + .travis.yml | 5 +- Makefile | 31 +- keyboards/infinity_chibios/MEMO.txt | 385 +++++ keyboards/infinity_chibios/Makefile | 70 + keyboards/infinity_chibios/bootloader_defs.h | 1 + keyboards/infinity_chibios/chconf.h | 524 +++++++ keyboards/infinity_chibios/config.h | 75 + keyboards/infinity_chibios/halconf.h | 353 +++++ keyboards/infinity_chibios/infinity_chibios.c | 17 + keyboards/infinity_chibios/infinity_chibios.h | 66 + .../infinity_chibios/keymaps/default/keymap.c | 48 + .../infinity_chibios/keymaps/hasu/keymap.c | 199 +++ keyboards/infinity_chibios/led.c | 24 + keyboards/infinity_chibios/matrix.c | 128 ++ keyboards/infinity_chibios/mcuconf.h | 55 + keyboards/planck/out.txt | 66 + keyboards/stm32_f072_onekey/Makefile | 50 + keyboards/stm32_f072_onekey/bootloader_defs.h | 7 + keyboards/stm32_f072_onekey/chconf.h | 524 +++++++ keyboards/stm32_f072_onekey/config.h | 76 + keyboards/stm32_f072_onekey/halconf.h | 353 +++++ .../keymaps/default/keymap.c | 25 + keyboards/stm32_f072_onekey/led.c | 34 + keyboards/stm32_f072_onekey/matrix.c | 163 ++ keyboards/stm32_f072_onekey/mcuconf.h | 171 ++ .../stm32_f072_onekey/stm32_f072_onekey.c | 1 + .../stm32_f072_onekey/stm32_f072_onekey.h | 5 + keyboards/stm32_f103_onekey/Makefile | 64 + .../boards/GENERIC_STM32_F103/board.c | 49 + .../boards/GENERIC_STM32_F103/board.h | 166 ++ .../boards/GENERIC_STM32_F103/board.mk | 5 + .../GENERIC_STM32_F103/mini_stm32_mapping.png | Bin 0 -> 162908 bytes .../boards/maple_mini_mapping.png | Bin 0 -> 237977 bytes keyboards/stm32_f103_onekey/bootloader_defs.h | 10 + keyboards/stm32_f103_onekey/chconf.h | 524 +++++++ keyboards/stm32_f103_onekey/config.h | 75 + keyboards/stm32_f103_onekey/flash.sh | 2 + keyboards/stm32_f103_onekey/halconf.h | 353 +++++ .../keymaps/default/keymap.c | 25 + .../ld/STM32F103x8_stm32duino_bootloader.ld | 88 ++ keyboards/stm32_f103_onekey/led.c | 43 + keyboards/stm32_f103_onekey/matrix.c | 177 +++ keyboards/stm32_f103_onekey/mcuconf.h | 209 +++ .../stm32_f103_onekey/stm32_f103_onekey.c | 1 + .../stm32_f103_onekey/stm32_f103_onekey.h | 4 + keyboards/teensy_lc_onekey/Makefile | 62 + keyboards/teensy_lc_onekey/Makefile.3.0 | 77 + keyboards/teensy_lc_onekey/Makefile.3.2 | 77 + keyboards/teensy_lc_onekey/chconf.h | 524 +++++++ keyboards/teensy_lc_onekey/config.h | 75 + keyboards/teensy_lc_onekey/halconf.h | 187 +++ keyboards/teensy_lc_onekey/instructions.md | 82 + .../teensy_lc_onekey/keymaps/default/keymap.c | 32 + keyboards/teensy_lc_onekey/ld/MKL26Z64.ld | 105 ++ keyboards/teensy_lc_onekey/led.c | 32 + keyboards/teensy_lc_onekey/matrix.c | 163 ++ keyboards/teensy_lc_onekey/mcuconf.h | 55 + keyboards/teensy_lc_onekey/teensy_lc_onekey.c | 1 + keyboards/teensy_lc_onekey/teensy_lc_onekey.h | 4 + lib/chibios | 1 + lib/chibios-contrib | 1 + quantum/keycode_config.h | 2 +- quantum/keymap.h | 11 +- quantum/{keymap.c => keymap_common.c} | 10 +- quantum/matrix.c | 2 + quantum/quantum.c | 2 +- quantum/quantum.h | 8 +- readme.md | 3 + tmk_core/avr.mk | 185 +++ tmk_core/chibios.mk | 154 ++ tmk_core/common.mk | 36 +- tmk_core/common/action_tapping.c | 2 +- tmk_core/common/{ => avr}/sleep_led.c | 0 tmk_core/common/bootmagic.c | 7 +- tmk_core/common/chibios/bootloader.c | 47 + tmk_core/common/chibios/eeprom.c | 588 +++++++ tmk_core/common/chibios/printf.c | 240 +++ tmk_core/common/chibios/printf.h | 111 ++ tmk_core/common/chibios/sleep_led.c | 226 +++ tmk_core/common/chibios/suspend.c | 65 + tmk_core/common/chibios/timer.c | 27 + tmk_core/common/command.c | 23 +- tmk_core/common/{avr => }/eeconfig.c | 2 +- tmk_core/common/eeprom.h | 22 + tmk_core/common/magic.c | 4 +- tmk_core/common/print.c | 8 +- tmk_core/common/print.h | 10 +- tmk_core/common/progmem.h | 4 +- tmk_core/common/report.h | 5 + tmk_core/common/wait.h | 8 +- tmk_core/protocol/chibios.mk | 10 + tmk_core/protocol/chibios/README.md | 55 + tmk_core/protocol/chibios/main.c | 147 ++ tmk_core/protocol/chibios/usb_main.c | 1372 +++++++++++++++++ tmk_core/protocol/chibios/usb_main.h | 139 ++ tmk_core/readme.md | 16 +- tmk_core/rules.mk | 220 +-- tmk_core/tool/chibios/.gitignore | 2 + .../tool/chibios/ch-bootloader-jump.patch | 116 ++ 100 files changed, 10366 insertions(+), 258 deletions(-) create mode 100644 keyboards/infinity_chibios/MEMO.txt create mode 100644 keyboards/infinity_chibios/Makefile create mode 100644 keyboards/infinity_chibios/bootloader_defs.h create mode 100644 keyboards/infinity_chibios/chconf.h create mode 100644 keyboards/infinity_chibios/config.h create mode 100644 keyboards/infinity_chibios/halconf.h create mode 100644 keyboards/infinity_chibios/infinity_chibios.c create mode 100644 keyboards/infinity_chibios/infinity_chibios.h create mode 100644 keyboards/infinity_chibios/keymaps/default/keymap.c create mode 100644 keyboards/infinity_chibios/keymaps/hasu/keymap.c create mode 100644 keyboards/infinity_chibios/led.c create mode 100644 keyboards/infinity_chibios/matrix.c create mode 100644 keyboards/infinity_chibios/mcuconf.h create mode 100644 keyboards/planck/out.txt create mode 100644 keyboards/stm32_f072_onekey/Makefile create mode 100644 keyboards/stm32_f072_onekey/bootloader_defs.h create mode 100644 keyboards/stm32_f072_onekey/chconf.h create mode 100644 keyboards/stm32_f072_onekey/config.h create mode 100644 keyboards/stm32_f072_onekey/halconf.h create mode 100644 keyboards/stm32_f072_onekey/keymaps/default/keymap.c create mode 100644 keyboards/stm32_f072_onekey/led.c create mode 100644 keyboards/stm32_f072_onekey/matrix.c create mode 100644 keyboards/stm32_f072_onekey/mcuconf.h create mode 100644 keyboards/stm32_f072_onekey/stm32_f072_onekey.c create mode 100644 keyboards/stm32_f072_onekey/stm32_f072_onekey.h create mode 100644 keyboards/stm32_f103_onekey/Makefile create mode 100644 keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.c create mode 100644 keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.h create mode 100644 keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/board.mk create mode 100644 keyboards/stm32_f103_onekey/boards/GENERIC_STM32_F103/mini_stm32_mapping.png create mode 100644 keyboards/stm32_f103_onekey/boards/maple_mini_mapping.png create mode 100644 keyboards/stm32_f103_onekey/bootloader_defs.h create mode 100644 keyboards/stm32_f103_onekey/chconf.h create mode 100644 keyboards/stm32_f103_onekey/config.h create mode 100755 keyboards/stm32_f103_onekey/flash.sh create mode 100644 keyboards/stm32_f103_onekey/halconf.h create mode 100644 keyboards/stm32_f103_onekey/keymaps/default/keymap.c create mode 100644 keyboards/stm32_f103_onekey/ld/STM32F103x8_stm32duino_bootloader.ld create mode 100644 keyboards/stm32_f103_onekey/led.c create mode 100644 keyboards/stm32_f103_onekey/matrix.c create mode 100644 keyboards/stm32_f103_onekey/mcuconf.h create mode 100644 keyboards/stm32_f103_onekey/stm32_f103_onekey.c create mode 100644 keyboards/stm32_f103_onekey/stm32_f103_onekey.h create mode 100644 keyboards/teensy_lc_onekey/Makefile create mode 100644 keyboards/teensy_lc_onekey/Makefile.3.0 create mode 100644 keyboards/teensy_lc_onekey/Makefile.3.2 create mode 100644 keyboards/teensy_lc_onekey/chconf.h create mode 100644 keyboards/teensy_lc_onekey/config.h create mode 100644 keyboards/teensy_lc_onekey/halconf.h create mode 100644 keyboards/teensy_lc_onekey/instructions.md create mode 100644 keyboards/teensy_lc_onekey/keymaps/default/keymap.c create mode 100644 keyboards/teensy_lc_onekey/ld/MKL26Z64.ld create mode 100644 keyboards/teensy_lc_onekey/led.c create mode 100644 keyboards/teensy_lc_onekey/matrix.c create mode 100644 keyboards/teensy_lc_onekey/mcuconf.h create mode 100644 keyboards/teensy_lc_onekey/teensy_lc_onekey.c create mode 100644 keyboards/teensy_lc_onekey/teensy_lc_onekey.h create mode 160000 lib/chibios create mode 160000 lib/chibios-contrib rename quantum/{keymap.c => keymap_common.c} (94%) create mode 100644 tmk_core/avr.mk create mode 100644 tmk_core/chibios.mk rename tmk_core/common/{ => avr}/sleep_led.c (100%) create mode 100644 tmk_core/common/chibios/bootloader.c create mode 100644 tmk_core/common/chibios/eeprom.c create mode 100644 tmk_core/common/chibios/printf.c create mode 100644 tmk_core/common/chibios/printf.h create mode 100644 tmk_core/common/chibios/sleep_led.c create mode 100644 tmk_core/common/chibios/suspend.c create mode 100644 tmk_core/common/chibios/timer.c rename tmk_core/common/{avr => }/eeconfig.c (98%) create mode 100644 tmk_core/common/eeprom.h create mode 100644 tmk_core/protocol/chibios.mk create mode 100644 tmk_core/protocol/chibios/README.md create mode 100644 tmk_core/protocol/chibios/main.c create mode 100644 tmk_core/protocol/chibios/usb_main.c create mode 100644 tmk_core/protocol/chibios/usb_main.h create mode 100644 tmk_core/tool/chibios/.gitignore create mode 100644 tmk_core/tool/chibios/ch-bootloader-jump.patch diff --git a/.gitmodules b/.gitmodules index e69de29b..1576b8dc 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 955f6967..26deac0c 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 f9b865b9..c285daba 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 00000000..e2886aa0 --- /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 +-------- + # /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) + MCU_FAMILY = KINETIS + MCU_SERIES = KL2x + + # - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ + # or /ld/ + MCU_LDSCRIPT = MKL26Z64 + + # - it should exist in /os/common/ports/ARMCMx/compilers/GCC/mk/ + MCU_STARTUP = kl2x + + # Board: it should exist either in /os/hal/boards/ + # or /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 00000000..649b43e6 --- /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 +# /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 /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /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 /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 /os/hal/boards/ +# or /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 00000000..c67153be --- /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 00000000..b886c383 --- /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 00000000..cb902220 --- /dev/null +++ b/keyboards/infinity_chibios/config.h @@ -0,0 +1,75 @@ +/* +Copyright 2015 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +/* 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 00000000..53538de1 --- /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 00000000..845eda01 --- /dev/null +++ b/keyboards/infinity_chibios/infinity_chibios.c @@ -0,0 +1,17 @@ +/* +Copyright 2012,2013 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#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 00000000..a44c68b8 --- /dev/null +++ b/keyboards/infinity_chibios/infinity_chibios.h @@ -0,0 +1,66 @@ +/* +Copyright 2014 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ +#ifndef 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 00000000..2acf7284 --- /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 00000000..e9a212f0 --- /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 00000000..aed66c7c --- /dev/null +++ b/keyboards/infinity_chibios/led.c @@ -0,0 +1,24 @@ +/* +Copyright 2012 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#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 00000000..2c68ea83 --- /dev/null +++ b/keyboards/infinity_chibios/matrix.c @@ -0,0 +1,128 @@ +#include +#include +#include +#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</os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F0xx +# linker script to use +# it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT = STM32F072xB +# startup code to use +# is should exist in /os/common/ports/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f0xx +# it should exist either in /os/hal/boards/ +# or /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//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_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 00000000..02c48c4e --- /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_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 00000000..99fa8ce3 --- /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 00000000..bb5251e1 --- /dev/null +++ b/keyboards/stm32_f072_onekey/config.h @@ -0,0 +1,76 @@ +/* +Copyright 2015 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#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 00000000..1a450d63 --- /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 00000000..6c48149f --- /dev/null +++ b/keyboards/stm32_f072_onekey/keymaps/default/keymap.c @@ -0,0 +1,25 @@ +/* +Copyright 2012,2013 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#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 00000000..18edb8ba --- /dev/null +++ b/keyboards/stm32_f072_onekey/led.c @@ -0,0 +1,34 @@ +/* +Copyright 2012 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "hal.h" + +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + (void)usb_led; + if (usb_led & (1< + +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 . +*/ + +#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</os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F1xx +# linker script to use +# it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +# startup code to use +# is should exist in /os/common/ports/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f1xx +# it should exist either in /os/hal/boards/ +# or /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//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_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 00000000..31319ef5 --- /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 00000000..7253e778 --- /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 00000000..d692c0ee --- /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 0000000000000000000000000000000000000000..c44a7d9ebcbf5f50ce5ad9a191bcf50cae2b2522 GIT binary patch literal 162908 zcmeFYWl$Vn^frhDNFYc;LeK$1aCdhI5Zv8e2X_q#gy6y5Ew~OgxVr=$++i39?y!^O z_wHN&-P-T_;jNmP>h7A`=iVdFdCs}rVM+>8nCOJ)2nYz6GSU(%2nfhB2na}|&ynC) z=volqCkW3hMdd{i5UQgw?u}94=Pw+kwOtSpu)6+y5#Q2$3WQ(8ca_v~RRvnOdKf#K zBRCpcJGe4An7fj3FtIRkntx?8M?iRrl93Qq^E5cjK+}68_0)Lw1O~1YJA$uP_Q1j4 zXpC}--zbYpqCDFt$)}T!eNTpGM`LpQnZzfO&`0x-H5K3V_(}Vy2N_GE=XLV#*=W<@ z*b!_*!6GxwUKkuILWcAF8B&ldUN%JZzeB+PIsB`V|3B*C3Ed{o-$qQW+(bFex;fH9 zx0v2Tjp25%x>bR-7I}XUMsHvFDr?d6tji8<$naD?NRY~u_=-R*_{4HIIdj8wXi%xZcu_DklOL zh5S!c0^cdGVC8qrdyM4@eT~_}mc{ynLf;`6-~AqfkY&H_{q6YhgJ#KdoabAmNXuAA zH=5ba;tnlB#X3(eTbrTT+Eh9?(G7*FVN*l)1~3S5Mqx>6;q|Xm?^G(A#D0rABp7@Q z2=U*@Uz>a%B{^RP)T@&cYIwNbd-7Glj!wiUuH`nUJs#QPxU==9V2&-7?yiK}MZJQy z@t=CH=wa6McXN%0*-N5iPi%j@{|TLtKnm7h0kXgStqd3%7Ir8uKR5}VD1N?ZMl|$( znn}@ij?Zv^ugdgtp*bO$Dx~;D582XjIi8)U*y4;wXEmp}siLJ`9ULU9y-{ z0tDFDIzTFfNpGm6ii~T^k2P$!&w0I6Kix5x(&9)bp*52{JFU!?sl3;|&1S$JBC=Tk zqn!GJG_0ZuNy)VZ7E&(brBB& z{k-r!x|P5AtREyow)*a`(LY;UPH6a9y~i$hUnpyyq#(* z_x-#>`C#2PIH?@;GfzcPSHmG=dMCAWW*~PP%k1fBQGb7aU_R7ZQ)z9{7<)1q; zIt%_p*3Cqp>hw^vLcjlb{II&US1dy7g$!d@=<~ga{S2Q3_CL>4@0&#Rv!cQ-UlgYo z^foQAS>RWLSt65|zWn*6kkv>gU6UlJVpyIjA5ezU=1JJ{ht#r z@(AT%({26HU@th{=U$^cF9QN(9=e-(U48^)S4(n*`o`s*S;x;No-II>n8u>`B;W?n zMgA*#;!(BuUw80SU+O1O`f$SOF_;HOqyS3JsNuYd45*Krm(TvAH3e*_OH-H!E*1Kp z*?$Pum0|z2Xd}TWgU{mNC(lzOGS03Xsu|cV2Ek6zqHpbTuQx8PI(8 z&uh&$twc$6V*cm~ZZC6X)5WF-#R-R9<=MoB@&#uZklZlTb#3zIr4R-75X!l^A$pLA z|C@i|rn6tJejqM;I`LDmZo{CQ!A6cB^z@=_JvD1x67!Fi2x$DQOCid)&Erg3|69is zsZPZcp?LqM8@yO14WDk272{L+>B8zlCeX${BZ`+VD=D&JOVm0%(832PNaPXxFF@)R zb-AZQ6Ss5BeGuy2K@lm1x(-Y#k3CU)$Xe4g#;fOT z+%K6T!e{OH->kW#qV?S#x-_=_+=b@iTE0C$K{C>M_fj~rrmD`%Z98GHF=~p=er0fW zZa*e3PtBcf?p``C{%6g^rMxIvOaSEs4E~Ff#S-=Lb|O`v&ICJ>@1f9eYACm_&gITt z#CrI`cj^;i<-{ydO{a8}|0c|hZ)=a{Eg-u<-!}czj0a895Op{XQqVn7&|i$cj(4Kj z58e!=O%U{;znn<*sjn$!g)RA~Db4=CE?$cH{>6SaSuvrGPN-fXlsIFj$>vA?g7e$E z-1Ndx$v^7R|EC_`AwWD>Cg`A|h12JHa#=y03DRe2H9{?`g948?gm}CF!nZ!BnBTFH zf_wx1X+y}KSpE)%ce^=z_`e;X;cUVGG{x{@|A)gE+~+RpIIrkD#I2!OQW!oMa81hn z8@p&k9NF@a*!(}nj^~#rPDNE(i_36trV(eL5(0nnGQz}kG0J%vkN;pD;=eUpg*(w) z-7sGEl`n|XAI(@W+U{OLWMrF9QPP02GThtnu~am`W90J6X%%C?R7KdIu{nQo+F$lF z<@J9K|4_gGqlf=5e`q5*J`iWUxLj@l9cK#rpYC-U20Was9hLKsX9)*9++ILHMnUfr zh+__6X&|6syVuRe_9&EFf%pk_KB(&9u^B|15JD1FBq!0+x0*?SWB%K3nTNs(upku+{^`4KJI1( zoH{!T>Z4-rZB|(w-6tt#%|P=`6~y77kB#Qa569tUt9%*YD%kI0XTB{s%vkxc+ZVY% z0_+Bzg?guAEeGv$1A`JD9(D~2B&R>Vym0p*dPbEg?1j!XmFouf!8XHcB#}OZt%o%( zZ&FKpXL~rCs)|*3V3P`^^MV;1f8j?5Rmjrg2?pF7-(kXmmrNJ{2TYs+59Ikt-6o1b z_5INnik3^tuTpnDcM)eKZkv6WO{Sa#An|7yBc2bJl|EO~)Ku74=Y)LoejlCo&!nP- z*WIJD;@`f-CR{sQ1a^#U{3wbBP-vj#p6Hy4^4~O)IJQi7e{AHvtW4*B>W#DfD=!-R zztwI@uVrx`N0AErASMxZPgeY$>;$SktePcm<-*)LC0U+?krQ zR#+IZyqJTC{*}h_Z{?y7flC!I{=Ue|GlGN22#9`(&mDSf1(gGuP^?QaaP{eIF7NaQ z+bX#M09oHcA?>ox4dfHrs4w$a7j&u60XwBuytx|}UZqtS;Bw<%ixb(*6!K>SSIti^ zjLzg3dRZ?_2gE>cMEKx*>iL!wDxBaT-LPJ-xd)l{NB$<}GcJ1?9iBT_#(MSByXbb$ zaNq$Oxbpb0X1pG+2TbZbdO#baxvhf;`aRPtH~XbTn$?*psp|aX|663;{g|+cB%8E@0cjtoh0Xumltt{B_?S@NjdaUwWk?;LlatIN}pi$EXsnC!;;g=nLhmf?7G7Wfocpe2Wbz(?K|1PpWdj;kWD~^2r;^G2;x5a(5cq4mk zKoRvdVsCI68XQ2rYqr{Y2Yt+vT<~fWZ~gevDNCCJ)2Su#xBwvy!GRmNL%iGeAc)$i zkfn3|`|%-h3CpRG8<=%})@Y|QD6I%IjLxA{#d!3(=B{BUUBdcu0E9F3m}B(6t2R|) z)~MG7eMM0eS#mg^r{862^NC!7A-Em{yOBR3$d(FI-yN+7hxRtz7$7fGef(Id-*7(} zd>v^I{*b+AhN~1^u}^KHdbbMENoL>?n@io~?kf9nkcY+tzOp0*`&}j`oG4 zEtBHCu$@V#R=sq_)S4hcZ^$sEv60|h%U|RV`H49WSt@wb>hp9tlU7b-+lBPG59tGzQ54s2hu>}q=K2ceBHwf_A%m5)(c)Dl-mxWcI85UatYcW z@{V-l;LDMJTf)t3V6P2gwYh)xv`#@C0q}qw_IgwvELSXCxDQZ#3WNw=w>W;PIL4_o zb_fnXJIxfZxmf50t_nZx-gKRQMZV+lYH5DEYq8qygMm*fjlHGZrd>sM{qCmu_N;CE z$xB6<%cqAdnp^?-Pq06%F@J^31c+l8BEvy#mEf-%ww#E@y-}^q1Q#3BbCGkfxyp%r z37FVs-&Jqc2YZ0U`(S{3!GONQ*1AE{&`6q;)TgTlVI7wikK-(1|2EIZjYoGsz1z#t zVd=ZgvC*rGtC_Y0e*Itwd4uLL9Qc`1Ip-{^ia^6_8;7l-0rxNdWYYWVzfiUsiJh9C z?0s>+T{r`M-JM4j0eDA%<9l=N)yuok=Wum73Yn{1ZS#8AIYz_QWHjL8W#wgKu^OE! zz&?ID3G<=NY}Hb!HggoV44Vurg1sEe>@O^=|Zx>-(#!e zzG4_4Ai`8rs`$cc-S&?q`2Wl5LRLRa4z{Ov)8;C&@Ck4QZ0zhDwPYR89zDa;6D2eC zTkCS!jCyG1+M>Ry);u*|@jKSTW3BAs{^YFSt!(JI2Vj4lH;?6MB_j7if0(^}snNtu zj%CArFt%Fr%^ZZ&qvh6z7VdbyYOFp-_{XpEz^xcHg=ANQZ4L`?=MOkJ@BQ984Aw)% ztg0QBj%atuQwPDru6NUN_#Fe`F_e4C&q`r2U)W(8v8zZr=lcIGGpl{x08C5C$7HpY z+*4H?PCZ7pYZhzyZn!{U-JNXfnAqp^YIC7?dijn&`jSv1KJJX0&0%hlcj29)VMUn^ zYhzYzT)Dls?;#92r{l!G7T*EWP-jYE@lHR+VeWxBtbW}!BgYx|UligxTjqO-=D2~K zPOT8DfOl)9p|5n$&1O-IQw!b_RwJQfioN+i#szzA-^W?LAonM zCWQvUSD@0CQ-epxtsMt63q+95sohL2WoKR=7SR^g($Na6Wk5V?n-&@eZ|4qRKmW&D z5WLS%3hp{!2CYj~Hf|C|j)CKQU;eChyl%_=0;EOe0J0kMZO`eJ^77ubv=EZW44S&- zUD$%%*Y+T{XpOd7nK#^r->F3r2{~UIMK49j-85zh zVEXRj!|}xUPh}?3M$~a2^l7T)iaASgwb4TV*O!ToSbtXBt{9gZxNmZL@b@+@=TXbj z(;@pk_=b2Y$jJIQUMbM;nsp|DeJ@SUZZX>oGQUB3`+v18LqS0GW)f%c@-X$drWyl) z+hl7mr`v^%?HCbs7xOPg|1YufOGh(j?`CZ0dcS-@yNe9R!UB^CQ5EtctfGhUuQvHEfyVs)g+4WT(JeRjQ zD<`y%)2zA2#Z4crw9deD#Gx>}cYbg6AAC?bT-|P$rd|-e4;B~iL;WDxm(K5gx;zZ$ zS}^`KcMQvMHEaOwO_4{W9G$enqX!GO>I z7yg?2ei-iYO7rypb9Ku{y~FTSkxTVO0e>@#FfO|>Nvr@u?hR)+y=A`QWHlp5c955t1dTUfP;R2Bf5ejEA28+J@WMqI2Z7Ya#aOH}!NKg5;QQ!7z@I53z9qhgwgZPjEgKdaW>j`-@ z7dY`Zt$@8RO}bCjO%M8EDw}Z*`t6f39~WR-Sp&kPV%9a*G}O-)q;@#&A7~fT;f)+u z>%XL+;r%^9U9&@SFF-G2$N(Hqv;w@aYifY&W79?{p7TZS%S#On#pnrbRJ;eR@!n zbi5kmiNc1e;ag6F@*!(rXKVVR1*JymIM65$7!yfmhzWPM@;^P-Am3-6Sf|eZO|KER zOn#9Ge&Yjwq>81!``ja65$Jfv=5v1&NtW*a>+qRX4@R&o*N7PUiRte27y(;21I)YM1 zlUC}~xYj{%+8-;LSe>q7uH;&MpHM#_4+cpLCMdPJe0wkCed2qOst$+(>yJcIqoV2y zIUSKWR)CDYY8r7?^fCFw$VQKG}JB5!8+I?^9EGADUnS!O7F+W9yHF=+O4bK^o zLe(+L)SnQCwlL?*xq&NS--n|GdK{o(oA1Nz4RlV?5bS@taWOqtnc3!bvUL$oU1@NC zcDbDg&)#i*x7Qcb{qPGnr#HuySx+}RgR4M*u-C)ZWa(}I*!yu8T0{nD^}pODVtF_m z*HnBIdGvLDnh_3Y^>%>qo;f6{r;Eg132c3I9el1@mgV_r+yzi$`S)T06O^(FHEh z09+Xj0%n2zuinrs@UQ7r8X$UjU0i0(RX%y$9o&>^G8?vfpIn~Qf)q2`Jul8Dq5b2A z_h+~J!pv~?b$XCR&HU(faXvV_t7!OeHa;Bi_z3Oo?pHi+_dLC;ExIxgx`A$Qwi^iC zLKpJdGw&}fM^ia*`ywz2Vebg=Jxx|uEUy9rF6Wku0#RpU!S?(74Bz+x?IHmz#tS#_pY9 zzrgg=$NIcZu#wo_?di~FEXS&b@8_ho0cWXDORNowTymh^?4W>#RzrCgamB9%;ld`gq84D zmmYyK-1==Q0juuYpmI$tU?qRu?qX+#CN>c4XtnuOobw%)gRqa;Zb}|M6Rd={#rB~( z7>Z3|;NyEW#12W!oHuYYTdhI9OUzuX-`INOq;6moZu1)KBvF?FF$jR2j>0gv`{zb^ z8w&5|hZaILF4@Rak{qz=l<=LIDai#QBn#==b znZnkPr3iU;s`9kVw6r&yFz69im-z_K)mIc5-A~gt7Wr!9(iNGk)rAZtg$z!r+A40^ zCKu;D^3%B7?yEv4!@DV<$aYFp4WgUWuJ-H;-#}yxKWk5F;V`NoWCdp zHWa>;P6RF^b64p~CTBtxKyChlMcQiReBF0HVXunpv4eI<_xxuDVJkJYnW6jq<5Csa zDB<(O;=NMU(b3Wbc)=LWnVNX)#VsfEy^-st3sP$+so2`&B=^w)`0QIv3^@Z=tN1^8is1{ z_--g^T7q+pMdpSToVk6Y`@@XU_V(yBe&4~|j>TZVqPCsG|UL_xIi zb#?JkOe_tSa&l$v&VIPdhs`H)8tWST3ZZp^y5N?&Y&KYa1dc`MrI9u@kl79AcOY9o z@~cYCm__L%asK2Q1rBcork;0>~&o-n*aw zI8Xj&EZ*-OO}NWz=RZ)j{mOuzVtGyi%YbCP8Bd}Sy2vu;mcuk7I;I;OT7iKtNZ%2V zZ`&U9V0Rxn&rB$6622M}iO2+fK(oW2tF$PaE@Z{x^v5FV=PA2#(b?T?w6Sa7M_d6Y zAbT&)M?1Nsv#)qv;6o$xyd8-5s}_nZFQkXv@)%0}7(qVT$L^rzjs2t?0JZXQ{xRA50FwJ)agk8I| zZQisD@$FX%*8xJhCxzyA%=PuvJOwCygDZy*sw<$me%O{@51+d(367Yxw{$*shTJX7 zUp5gPk>>gseH-)lSVlhbMhn?HA}w<38}U^vhJO9&+dB#G zaNwx_r8A_wP3|+z*MW?iXm)^ICBfz^R8mMJg|`E~1$b=O8QgNyOil$|mgn}IKRk!E zk4{%C_L_mi*H1ewN~K!v`FNYTT+e?Xx`!`$Yeo__vU~U3B3eLTuAs|FJ?IDh-46>> zvZnQ51#{sz$*97&e)2mP>;`6)puUf`_2r%=kw(?!RZ9vgTUIQIew55YEXGPYKs9;I#e9 zYFiMLtrK0XoYlG#-_-f7Nj(j$8f=)ym|>aAULH`{(WcPmu0Sw`yu$}k*ZMSzU(;|f z?O`+RelP(dtQ9@vG&|%bJ7zC9tRe$~a*x<80bJ(CH73VZTd>+0$i^bHC%!SjCJ~1D z8zQuHHdHt0QCj+_r`|SQItQ@r1md+~aQ%>NAk?(W=Pr}vw*NZkgCVk191R6ubHkp2 zyfJ_fjN{8!`umk`^ZiFVp9TJh>2BN%Zfq3$!R|H44I9XUl4xZpcZ{BQqfKa|jZzHP zp^S}pqYHNvH|ie!RP_+lMolegN6KxMR<2xLFdLQGEOJVBcwTe`q9YaN z8yNMPH;Q%wWXAcV?WEX_HTf)Td3FR-0 zhBcBus7QI6@t>y}+i95>w{*${#8qEnQH(D4>C{s#rpdX^Y2!0Ba41LvN3= zZ9*2BUO&kz3{-kP!%99Q9=bX@qODpPaJw84H?N{X44Ux-D!gw)!`a zV$9DJ@AXGH9PEe%>$cp_;gh+PHnZjF%^wAs)^qm5RggzQmpMV^3`_Es>Az z%=vy(&n%m&Eb)LbmNA|DNwkFt&B+qhdOvKRSL^UE+PZXnBU#_Xi@pTV zZZ}m~BPZ8o8-PD*T{yFIV7n9V<&{ojhdcLgeyqheH$c8Jr=BhR2pGs{U79%XS8ZO<`)b`z2TjQOqC$dkB~EX-_RV()_!N&E;zn)TzHQQ*kO-4eI9D| z1-$qLS*ItD?bKNCl$`d2+kP_RcZaU5MNn=dU;S@~lXKaGZKGS!?Jk`ngZ>N2Bu;|e zf~~W~y3*S+Nb`9M-+9Zeoa7$s@vr{lTLzq~2rakST-;LHL&>k8WU!g{D!FL zRObY1Xy0x53w-Z3mL_+RCs|5K6!DPxI4cW@5J2o(o&olbQN|J5-_MRa7y0-&UQ3F+ zx5oXAT=2uZ1lL2Jd4<2!uBI|t=qnRttXty6Nk$~cN`+RO zadggHQHPt?UgncYSyBsD9C$}#&r4__cM*;a`;25Y5^pMEq+LKzPGpe`v@3qujd4^2%BBF~2F!jWBcbc24Y_l&keEX(iwnwW6&Xx_ zH>p)5zu&X8+lCZfRT*dqJ=~@3r^S{Cz*{PX)2_*S-1_VRy3~ruvJ_N`(giQ}7+yqf znpp2b=RG{L3~)m*UFxc~V|fM8HAl9fFDO?YZkf~5>$!Lws~e2M1DjPvN)le#)H~|B z;mbQO<1oI(_=cN0HLSBo6ml)>y5JEsPf+bZ#CA-?LV8dOAgnqjsyQa8Iq)#7pg96{*sfS{4t`1YD7391^Z>-F6)7vS--D-&Yw+`*&v6xZC?NThgPp+ zRTVzPz(Zo5?1ANXzwc`2s7VD@U3RUDUc_WT6b)!==8%f$c3?-xw`m!$EL`MA!j-2Q zz~&F~i)Os_HmaLM)a}H0cU`gee8u)cMlhRydY91@a)kx;qY(ITa^w^mzJut|q+0*` zaj7X_Bn`RnSaamw)?lA>`{uOAjh*dkgkC7s&{>eqp+3kUHmnI`4@3^q5;K*ycBN<| zTLhj5VM50be=?2_a?MQbswCU3*{I1IWy z??0TRykUwQGK<|KM#@mMn5zCjNZ3!V90VC`)Z2ycQrYV~jnACvCaO!`q3wm45x);s zT>rKw@G6qp_ywx0B!-=>pt%nPLW*h2^oa~wJmJZ4MkK(nd!bPKCfxMcQ3?6 zZ7bfC)1b+bGNwC|@w;60%-dIsp7wA*yuPxwojov#wlzIIm;~6eKhByjv050^8m(|x zu5jl+S&Ot=P~Ob+-;B$bzLhFfZ?-^r99oTg6a{b}oZkyc803`A7+x&nXInf@ z{k3Wy4|%_#Z8}srs{?xXcDP_`C?Z)_GAzlNNRA8U_^@gQU zjxJcn94QXB=30O-?K@>0iv*um#@NPmv3nt(uEvO9ldZUgT5*${lmsr@ATeL0d{K>+ z8CBd+?i#I{K#F|fNwF(=u(_#~n!3P+)y2>@yQ}~)38kD+^pJThuiWcU@y)ZwsWz1p zS6eV8+YX(OU*wl&xloo>1KrF8Ueq$)k4xGgiItwOxm2+FQnvwKgXXlFAzvItaNRUQp7hgBL_*!hWBmG)-R9!G#=p6b$GG>Z+(Ul{1=v4+ zfw*m>FA@GR9|7Ea>LToO`PO^!i2jrQRN01hQ%SBvJU1d2{4&v%dcIAqzkR*8tV>ts z^aUToq8>_EK^%_M^3r#9^*{!?1ld7v+XV~NESmz6lBZ)WAJGtQehQn5xghyPzc% zH@?AU&9G)8N0^487d1j=GU)j-RxFp@iUAO5m&-Vij^AqHzkaU7__H8`I5O39RB&r#9J3 z?-<^Jhdq@L=rBj=^>{Cs1gTTLPN#X=rv%)R$t!+LRoFxY5c;(hHbV0)QQXxz54FKQ|# z^|F4F8;2Ezf$kcQJe7~ zez^KA=xzgjNo)jN5O;x^V}dTt0lEQ%LdPw zF?81!CK;*wFDM9-s+q`yoK4+9FSZk99h`@}sey;7+@Hx(%kH+<)t_MYU&`(0^D%A? z5x}XEqGhMVJ>v%?SSeP&W@ggTYgU3*s*@rWD=ol<-`&~;T#1+7EIj%~rP%~eCCJL; z5SV7ruC=9(x`0l9!~(P)?An5B5qq zN&D*3iI`!1fX56gdT2*^Z&9o*xPAeFU$#FJ4=E}}bbErVMr{$g{a{w|%x^lifd--BPh+q#OJA`}AI^$8x>QcwTIWzl~B@l9w z!a*KNwJ{|rmZ(4)>)srzk@7`-(74QGI??%6Qi5fJ+6RPbqFf5wQx}ghX5l7>nc4kb zDBCo5Q6D4Wv2GlTv5aADNKcw?aHlJ#iUzC*na=Uds{*=pQvJYF$f4aWcvY*yl^VOi39(|B&diRX{m|5LD6#lP`s;g*av%521 zTl@R*RyL)MY)r%~f}jT%B;TK6NO;ds7*cTBgltUI&Fq}4j2??SZ$fm^IL)QxI0;{8 z;l)IKVrl>0Vn0oWcToedG952O>NKe-VZaOPE1J}j5J>xC8uy%mE>v`frDUMIOb$Is z0rjAd%A~~e4Z%E7T$f240Wn*G{D+$75~x8P`3Ti{tk31}Sh(n-6}DB1iHW1WOUCX! z!;9;%h-p+qN)YRb3A1_gI`L!fqznV9^Bqct?4~oVFIS4JSll2!dRmtSV$O%@&i8;Y zn!*@KwdM$l4J95sI?`uJL%WmDObRuCIU02pEQ)=}gJ>pF`Xjw#)f(TJuhT8^-&&Um zF3Ab61pG?g183JvOd7@C{_G)%G3NyV9w5YW-L zj2ZCR9lcKDbf3x}Rfl^!9+Up_Ic6zG&y^ehgf7Rv@Zu{|zj#GW+KghG9m{NfH9+oN z)%!gx;j$?l;baKnqh5p_5N)VYDJkQ?D$Zh(e|o~veWEz^hLXN$d+YAzOY%YAo)bph zUfTI}sC>+HJlP2l>GB2OF(1e6`<#7T@*7j*Uy!9A3KlH1a(D@yWXc2*Y?z8hIN#(1 z!Vr7HdyJJm?a&nmemL%n;iX7*vi&~jfZ^<##%k-ag$GeivP#e;N_WOtec%i4*!tl` zY~~s{o_!``WNL+u!_O5vO!mV115=nZRjlJPq)fT|$!{;Ia3lzWr7X^51OO>gQmXqr zgyCHl(>!n9CnyxU48CE?>>x*4H?6?|ZC01)0TSr5oqAr%kft~!x3P$aYkbHZ*^b?D znqV)F^`RB980J0qO`)0WVObh9HVF){p4}o?(AIustR1Y!Za2ctfcY+UV0K3MCH4n{ z*KZmJ^ho9WUXZ8+>Ary91P|Jz!aI= zPrY(LLqZ^=z2UGLBTS`ZS$?+NSFw&(I%HUv(E%gOs89i{i{^Iv1URPp;zueQb ztU(>u%sDNJI1K)<+G%Vt-ic!J@Uu8(co$oruR5TwkrlW1$4k5tH3_|<;YIVjxtME? zcL7nsV2OSIK*=#qE>{pVk8$#i)0fjb<9#ziIAXn$CQBX&Q_fbkV~Vt;ndJO&VDo~b zj#7t^%^ojfoUE2Wf-3Z7exzu>GX68dU}-6Z)*ti4bfM#GFYxUMqJh~t1(hYko6q+- zm?Ek2RhmA$j+85mk$Hn2i~3o{*lCXe>nm;HSzYpbU40h}682ZRFVABo*PUeq$b%?5 zlz4au<9f`<=bl(ay~#6jMz;y2Ia}@RRLkV3hWAk3FUbkH7Y4G;bY+v*s&b;xqAs!u zmWyQ&zcb4(yo(4 z)zIh!8?H+blBDix;C(#3NCivU(N=14jxGQ$0wX2qM`2m&JP+F@XR4;~F z(N`~G$=)$Nntw=w)NE5D<$%fy3uS>03VwvCy$({Knx-|QnqXy< zjPB*ku8!alAVT(2HT7dP9LcR&P~-Z|_~9EFzTNBa@Q6~U8;%ORxKjCo)GB;12dCZn zdA`_-gu#M|c{RFuph|m?(7Qhmx#2){!t3fAP4FVS$*Ost zMaA^2Z>BH^;K<{p^=+#xsL)O8kzH2Rosx3!R8^X`MqQc#>c2%ZnwnamCu62$^yPit z4{J^>@jL83JaqmTIdn>rxU-LEYnd=R?EJl8kQlkQ#0DoEEcJOG%)0qTvh4e+H{s!l zE4amuR!fSKL@h`+qHoiY@s~@1ReD>nxH*c3JX*ac0$}21vS}pHQDyG<&3Kzen($1)aO%VqVy8etIi-v#{KYi^f?L0%76VlJ)T$-^rpn( zOCT|IU!Wx9@Gacg-u)PR-W<#u%G($$aL7dz{PW9J=4*X<^ypAabQ(RbltHlyXNuav z52y)ax$I3G%@LotDcKo+4JHcy#?$)oDy)loGT96@d_<)0QreX-wvTLz=L2fi&?{xn z=9jUwk+va}x~AVWJioJsF_E)*sWCZO{0l@>(gGZU!&Ri1}aT!&Uqd*u6ar&(O?OuNz$6+ zTC!A;*-91`o{r!-X~$g;fGK!`m-=*d?+DW5tEz~L3P|#caF>Va7W#-8=;n+Eahcsn ztF?4-M;167zT`%vRks+9+mKd5Y`JNoG}zl3Ae<#rKcQZER_2pQebJllWbu%WM8c2T zf6h@|`KA5RkoLXJ%sK6`7KyT7#66*+WDT*Wap+=V5@_Y$+txEe{jGf!WI<0?SOqhRh+nPe}?&a8*={;WWjmL>21&HEftoCye>5x z>U-Sb)>IoP_@F96L$cQTo`*w}L5`Da0B{7DZU^R;czw?aYDZ<%6Qh~Vws&TWr52(s zG{F0rwXq)Mbb`jS2LnemY;SobFKV4~%3TwtzHCDcW;S&;e_0sciBsi?#HHA^mR$X{ z!Lv}+wc^I+Z?%|*+FlRrL9bWMj&8ff(Mm5Ns>O>^wa*e z2`YGEL?v@U0E=0j<`WyM%+W4~m?E&Q&A2$o`b**CGeNK!=yAGL@H@jxi@me0FwK{M z>QAb*Dsk#L6k7THn(_6ovFUdOXi{ppg?6S6@RlpO=^Vo+=V#Pr&pw`*HtP4oBTy1o zQ+0ub4*t@`fF??_eo}s6p|#7z3c@I^RlbNgyf+h;H3;Ehnf&dd!P{{_M)-K>38JT0 z-D<|v^E$7Qd74~Ny5NYj@Sk-AG@O|4pCV-BPWA2^cEX~T0}2NkUQ@ptUESGpT+qAn zFpczSzK7_H*m_6AEk1L67Qmh>h|m68+o0=Gw1J;k{!tGs%|uB+c>av2bgK<3g^*2Y zMMh=RDrHQ9F^~98NHv5fh_^sshfvDYYeV(*;@hBGYpf$~fRivbs5W|keWS|>e5ijB z8M3g5-EgpNvfz^aRb7}}m0H!*hkdvWkL!Wa9yLYloC*O%fu&60V>B@4d5U1K&n=tg zPqm{!wSzob-a&^v!q{0)VV0sR$SxKHKC^*8fjPm)F>+N&8?zBOIfpyGZ(^p7?>8PIP`@1W1lgoph z%bmuK%y*q!;J$M=^gVlFIVtL%DQ6kik#yrW+=X;IRNm;YQOmVc?J_-=-r!W14>cU} zkqka&O6<8F<1|E2qZEzwLW9<7aurr7&+WARggxi&u%u>h=67Klveu=PBLyZydiERd zN$6-Ub#UXtQ}&;T7r?xf2Rn5mY2oxtb%*XGnn4MfmmbCl6))%&tb} zxL-JN@Hk5UQ_$a}c{H^PT1|beV?L^6$Aauz+4MAc8N>7Q&Fptg&U-5J%y-3ETd$&D6#LxtkX%v~ z4Wr8<_kYCPd$)e@8n#Way^SJ7AsG4v+X=(forJxEcVfo=KJd|WlrcC$o?>(q_s|aa z_9D{BJ&Ncsb8Veq_vn?Nr}VG2&R4-pU3&UrdKnM;Xt&sV?-l|?ZV~22{Kw+%T0XQi ze#8b43))#7R^_l709aQtW5or#1kfZg-J(yNqputlok@Ri&2zfMxHP26US^9D1TW)) zL#S>dJ^|K~4mq83=YIcs)vX$Wt#}DYT;EKC?rQRkRdP7Gn!EnK&7a@!S16JD$d!>i z+Gk#SvY35}vbD{ZQr731Cj8O!~2dh~BndD?>cB1;91+Phh#k*yl&t;_RzoBsbLz zK^r+ERp&9;Gm9223D$d!dKvCi6YaJ~a=eDKxrf6(K|5Apcq&pfIQBrz&u{+nfZHj? z)Ff-=MFTjOvHU$_xrv=Ug}u+m%L9Vt7R@s8tYX9{Wn|*lx4b=zmoM2l(zA=+nOU)n z^-QdGefYKbeyNYGCQ1Ga*q-OLptwDQSVZJ!H@643`g=Fd;CfE+`ubou*M1@bl$7L< zlw>I)?T>_MUkQjJ=O#%g5+d=!`ae+y5pKNT%T*FIZcJoR9>^N9z?*up@KTK_jpb{% z9J|U(6|OLi?+J_v>q^Mo)=b^FR-skBKc0 ztre9vCkE&u?0ywOIZ`PWTy_R+y04BOW z8+M4_+Xsog7%bQ3lmZMSMHzdqv_9@Bi*@EZN}nL-rr#h2?V~ zflLP`^@hN=J#w>irPuEG0QQJLl23h@?@dD1t0*S4NQwP<@StHIeb%cppQTeHLZkW{ zHz$vH>Zq{<;{z{{aIG$kwMHBn`rd_-gmqq_ z&PAFiKA~|X!xM}OB#;-0>@2=1Esg9p_H)7~<*;Cg!U?35>xiSuX3gPI;~*dr@1%-z zEO;~Ji&Y;V#+aXTwpT|?(cAlVG_Sw}vD(Dd=xd>CP=pp`LFF5zB#aW-{0K?!&zux! znHfnw))xELn!B3~i$36V2jVnqiDdXrxj}}CF2owi zY`5bx%5gNQ=2o@-{ln?#rLLlefxnv9$*}@18Gjn^{tUi#^j+@f#z5-=QF?k5Bw3GT z5^SICrKsyE73?N1*F=%Cgsc4YT7^`)I7wcj-`+fcA)PAe$7bP(VSS^Iqn26uON+x>pm+I#(n`;gO~a~4%&)IA;wlnQ}dcq?H}6@~A&&F9DO zYu+&T3ODM?A~xS*@B+o6`bwUR<|THfKU-O$%_#_3+;SzfW_x|V#0l>f&94Sg=|JIP zMf8Un*9dXxdDy(~;+bHfD1%XcNuNX~MPu>gEA#VdaQ)}=A6nn|pfS|~eRQO{a39S~;^ zdDgyd;INQMl6=hhi5V7)RvW>lS=Qh&&yyz$mq))Z?71zwRbxGl^v9&Y)aY4Spio*; zCr7Gs%2Xu<)a1#1P9X3YR&iyInHQMlYfs`%(EB)a6DV9j_VBWN%g$g+)253;+V2*6w zo7`yn$YYfpp93Q%%5)lV$HsVi!DT*`Q`=pM!+}{!X9qw|j*!^fnsctPT3RIJhH0?L z)8de#4=oW07D}@-RoXUCw=vgew>b1^>Q05y!vSeXQ7{xKtJkEAS{ynVJ!raI`@l8) z7E7^=Y!8C&gF=czvKhdo@%oHM9d5*83kXn=79spv_bWhuvP%V_hPH2Q4`eNzR~E(A zcr>LZNhQ;tVEXgA;Bj6_sR3Y{9p}-O;Hnbi-=ow#S!b_1uhTzm6;P=YpuN=<0IgJd zTP*iAQM#hk(mfsi$OdA$&tQBu3caPwQn|Z?nUAyECt?moJf%fCDT2MEfIPiq(AJt`%K8(+>fosr zjom$A)D*DDlfI&SzvT!ik0;vyFW^wt}~AW8uQ^|1@{c(Od0aG$}3z5d|o315**_40A=}6g1_b{0eEj2?(yRI z7CqH2ADNVI9I^2wadOwmPzy1mROQKcwyzE?R31caV(2ooI6i|J494BurC6AN(=1^# z^R$G!e6w9#-$N&R%MP~YogDd{9M`)0R8R~azLfYtaRf?7V>#t zYgB^>tyBACZMNM6ib7)aM+@z@Svjw-5&=-2X6i?h*1=-L7zzK>t)}dod zVBfE%h!pm;G2Leq&us$3=@W`E-`4UduivIhA$iS$)$&08+({nT)rtJchJI&s2^kFC zcBm#86kah!H>>?|YYE6H1^stQd!M56wp$Q4NUh@1^-pjo%W2h_Z)joe-(K3nflZ(V z`wdyawI9%gy4bFl819abu79 z(yO{^+ZxYV9S_H|RV|j5ai0h2A2t21%8nLKV^C$%_@O{ld1Gv(K9DkLT5(o#tt*dP zj^nz|S@bkm$Cb(aGnhNQKV`HhvF1vQ&4&;tS-eXu7J=f8U_|0u=INBXQ+7viAY39( zTae)<6kK6Vz?ZF)n0Y>8@~8W@*vWGnU<~ZRa8%&u!yj zv?goP?>y@feBBzb@R3xMbdT_SFFN*~tB@J5X1PMmuGeOE*8;oVoaWhNggmivzN7>j*>$BO_KGvcrJL)|i; z5K&41rq~pm?WeYK~dC( z<#RHS1aiY^$=j_eV(kBES(d{VsavzEON&KNy!H!UL;djO2vr=&*_*W}wfX1OIZaW? zU>r;;*fFH9-Uh)}glM7wamJt^4OD>;;jm&9H0oUsT;_nFY)Nv!6<1;JYEj6O90Hyu zpWSY~fE>t1j_wE1cc_>sr4!8gon)ADudfKnVd^ox@0?k4^wAP&C+q$lH@{%-eX%@R z$8q>AYLkd#g6Jtqq=Hplsb>IH|RESJl`&Z50JWiFT9;SA4Zs)Yx{RKl8e z#5+2a)v=)`@{RrI%on~x6Mhy$ILN@f&SHifayn_MZdW02Yqn@vWB=|X*NPB zv4?AoZ}EU1S9FfoqHAU48?gYO`}_8v92;r2mcF`p{L&u+3i+wW1t5Zo6T}9dqRrX3 zda@BtzSLU0l>JM0o)C56rW84+*mQ=AVhfgIaID?PN>pPpviM!9X_qaK_@18>gTt}$ zvnqZf)ztKvnYm7aS+^nuI8u!Ab$G3| zl6-(HQArYT{ACJEf)}Z@Eh%QAcn<(Pk2-X$dm@EwF=r7_)q!;<9^%Qy>$w5bGvum? zhccq?pqb#1J`Hk?-{$QWrfwRz?lF0-T}1|$R=3ikE`1e!3>P$#`4JKrnBtdgtjNK* z`T6|)u2V@pc^Kf@8=rxRFUT?kN12DqO~H${Q8|$NUe#7&NaT^Y^$=^ z8k-}QA8LO^&>BXmF}$zhc!xw={3cbrlJ9J7aVBK0oC#KEV zy=e7YbCP?QTB6ZrP5m#wATizeBDuD9UF_&eRRCWbHhBjN_0A!&I@2A6iv}#*w3XPK zf>@%T4V#KqVndTiXvW@^?<%rleUdAX!~vbdn00R-InbnE+H@pR(#WSi!i zYD`>k6>1Wx2MTOXGhI(hvt1CxasM*Y-N))nc8PL@+updT4T$>%1(z)(?llel9J;hT z85!2%e7l=^OrRV{2A`V#yofD!B#kz_>!G_A(kI1cgrAu4bGt7dM~d8qREi%ICI!er z8%j~Y<@j4X+@9m;+|z^EFT0wNsCl@L`ZG7k$T1EZ$c2d!A|ghNHIr+kaJ^Y3GE~-tBx@IW^6G{|}M6nda*sPZgzU#5)sjv>wVOZS-YLc~(|>_j=y#izZQ; z^vMFOZ3Wg#E5y<@ni8u-myxfyz7&DgU57i(x*(8WtOlmBQReZY|M4R;hB77NM0VO9 zGv7kT#VyIi4cz^TZ6%i>lE4Wn_?$5Xsc2bNqE+_v2N7GzMH{vP5aSU6@K>o#97O%P?eT?NeT-QPvd=y zuCL2!bLNP81yP!AV|Vv?Si@sH=x5E&pJpxprHuAS@X|M?OeUi~7`&C9*v-6z-QSCS zyIaOO4KDDbLHS&B7W;!TQ+X*l2I~@v!_1;?Z(b<5Hx5n%7Z-Qwm&UyP=3;Uf20$=;@?S z%OS`GJ?pf#IAukFQ34cw%pM!CFt*0J**a?B7q?ctH2t`~gooXUy=sX$P6$ zF;}H)X&l$YMvwd=mpWuBPBAl1O;Yi6vjx_&DrGgIHaf<^>mWzfVa2BjyFEe?+I-3} z5jj;FRDDSyou}v5f2-&9!IwD_7wM|>>y#^o7}%ma;o+yHzX4F88LeWK%oZv6wfCf~ zyo+ZlY6gj)))Y@)k|CKiv5uUuvM}d?4UjY#pYO45uru?Ic6RW~)yrnAolZW2P0A$Z zlJ$jPYsb6j_H{Yag~ye4O>OU$OwNVo3P!$)Np%-28V~<`VtKs*OPl*3y?X<>oM26} zsgi<}P3(`FtH2OsG^;37(17!g8^pxRT~IzwJ2t6Px-DG*rYt#N(;q}uLb=H-#iatJ z#~&F<$Y`+J(pHg@l6J)Il#x^^n2r}o8C;gTGljj&!rMPZ0Kg4K7&LgjwD6~{vRMu5 zQS4>W$y6qI=}*;!uS@OrP$5S~3l*nyKVe1)X2_d%lI;7&R}>_aElon{bOSyQD-!Uu%*ptJA2DVe4-E;LZEnG7sq`I#Nr&hRb6wqy2()tyX`eS6}KUn|V zvF%@Bi;*`7|9OU@b|;D9Nx$u68DT6`x#LFP-2ynfid~N}aG+pm9tChy1nMZsBB744 z0q+0FpIXMQ&w3SIlu-Mv8%#s#7V%vL-%@+?h5X`@^8IejPHss6ukD4W>+BIr z7PfO~2wg%N)CmQj?bO)9WBaE)lGU>Qr|(Y9Ujit4AZ0YRPJCPnix)7ZVaFoX?^oqH z%xB7I@o=oVJ&-YWJJ(l0bXa&l*a-B<)x*e4eus?;i2enlFcKbKM0XBMs|S?2n^jxEIo4rYHl9Zq3pWKcVG5WskuPKMH zK3=d9i4vmYIop^J^@}2*fmEp>rD1gjn6)H~!znv5QawfMP%p#D0-T*6u4{;7otHh? zXd-8F`1e>-_&0Jt;>&ekG7C$z7G5Tfi5n^RsexT+@EY3 z@xL!w7|)4oSk-ros!Sa*7CMf=BH60%_IKf$?)(t z9A<6!6n!ei$d$y{FWpd$F*RE-&Jo#uUV>rWH#;XGN1E`OD@7iy0o;}*S}f|!JQ&01 z1Jl(~+bP;UEW8?x3GQ zQDY^kW3-U#T)h7);dEZeH4?zs<2V5)q?hL|gI1J#F2Inj@ta#Z^~?)XFIC z7sZvza{t&DL7Xkz(jC886J`kXiC} zX@2>pA>nc~cnizxr8&adrl`&*@l&>tgt0ITBaC(2Tkd$4abTL-Glepx&grq*iYzeE zCX(;!E}h`kpSiIa-TP44{5Fu9(%wITha z3oC)B=8}1XXY2%mg)*^jbm+x~JNSWegSew z>RIrlO`MxxNl3usUHrehFrN8$@Q-4O^$Y%atH0E7&klVkXJ_D0)F{xq?W|Ji{ zQmZSY7UuSUPbi+QS@cGY3KW?Gbi5!de%MB!-k48I*pu>Tl_wP}KA=;dz5qSUgTBD4;@z zK#8*LSfT-pp~}$W(&NXEiR#MRW;*ds_YLOO4t$5!_PKYC00Y=rUa#Fg#ZQ zKx}OoPh~~HXM~By8dt72kYnmtB8B|yU5m;Ybyr5P-)25n0$tPHa6VzpU9Uysg$3IX zQQmd6|zvC4Jl(B6t@bp~=xw&I#j0FtgV-VYInD?~tZE)DvoYQCbvx~K~5 zrnYo}r?igq3%FZr@$J7nd1A})`e=FC=NrBb-K)p(J=)%Gr>V?m=d~lstl{!1s{bt; z@RUROe`}efe&mWQ*4o5ftwbPTbR+)n8u0l%R%!SX0l!GzbKeIuyVP5Xo49Eln09N0%-{)y_%oLQr2bl_Y{IMUF2vKQuysH>5{EdbfF^Uwm@tYXN+^2PxbiD@t?TQhZa&|==l5lnp6Rkj+LT8z{5d`9v!F01p`RUe0KEi5 zMj1s{ty{1gnXlc;EEp~W_i5WZOa|KvHb;pe1$_YE@ff1SD&1g9TwmJ;9n zUNvgAo_8S99JSL*3V$$cdd2BP>aiX(rp~PK>U`eXJh|?CeioY%5i|O$8F5EJuXm1= zpz%nja_nsRkf68>93;IZJY0&@Euz;L6`>iXhY=L?LGh!F64kp8JV!>o*fQ~El}C2n z&UYj6G7kEpiHU=oU-3h@Pi#}+=c(`&zp$fKu7<1sSDv6>QQdK`8j(MFM}JR~9YlW5 zLPJdxa4_gdJYq{F&g_-iy+XZwB#(avaW=K!+y2(n`E<3+4Xj$R-Ad1jQ)AwxYV;e|g2B*cQqp-|c>A-4>`OVKp^1iJ0{_jYxd% z>!+Lh|7s)Lf3-2$`tG7c^2p_L{arI@#M$mevOV&KcjLjttQ=;}!pGZ^wHQFPCcoMs z(>7aw9H~<4MEBp0&U}&HG>PsMh0YY$A^O^M=rW0 zSyMD1Q>VlU9M)oGwpEs!Xe{-t%Qzijdo1MP0T2gbtelPs=AcG^~i$J8`+kKXo@6M{Q(tK=vn;N32MckXkS)INvpeVeyFvgo1(WlLPr5_H@RR8-^dHBcmRjC+6G^@4t2>CBW`>W# zE^^F4XqDKOI$&l-sW5euM?97u0^4g@*=t+s_gom?=kZ1rMKt`7~^80@h-FjhNaz3+dNbtg)xqE6iy zG}DxR1(hyI+?lAu78nb^;*cPOtxLvkm z4Bt}H3p9C7`P8PLTq6?L{(D{|tC@q|IZDOnU#y#Awx5P@$-WT>4ru?_0rQSsAdb+@ zbbpr&4Z7*BY3Y!C(`F9{@tP7VH3I~Z9CAEw)*)g{)~6-zDH2=4f}2lkl_yZR(53C_ zN0CAmodnIkkj;~SOPy&MaK~)SXLH%=gnv~`8gR;ru+HS zWo4gjsgKfNyfu?u#L}JQLj+B`TXi|a^cFeE6UvNkEt&6`l0TK3lEF45M5fCO0DIq9 zkRlG(VWP!$w4T)p%xC=A zT86Jz#U?>@q^B64&;OwKYUa7A7P*N9I^`8_d$oa|Bk`1GY(Fc}4Z@_H`RK5RR;P-s z^@|hk`)G-_P#M_lZ0>@rm5Xf9M;Ne~s&Fr(5lUAq4&QKJ@9>u)Fk3{;K8^0X8QB#x zVuf#@_X54;6%LhCs}rmp67f%^BX5PjOh5CPBEGM>22CB3bMV*JMAZR$nM>*tjTewx2OWPyvL z-Ia!U`z&*2v&=W8K`lTf1XWwOtpj$O)#t3|>%JPG;Wt?DPjO18Cj=cSu3%Ida=_Lw z8bS~{6d*WAio9$P#k((7ky*ut4F@Y~u;19R#=?dRmmo+29)&qTRE0^1|5FU|z$U;T zOtEO7Kdw7MSy{bMPLJ90`gnJa;@-_#^tTbFHD4kw4LTzNB9Ee$gNfVl@#*dHZ36ds zAZ0x0eDIqqU-mCa zkuGMnyEC?PDnwXxVS(ih1~L{-sXI7ye&u%Mdne?O%JPu+84&N-O=H+8;&>_fl}B~{ z{d5xz`FL7BEdu#lZJQ>$`u`V9`&461Dw4^v-;h5Z=py_Rvass(OFWMDLcT+6j>Btp zc(Cogv!7L=`eI{46*4-s`@PsbA4OwdDqLZQ4aA6AzTr^OWGk+omZIsS!cr3QdETi( z#s@1%JSP^PoBQSzqVeCDhg!8$1LI0-(q1|L1ge3vN*PHB(IL+P)ER&JYMY1sU8v62{JyYprH#|Ln{z^!M4zO05cV+nU>qbqp=`GBZn1if2y9 zyfhF$?2e@tn@{pHJD*q8?PsO1KBx@W(*`S7nHCYap15m`v=fu)fMcs7B#Es%@8gGA zy~V*!T4C);`3XI8iI%&~T(UT94p#ojI%s7&n5GD!NSL<9w3VW(Xz8`$UGUBfN44m% zYbk+ReQ0LC-|XBtu^JBD2-E_!zZ4E$efs%V_0DJKIaM}mVr^?$307_V=HQ}bwFr04 zQL&f`1vY26%zsFE*2Dl{@t!tzy4hv4vGG>U@qLE-^M5MQ6%st89m;#maU3!}%R`Sq z8Gd1UQ|%os^CMb@(O#*R!kU>-c)P9oj$FLG)IZ`?e2cvp!@9?Kd&<-Vox8Ic;v?V2 zWkn717S{eNCM@m+nnm&hw7uEO?uk}ku*3CAj7s}ihQ25+Icx|~V+|MeAfm;9Ckd3z z?zbBq&mGZA=58vx#9CqCecwkdt_7xu*X0I(XVCRAxZ2joq8HF?*!D1;fA_4rr=wb7 z_usGdy!p3}RW(6hlFCux_Iw&;%Bnt2yTsI4;-)s7<%#G!5CNk5`jxNVYj6Kn%5%WX5a{NrFqJiYgwY*P2Y{hZ&roFjYa+8W zHZE2;I;-^0yx5+0WF*p;*7ogOWST}Hf*0J~Atln^n2Uuw67qK4ghZNqe_(r7u5|yv z+nS%D&LR2?`%S>vVQt1@S2GE7K36E%k4*T~3-$yTMlltEd`t(~5FFMnt-tkq(-}EE z2`I!E^`&H(HuIRL{6IhI@Us z_3L9U_mv@zA(~R)Yn?E3ky!A7Sco{hXUtWtJT5bN&lt(e+M-0dp;Vm=LJWf4Ec9bz=VUlD}WSq}1m-gqeOJTntHd=vT<|dsUBFes=F~y#4yM@3mvNdF}t2 zi|T^K^NLZ6nq_e$u|;Kpu7Lx87Wc9GlbZ=P=WKQ}jdN&IC;AFlQ^2CnrmacZ`FZqq0r*dV8+X#(e{PQ^i`R0f$_^&8-kr}@msSr;uFS;Y`Jc1@8R<;*>4Q=1 zq^LPfgLdu?OoYtb9YwF`t`*SErq%v^<}vfkA5Lh5@Ev+K6U6S*-`9Owsw&h(gJxZ=EY=~!p`tQtks>8aY^+V4Cf(la1UPPW)A z>J{S(=?Jv*L;7en3skjwX7u(EeJM@SmgLUPGz2CDtz(tjMHQ?}d3niQq;+1e_~F+D z{I0gEB=C~d&5A-y%pMslM%LOL*RyPC?`^ai&5ie_)B3$R$24oXoRyXjU;A?UDa1Id z^!;yNmnxSDZuS!&Ltx|;63{N-vJx-L7~N_8)sp`N!OW|HJb^CaNni#ImQmV z%WuO;9OD7T%(S}pW(PlEtLi|RlwyhI8a+a+77xWNkD3Jc;a|u_%i{~KyoI=nhr&>M zG*Jaln3N_$uUvNU_;Qsl*WE24XjQ*LW^0MZo4802p&;SyY*gX?B)XuBQ@86!wH>$r z8J0Ko|JBr=Ud@1#<1gA@O{1V^uWv_Kc}ahoVJxW`EsPzdmq%7w)tnEdt^X+nis@TV zfrdssK&4-RleqhTyR1b)A1Sv%v5(Va*Sf1{4YyE1bCN~N!U4kiKUEyV47_T7wNv*! z9G*UL2f}A(uv)8{Eob4hc;2hcp1r71P*Mg3p%8cGqX`$b4-pCvi|uA3$0spD#%}?!ipgtsAdTI+V%JJqXqixn|#wx z;5G6*Y93dmmS|GPUv0nbYE<=ZWYBK-<05S+s%WURUeLFu&5`+bW-|YK1W87nZiqJQ zWX0T?s1A|EC=>HO?TfdFaQmODE3dXYVFkqX7v3e&Z-n?c_ROUpo8?;qE%^fltsby< zPHBhybQ222Bv%6n(+1D=a@GeXjG~ciyIWqlwfzsnZW^%fE>!wjmsj=W+wPE0Kk3s# zMAP|CYoCK(WJ#qheJZ!=>6rNTnA@xHAgN_{|Lc83n%A0I*Uw*CbP)+d=$_}gLS~MM zs`Nepc1^xs!*Ga!Xj=8OX?>%u6^Cmt`ZD_?qaFbQWTRhOddi1-ecfC<45fjuu|mQ3 z(5&otc~7@gTJF^rWl_0&S9(b6$UL}XOW5prZWCjxvCPF~`*H;Aw?nJ1g&kQDI=cT% zWYc&ns2ELWPEUK@(%mXjI+-~6Iauk58EGx#hWiTZZjvU)HuO~W_*s3uMy6(bI>*p2 zmQoc}Df%h;XC)rt(Uax$+4AWecf-Oue0#lc20_Y_!qE&y~Z_@V~{BJv}_PqXMS)j1W?kiz}W5G`sGG zrL6ffCK)SK@GH!GM4GH!&hL6Hmtx`{khTY1c&FCcn{^?7!wtV+LR?LyjsHxq@CO8+ z^hfoUwfBwAj+N3@Vg#3{C>E(E$6?pJdxHcJ@h~JzvILv z7TF-;CRUOx$0<`W?$G6G1p!#cJJb_WTVk^AQ`Z0a4TKn?j)Q!*L^0U|L((P&>}pl` zuFp7SyET9KLK8I&WV4lR8frCfTct=d7UJXm+`eul-G*=**E+IF`*<&StJLAv$>-8P*dNl=BN=B5S>c z`^h;X0y-lzzv6WJ4w%=Rr=)*D54(gHUNjLStF?U~__sJwFqGYNk*V_?+8h)8z-&)8 zGCTqwEfx(+Kv2+2&TptSyk6H@#(%Bd#JInlUS|J7udc*NPj5S+IzE+KOqmsHJeBir ziOs*rYuG*KqN1WloRg}#Jw3D?`w@kvg2i-}Z4CO?&)y(N_RwviGuPY~4&xM+U1LMs zgDu=04hNs?bwvgSH24-#Y&?^&#eUNMo3npW5h=O3oWBk`1htSa4leQg+*Ylh zpMdtI8>xQas%1anWL9_qMBW|QOo*}@>-g48_l!ZMk6GMxFwxbkOTyb!^FN4r_ z|3fI9=7xB|_Glw^#jmSir@?IeQH)uLw}75%hX#>?Y-arHS+$6ap>=a+W}an|aVgbW zyiQhLUm+exD(Q;!+ysrbv7v)b%u^fSDHrA;^c&*sdF!{9fe$0ciMK@BrkET39L5pU zc+LarEPJfs4^y^4u5Xjq04AZyZF?JR1FOR-YT4MY#b3D$CcY`fNRtKdT~*;`@G$Q* z2Q?04rQrsitnKR*0-Meb~=*4gm9XSkO(e86Pzdnzt7jj@kG|LK!4R3Ifx=tMd*>zuPj zy=Jy3(kxRF`NCvztIuDc5iGoe}c+=R=sw(ESMwb4w5D7;lk~zhx0ExlwJj`TFw)7i?&D*an)G<_$o7 z=Y|xHM0xGZIAX>fNlcy;X?&49ubp8%m0iWZ#wIgN^ik-bPr#};rm~VXGb`miki12W z9in7$;jXgrYBcO1!^}y`dY4y2l3hb%wbsa@iE*n#iu`@hVY^hzi`#|YoqE26dBH8_H8(eY-&6mZhx-&!*Dn{_h_*#O>_RZYn~ab0i^31(PMW z10oV6t~NLR`OPVwXBsAOP1*2)=d)Qe}2HmeKq8uX4y&D3wSeS4Orr2+T8^@_KJMmotN z-$=z^^K*OY=qZV+*&NPYPQ$+2l@huMxrJ;&pZ4m&489vYyPeZqVB zDf^d88QhC8n>-jo*?PyTr>V&6_6h_oW(Q2(JKSAZ6JavB^*sJ!hSrt%j?H8hEAp$( zvOxX9MDSs*rdN3&N}7-pu;j1vnlhd1C-Nro9eC}Q&NtxhsQCUqUv^-2P!JRh#6FBC zpRJmY&sZSQpH^ri71}`AwwD2!)1mLU$>t?OkS}h?cK=`r%fGda&J8!&D=!YK&d6pl*6?%N zV9YxAT<%PUx>;!rH@Bf`cRdBGx%zloM~THq`CM~~VI`SYx|i0G=L)um*5UUCHXK`X z-kBMP_Dnwo#=uY7`HqeIkk)A56quG3&&*CuPs!6k$6@E`b!<^X4Aib=W<5WR{H@z! z2`^KW6)CU5oAV)wT(h{~>^wcUSNJpb=gy3HiALPS;^gLJiCT5T8VtfFca6tT@Fm~vJU$u3#Am@@7vmraEV3BotR{D@sK7&KPg zWQ8qG3O&)AAXiz|970o%1C@R094q=z;vcY7w^0e#NEtPkr%)~iE3#Vf7dbhkze-%B zrZp87IE+TN6Z9+J@0wSHA*C{#X-tQ8i}kME@T~!Ozo%?(r%f$z_~p3j_?NkSFFxH0 zG!KHCkO|XEh*QdnS4oXiOGHmTI1>mLc`!#2xqX^_(Kxte15H7e?^rT&%P{(S#<4A$ zcsXpeopvkhQ+$7Pul#;3`hJwTu)?(RkGQSLGAUE6F;MosYyD}$O{~&Q8D0aUWl;{# zB7NHod^+zv5!QVofvnGCCn{E=-|!KJw%?lE@CEXvovjPW;jS||?3%q){#?etki6GY zPz&9OpHg_cM@7;sv=5=l9oKkIHs(jIddQzQhsI~8;qsOwI90;8Mx^u3VM*uw1UC(E zLndfth~jj?zy`JK0{poN?acke*Lb*i1HP)HOPxm@w&U7jwwUIUvf1rS&1=rlKUr%d zD--b3t#S~yL-0Kq;;t!whPZ1^n{VF#v)4ZJjQw9SPrv!y*Lb;9u!_&CbjXU;N~YNU z^8PP(gT+x7$>gY+9*&K_CZ4|xw7b**&qzTz=|{VW^kNr{@Y`N+rm%Uzl;pIH z4jVL@tP=b=YUIg}NaYxEgDw{uJzJI^iMfpNlzJmH4`&W&afj5h5h%vP2}X*fcM;3yC_!Dp_@l08 zhaeQ}kb2&VGBe6*r%_=DH9Yr~sj%4k2$C19_E?m_Cm5JIi^b(0Kko9jpI8 z*u0UY!ZOmHiRAGmGm@_i=K3c-Y3>-E5sCwrOYmVcISoTv7^o|k)bWst4)C>t zF!(%9w5wo~SyOaXg~l*CNHB0xQvJi8v~m!J6c8JU1SlCaXdOhI-*;S^O`S8*X$t;! z%<{EE;q7Do@(a92kT2h<0P-^zqWiCijiEssgDrK1nuwtkShiIi8arfI*5q1K|rVTgf1>|3%k(P4C~fZ|yGzy#Q^fFkLj9;{@gl4_*khMfpE! z3*G{~1=7K4i|!mOk~EEvJYjxs>h19NSC2d5xOzToJ1XWi>dK$Ct#-oQ5MF%tt&Jig zEOK!s-Bh0Bx6}TAgB~^b+?S6$O|cFpUd;C+^W`|wZEw-_UjpuowAf=3#7G#Tza?Qg z(|}WjDa4r^g@D4JqWF@8v1R&W@;3*-)j!aE@G-J~_J&$d?SWWRgT6icvzC4^f^Yp> zG=Lmi$u>P7qrJb6K1_^1?7yCW)PDI$6@8WG*%BNM`Y1B~V1>QubkTY6uzC0bS&ImIuV&22=zm9`|6%260-S{X&+Nw3@g@PhI#LV}WC& zo2*g=QZPzzaA1)x`TpDk1%-5&$gcnzq6hzZ(jGl#+o%*3;A>0#+*@RdpUm%8TIDth zid9r)`_UmvB#an#?kci&K;Z`8m*^3$98W8SSgJN?2JTj|G3ntCEw`;}*S@t7?+q_6F|FJvPH9h+Fhyx{ z!E;+z21A2lQeW@@(<$9z3QJ7WGt+1VX)ZCjp}vIUk756OL%8Sn5du6jHywjwgA0N8 z|1;YBXTeQ+TTL}T3tFEPCuX}ou;)udF2%H=G2wWYy3&O?k(U6*WRo%n$J0%?AmH)Q zDjYeA)&H*oBs+vc46GJI;73Ne(?>O_#cFFJk)}9K`Efh@l1Nn5WL&^ZWiWxwu%<8K zTrRmgnipdhAFv**P|eJS4?&;RnsvWsVh&akjpe(@^v9t|^2bX-PJRF2n@$r5<_;!a zi?qcXs!;n|gEyBdeRM%q(8&*xpYUjo?{r1qzX;f4$Lw_Hd@oX7Ju>-@YKNYR@=Nu* z&>Iv!L*}AwQG(`Jej$n@2~3W=6>|!qBTU0rIAgff*r2xyd}LEXa7ysICE52ITD&{j zwim_9aKU4|(ih6beiU3v0@y#iIMOWRnAwJbP5C>FZv!x*DtWr_*`587IPA zwZMjeaJ>N%I<%R_YD+Bg+ZEI?UC^>D^Lf!1>QpdX_}KfONx{5;c6<8FaM1KjIK(qL z+eKX}wl695tB>Ug3}~;}Y1MEv?Q7BO*Y-~T#XV`&Nd2{y*}EWU1K97K>Ahz4*N=c@)m zbTj^k=u*YH10axJOl`y;e<$6S&Z!h^+oGrb=FX*ibVjIK#Tde4 zBn)PP^1gyZ&MC5sLuBGgA6O?-)~0UzAo}$4O#Yj}z0n5-J%Of+%dt5+L6I91{EjsF zl`%5gA4(61M|ezDWk->?pxfAAs+0hIFlp1^dOV7qG?P0U3M3NrJ_q?4xyB+%E3A=t zY?Z~_Wb-tVdg%xA)%p{kaS ze?>_P>*DnqiJp zLfDoD|FMQ4kpg1lVw^!$wX}+xzIvakop$^`YbJ5ayarylklwS)LNgojPEqkIqbsPI zVz2bYAL8`(T%n9_$7a5^rua>h^E37iFxAD_xbCC^M{j!NqDvt+gzjY^3+5c?EHR?K zPUfMZA-; z|9RC0>!m2xMv}XUm0&BmaA}?sgF|+89Bamr?hnVL52Jw}jbX_knc@BUCn~*oTAmOa z&DbW{+&XOteL*5Fm)~O#GONnBN(&z3F#}B%gP%lXZ5v?USQI-_@=DizlKhXSOM03> zgGFiK#`VQ%i>46=JDp8kapShqb?TvOZVph&6PQFk#Hpn>S#yH8v~39Du}_3s^gFTb z^$=k8!AD#pHL#6KMQw_!#&)x9 zR21F0QV2;#DH5?>^o^WIHtT!Xw7k(LFECQ7NHGEDiJY4|ELbkraDF5Z5sf-CQa(3d zN&U~Lvom~Hsu(dvJe)tT*w_q7#8}ZczPGare7B{_EqC*)+_XlJG%-IUw85KcL6Ghj zo7`kd9!Gq^WlaA-p28}Q3RjHIkU>FyTVZay>@iEx>}W#!ryV~~TeL@(^le)T`2i=u zIZ&2&ggldUzIo0<(b>92_-djiXHT*;eW@x#QK`XoFq|*F`KodYi_=&HBdbK?@RWa*HTVoX2%L!!A^oDGHRZoZ$l~rufc_$5; zUet46KHa?B=TbFRRK~DX>z3Gcy2sx7=Q5)Z+=e-I^!9BQmRtUn@Pp^;_T)v{b?+$u z@&%r#II_QY*g8dRD~N;l`_Ga&%Ar~-%saGtAN}n-jmcEykNW4{Y;WyQ6IbWCS_`7O znI*3>N@5791I@9323w;sG_!x0l(DP4@ts7$qeM~O{KyI-izQ2^IQ(IEDcd~;3w4+f zf*F%o#Fv|`tY5;Ndq#%GlWFO3iQLrG9)o#hV|%Opcl5#WEnOmi?D19;L?4V}L*hok z-Gx#;V~p`A)Pys7h{fY;aD^^KI6x-btl?b@Rvc8&b_?%6c*ssrDYY5HYdu&KrZsQs z1&XeG((}rDzah(xk{GKs8!T7r#<&nvRaHdWJ;ifz&O|mQ(JryT-M$gJ`O9-py@2(_uc%!uT74=+zgy9=qz!&%QP}G(Dl8AyUmoZ0soHY%3&lW8Xd7 zHuO=1h0bPNUN}-1emn45;S$5+6Sw6<*lg7olD5&2Oo~^mGJW`jf!K7CXuBMU!YRWx z-{l$gTGOzr8~*q35Cw#qF0B87jal<+vY}e`YEwN(H2vS9CCZh+__DB~6;V#6cI2YM z3CB_n8n&J(DT4y4u9fvBXJbQ zNI~#SYJVx47g2pmQ<3;K|K&RYt?4wc@6p|ALa`VM{_OHtQ+04J4q9>Ou%=;-j+K#% zM1q&39}i_gR`Ohx)Pik<0ybOdGKEUex+K4@wmOM0OV-l#khs=fc`l~qHm7T0a#H z9`*^o>Ye>o1kKJV1l`hLK}VO9zZEQIgo>`_vHC|&5WTksNM!)_pK)^}-VLw~NCQ!w zm^@$qvDTmOXYH9Z0{Ca3ye$55fhh|Imn0uE9$^r1#!qjP*|pOGei)8?3UH)Wm+sh3 zOrT}lC+FbP)WeCfs4(}T9h2M>AO#adl8 zNfxrRd;pLh#AGim=`W?|d!^`iE$O%5>6Z+BTrEE021f_{d^VGjld|m2m4RtXLSacF)(n_wQleN&VM#Kkm4z1hg*N$xCZLry zg{2mig(kVV28ES2`K310^K46te@Y7%^@JFBI3(z=vMYE4_yB@ccwy`FWWR zH7!=TSaDOGq+{}__D!uF99F&?UPt|u2E}mT{(C{}jc+1LE*W5>QHif_GFZv0qJzK8 zJvlZD$NS(+oXz;z!hrvGhb)QvSHHx~szR%)F4IJ6mQ6qvujgvPr@2|fk?ZaJ&u=M9 zdZNqUYj6KZ9k+gkdOLXD;25rboyGtu5R_GyxP5lvbjB!blro`D(;{sDp)XNU)nRp zH>q|iv1>U)PuNM103=?WvF&0b8f5x(hp5NWr$I$&-B`y%?MQ$6Q@-P+aj&l4U#z?7 ze}d~W*k-+F!fe-e#V50J@{x8zw=xn&aN>*5^-S)Jtgw-_u0X1wL#nKt@YKXj*TBPF zPX%hFrD~?7X#mq!Q#I~DpXFd_iiIPD3cOJbPBBd+vOo3F4DX~H&_PSEg~txq6b%;MX5(4^j?c;wpFe3p*f?07QvK{+gtsgW%ob44qwEk(S3&HHI$rQ zB}XIt!z+7=06w@*`?JGmuS)Yz+cWQ?jwq`%639n@*j|sV(fU;x{SV#+>USiy?;4DtD0*W z=xsXv59%Vlm1SCJK+y<$w(v}DTsYU8TCW;*F(~EsP3iQ9vZfJkMRLh04p<=VI{=#L zr2n)+5$zzcygTUTJIQqQN2ZZO!{zgUZR-Nj?SS%g2I<=8WY1^y*O)0X=k)MbdFDUe z^ImV-1rO3)YoG95Z_POOf61+z%}HK+Hf~XUUQdJb$4CZxH8vF1z^XhrHh81O4XsKQi* z2qtW~i6n_N1Kve~Jv#_EybKBBCJxWmMA?&=4$t0LT0KYbD+IDxJ!$=?;*@es%-yj9 z`#DD02)ySm91nOY&LR1~Vyb^>NVPB&ZDAx-OV@I`P{9a9uG24}*)GPZNCmA55mAND zqJ6mQMBSu~c&w=7Rb>comG-w5g(OjSvD?UH`kyEBUxqV3w*V}-U^?fva4=qbe^2Of z(q*0V>T4LUyl-k%TUT~97{%i_ld z{hY`a`Rvwyn+Cd{ljmt--K5ZYH%qqIjy@5Mwp=F6bjv7yazT}2k)SOmPF>sMj8H1H zB63HJ8{V#HbBK=|+?H4qB}|*$HarRW(A)6wL58Ud3+Gr6FD>p`z@B>7U=$p%tfmQ- zh9zf(6;&k*R*+yw4;o^n4;rxE51^3&ixT@2;6#*iV|(-JQ=N%2rwZ!TchYgJYZy|d z_UgZf{&4)x!mu1Zej!ZplCDXZrqnU*vSUa3#sz+v80x4P*f}Y#6Sq?xM$I`;z)gJ_ zAK4M>XO>w3bz2y^wqw(q5=vwpnSWL+K zbQ3Tbd=>+WwJsj9F2nQ`P2%w&4(Y7`CBdh_gQkVS`0;bh_WK8u?j?&ICqm5FBT>Z z#&Y5m-rm6&$(*?{OPCO;f`kf763j+)uhCqqHney;BhxbHiG@jJb){XAkzt{gWt9PW zE&>-Da=>H(^Qlm-puE<2--5c9a#?w0X?}k1E=wRpQ)^chFsrI7I=LxW29QwWVGW1? z_l}-CuwUV2fW=CYHbda@29KcCcQPTU;tE-g7`kR+Dg!^<-?JAHY9}VmKu50%w_g^0 zvO??oi3?IxxQWZ~Q{+ryv7{fgk!aFjeSNGi-egK#JVmHFbBK|o);diMK%1q3GmFl3 z7jM|sTUX7@R(0;_cR8y8Pg(Z;U$5R$Rs}Lq=WDOwL0a6jUUN0bm%#DQm(ZqN?kg@T zRg92RIgF`cP3hb1?ew%&&*zrqS_jtoaW$<=%TgL%c`BKXNKV<1ip{3p{B+I(p_&=# zC>&s~h~6$Aqb>VWFXnX`0B%`XI#v2xs5LQB8ut)l2m(<0J2F$U?uN?S(%J8S(khhYhH!Eh{Js_nCyP$XJn)(Ha@C27FF$x%r7E8QY-aaUW+m z&C5a$`f-V~#6u-!I8EV_oBhCGHXO*nbRuwa9hx1j=dm#BUIqHPnWc0yY#Pq{!Na$V zy>`fZwKm6UxyWaGUX_+9@5>y(BPcr=k)fl;+FO_Kes$I6h#5b)ZKu|E6s7CRpv~wx zoYud_8ZpM-??+jg=%g{=LygOlu%8|jTvzM@Bc1;GsqO!%E7neOkcjYeoUE*6V?VeL zf2g7zZ9|6ynr*}at6^o2F2+4u*nRs8%HV{kUysJU~lD-b&xQ0s767_w`WYuyCwmssbfauxab< zlHO+vho36aqTMYp+s>8G=Atcu-SLa>Wr%cH_Xif(M^0l5$4fS#WQxZ;rHWxDXyf?? zC93MsH!X*I`|W}8=RI`KO-5knJ`zuH>V|XHYtsB4Px9@n*ts2IiC#o#3=+^yB*V!0 z9Dr9bDPnK5NK;6~WlX(g16ZfrB{-UQ{hM>4Ov@Dr&rq5r4K>_eu;C;2`yM?qG3YUp zb=7R@lnJfbadc56lLf8APmqonwQi)qnT0taaEhE{Z=^&4s4x9vi>_Q!P{#q604qtd zm}Nu+9w>9@`0P!5wL(CYPQB+)NjD*j5v-IuGBL8yx1v4pGkP@KgMeSb0sv3uBy7|w z!8^Orx7KGE-&$HL@&y?XgKuVHYHMrEJ8GGyUG()H17fJ@U7AJFh`Tzey+vx8XtQjA?Qxt$B&N6j~$m4c9V^(57r$YTMe% zZ_XH|plI?NN6VcUFT7tC)vvX@hnH-Bs|zNsL3{axIAVK{l{y=S?;){gu|jWx%-Xl$JIWi17wCab?Hzh|wbfl%qv6RR%z z3*)fC*i8u0yD0uiHW`e=e)wCTosZ7SR~M5R!8(O2^uV^A)r?32oe$nn)E-E?^Ey7O&qe& zq9?!|9VO5WYXP-n>a#2jjp3yrxTtpE{A(aFZbTew{k6#xZbcxt#ivlC_irf`HIBY} zchyf`2C*_YmZG?~ga}P2lYEr=UCV@ek%|f==VrmdrHD*GluE5P-mEN}RJ^jFnFrzv zZCG$Tz!Lf-Msp7b7`kUm!TH9;`^E{rDuMA=Gx)HCy(W;HVspJ0MYd!I@X{U=V4yz0 zDP|reb`}k=vb=Ok4w+>h^RKu6xNm^&8Mf}J?nxcS?;nQLM>BFq05d2iX%Y*P?@eFd z0o%xE(|c0jI&nR{#AbhqM~Qd)b?&P>RW!FphI^{FsFtO7Svzfd`iO7Y=(%5udf!A+ zX_R+j;M7_Noc=5MNf~dPO5o#8B9xXyjJ(r1y zIudxjzwAY#19c=tK{|q2M}s3rd6GP8`bQ4jB;WtNE36%i3ni>`kCKh%!PWC1ROCBd9@feP zbZZ0Vt(6&d(z;k$Kw5e_HKHu0*b$&ea9wf`TBs{E3jUxB^?-nTn3tGI>y>-) z)NtmwCQG(P&HM`;T?aZ1B4BFRa7-fA6~qu_JgNNnRD|X>DY^bT7C%i1_feGdu_)oa zrCwoqiTzz)riHk0D_h@r$ztlSPxYMZw^neJ!2fUt--9#6r1JJGzD(p_G~r2@4I`M< zR@nCVd}sT)i8Lu~*GCvwwcV|}xrh(;UG#@t3{%GWIb*R-H{~`ToQ_TasFhavejaxt zJ#Ja_1zn=+|S(Y0-t}V$wp0^WWIl1;_Sn>ZT z(>jS_#GK*Kh_Sj&ntW3q;&c8Z9c2bdnsF*(31Ca1KA_M$mHp>^Sy^YFuH z_DU5q`#0@7K5HYxnDd;$?bFN3%3uVuP@#lN(8Pj~Q0+H3zI7E~~7SP@YsEM%nWm z#2JDnnmgB$PQ_Ol7Cv#pJ_Cb%i97rWXju^>j17cGt>929^wWZc7fVtl*b_NF{?Mf9 z(mI_Pbzb`~`-@1VCwfz%KcWJs6%`<#s~97-#dP zz@yj>FmnDxXe-%gF2IGB%cT|iVuWqeE7>yP9vksm)ux@_yHrmW`+G?lpSv~z4288a z$93l=-!S~hi3(An^<_oH>C&!PIB^_tWN&D(f-+Ts3O5^7DP2bY-j5)-KqcNH_-f^# zdHP|JvalCSa(C(<-O0ag(dWuVBN3hY(R}ro1E`H}3cPDWX))|`e)v@BBEUe-dKQqxp&_Re(M*Q9(~vDH91u1FGYutK;Eo z;Q&){@!&il_|?D;2x9{bNif04C68}IWwlS*Pfb@-bHmhmZ?O5V?>Ce z)kRg^`=i6;A=MSwsw;Cz{Z>(eL9m^Tbl8B;BDUbCXR^-7$$x2deH9tNw1ax>9vd8? zMkq`w@3C=lmZ-t2mqno4Wr})_!;cImjnl7iQ==rT-MylDu_MiI+du zkIl&gqIT@jPa-k6*~LaKsWU|TjlYI+xqFlRXpRLNC(F6L_G}e-C&&QpCs7p@TM7qa z&I43nUPo~dNg`-Zmt6ZUF)L)CwOW&fdX8xk$&-r!(1vj`{~E1ptyKngX6Qc&E)j6@mO?UaOZ z&W`lN)7y=+d6!P&eIWhP{xs{zqeiM1=^YvBLuu@jb|}o+Wf=HNYoK$SJT3dqgGy7p zutaXYA)K*eD97V`W zuhL;vuhsfA=5A%=K0ooH{mz332e_PLtS0j;Zw+hpRHzCI#BY3l6p;ocEeVArHM-+d z*r+@wNL4%v#m3Vy3LD6w0*!he!pL&#;H~rPgop?{Jh}2wK0_~jTonY7O^}^IVxKon z=iOG`9!H|yRn0qRr(~~*z9HWDHZa#IebzH=f^jOdaJY{BBJ(%Bh5;QE4_YksuBu7P z#pLe5^r{1dJYWR|H)}FVAryF!GVq)Yk0VS(isUPcL=9rRE(=_Oh!A;PZ0Q$c2GwfV zLS?}pm{FY6db<>6OkZS>*(TO1FZ@*ZonbD%K%maJi8-!1pN*mqYk=ltVZpM9P;1c-+KoWEBn_(#f2-JPj2AxNSKS>FWo&Xn4Cwgz5+TvF5DxhMuMszwVzx zDp(&C1#gk_1on3v|LWyLO9WEz1lGNrW4-EPR60WEW~HvmRw|07hqk zC_K2+s3R|fJZCS>#`ps#z6R3!TVrPY`&dhi`uhFlAKgD3C*IR5XI|A8RdVcaRpj5O z&}Mpe>g{)bFW@40f2qr$aFq>%JN@x1w+h)60ME(57}+alP=gjY6Ub|_OHRY#FCzm$ zS1t`zfoA~GffTw+fXi&|r=RLNI4j z?m37W<}@Ql4FS`np1k4oh?Rzpzk8$ND}Y5!I6iqJqnPucW}6up8XH)f6Cb2YP@qRn z42{Z88V?OA+0XS!SQ=9?$KMvBb%}hDorU}y!B9dM29^pL(j7?$X@h_LjRi49j%*d} zUt?G(z0Q_%0gD1$c@^pt2Br0dK9z=EYYRO|1%C?3antsyN#`6ej*W@M0Z9mQ@%0X@ z4HG;2*zJO({o9p0i_NwQPNNX8FjDc^q;u%ql7i$JGoN%Wh$k8uLA@?lI!z&66Ks?R zw!i6k<+bF3cp7>p+bLj(#?#Qfe}vhF6BQOUI?(g#59`-yl;<#FY$X`ic)fut|6`s`I{OHUf!Q1JnBk+jP{L3P&M#y zVmKSwI9QVKaUw*Z38F*CQQ!!{%sIG7Yu@$l0$H6xpAaO_MiNs@2`*B5V}4gF^Xt%)(I26$To z8L=S?hq1?=I^cM>5TVy+C){OIr;ARLkAVZP*5@`PmsP2Ef+Fsu0A6hLuH>&-v=U}W zIp+hQdf@{D_P?U<=U61@4C7*ZaxFi(W2~$m(bY;eWNFu$yZTc!G*{GJ|E)l@_ufy+ zZ9hXF+H_Tan}3MfaeEmI#j9x>qpD-pQ=h`*+3oa|8A|bdkgQzqgD3 zQ$0+mLvh zi@f&vxo)Qxv{n9^acS-lSsk*VdzT;s|DG_OP$btxcdw~>&`r9yx!J$6kxmw>|D%sV zl|%_kE=eN(M8qBt;3q?pzgN2AOsZOXVMvuKg2sykBTY`ck2x3pvwS0YZS=c0g0PXa z69QyVoFM5TEQNJf>UfI%vtgHlwSJBQRiv?_aF*b}?k#xhOmM9?sx*};d~b0ql<2Lo zcU-Q7At`$-LJ(=rPMf%aC|a&MP5dYYG<>N94TOM{s1PKTLAbxa0>l1zp*Jv*F%C`? zzDpl1pg9(B&C#TOb=A4Jwnq@)o)Xkb(zAhqb{SzWFVX_K+^3+uv2uYFuDW8%svJWr zq(WfyY+;Srn7m$wYaJRE^Tp4!k*b>Nd`0V?s!|ly9JBcRYunwaBL5_zZm&eO28wkMoQ0hXKs@qKhH0|LJm_q_Y0^ z@DEt_evHLS_g!D;3kXeZ)E3sU5g9*=8#V{8#9OS+F{c&qtA5Tq`Gj}UKCH77O--%Z zFnE&}`}7yS17Hxrnm_R2vazgz;fZJt- zR4PtXcqJut=ooyG;9#GUQ84DTNgDqxv<~Hga4asDio&4vS{oS&!<=r>CasT$AEILX{Z`|DzNgoz(E(P1S>-MrW%a!cp)^Qp8?ZA(u#1BZA z&qmnK5kF5~Y7G6iy4HsfBpbbh!mLbNZ}YU9{taUj{A%<#!`46rB8u?IKtq-NiadZk zGCn82Q{6p>nU_5vCQ8a9E|*i3ZVJ;ez63{NJuX&oy%3Fw+E|4JH$kSSXm@7R+?^a1 zv*4=@6?IJ}=eC~&dl8GQIxl+GhzdD7mQ>WU5^Ju1>&lEu1=F4+QYr)&u`qG|-vY#} zz$tVVckg5{Qe|Re_yL)&&{5Qy@4Or!WlE31i%!s(=*`izA0N7(KH?I1k9k+qY#x<$N9q5!xswJueoT zV1?UlO}r}wZ&em6LyJpHlEo9?&-`J@6d0V_+|Ia_K+r|POlmaRkr(?K@ zKNk1B5_tC8(w0t$#C)6^Ms@Fa_T4yeF~wPXUrx9V7uryro%sk7|L2+ZuaSN{ORMn+ zDH|aPUUy!luYQ5;%EEQe@k0|H)j@nZ6JFHm1pjsVN9fKKrhjC1$@RbYx4_4n-D%}F z_O{sOJwKg%O=GzzODW_zk4>E9U#Qo^0v{?rwUAzwSzUp*)#+cq0b{!`jk2g`^v0NC zWT>z=DSb4FoEQN+9Z91`P{;ADCk9F_by3sf9*d-&IOw~>A|auM6aLkF;j0}z$ z%+g}yC%_f#^_pg?>*v5n)5&%Js>SxVjfdvHFuuQ>rSBVF z^uHjfdz5l|(x;y=?|}b$uUxGLe~duAbyo81fJP`=b{1)Kv6Jz(1xzD z+~-P4YsG@p0)9UJ9Rj;@{d2h^e3-LdSbjEy(rx8T@{K&k`#HU=ud|ki-=h7u&pd|P zHqLz%_>nZ!0}tE_0`8x&?{7(x8S+Dtw)jp03CgxWc>ajHtNAS&h>N+urM>D5lyPD* zd3mg%B@36&t`;KJ@VG!JXqW=)IQnO))ML@#*;YuiEf(!!_b93uRyWx4U_Zut8QR|mi zZ5ej}iGbovOn7J#M4eb=lDB9**e|v2hbfHw?$oc{DT;OxIq$~uqtEHazc*pB8=45fJ8)a$8n?w5U5--L9hGRaNrfs59;#eoH6697qu%R9V?yNjW$LB;s@P zJlF%yKKwPzzy`Fh7I4#zsdEdMjlNAh*UueIMrLsIYLEc!EaPx7zn#|iEzgqlEUwxC zl{H0-oh*KqlpnLvF!=VhG%hK-$pSm{`dWp=xAyw%q?k|wpQeLO%t#lGg*KF#pNqh{ zqrQ|UltAaaI_8*yzm+IVr$r8qt#8q>UO2FQ!UHz@1;L@} zgQB6cc}iFA)jM4!q#VVT69=YksEYK;|L@HFtZZ5-m2~G%cxf+ zc+VZCyA$kvxb2kO-%>B?9WweY1D+fERvSAs)`!~(Qjb;#(v_rZ%mL9_!Z_Q3&E~|> z<;7Zr>L>Ms0wY1w4?8udnW}VEF^J(@_BKF z=3h7yy8_}Qb+sLz9PMHXr8@|%{W{90CfBvQxu@pMQ1KFiDXNQVIGJ%^a0AQP4qTeH z*ikXsUL#|?X#{;}hPDq3ko6mQN=j_dF~-J@E!%N(|6fus(xZdfn;d7}^$J$dh|gwmLAPJ(`uJB%!ONK)_ztS(t9$sT#qU2I z0j{TiAaq7DzkSY}XnqvKmHnNx`&9aA2UhWjutj~$$5yb(y0_7o`8Yjk)h!p^Zenn! z@WX>n{1-s<7yS<(MiBufbJV*beYahK^@5Cc9T{FqV zvJrjsr0aIm+_ZnNo*apX!3@KT=N9>IN}ztkj0>4TC$&0Cfh&eCV?-!b&l&a(Dp153 z0`4qqp*cZP={JNFixNW?_sitpVQl$twBwUyBNKOeH4CVc^uu*-yVT;NCkb>aln5?J z<{DieI$;mTf-7(m%TG_4#+f#Bo%PTSNJ@(jpXFw0S?q@1qy`rNBSGbg{WuhdQ*2xX z_*7}$C)uzMBiy5M>~fhdo$luswn5I|m1(3=HN@-J(;8`^wO{-mtO#x^e(lqNZX=Pt z9^ubWA%l7@)~bA!YJ2-^JIjU>`$&Q5ob8%g?R9lx(L2*Ro|Mh}!Tg|7+aVFxJdCps zONvLf`AB^c93X`8Og{&~>=;VBw|GKUpVw!>JPiq(8d%w>vD|_e-4$Yy* z${XJ|#>Sp{FKs=I_(f5R4|mMkdOsMh7HD_5ajy7;PajP< z!X2@(e}bT~;DK_9ESn!)>K^FbD%{UzVnzuJ)na+WC9=iFY6=KmH5=L-p}=CwwHW|& zTc5gQ+r0z`kxW29m#R!u6{B;;*RHn(q@lQ%fbPefXp4Oj-L|&vto_$8TsNRqhqAaH z_~KWIfsPV_YtsW82eVa<*OU~gdM>o(AU)3EwuxmyYNdjhF z+($rF1_zTdM6?4ZK4%+PD!H~O|MP1Lr)RSCH3%gsz&7RbmtsESGqK0<@Q2xvwJfZj z*-(4a$V;_}2g=`wXznM=`yq6)z2o4}5cnZw-=rolDq+6FnJULsLJ?znXw}GI>^#Lq za%&!R7rD?jlHQGEWqElv6)f8{7KeK9_T<1(vYZ5SPX}^!h#-v79sq3Wp)|JW6wt`X z_=w%h*2lX~u{)Jez5YTy;Ua^&nY6wdOI5F0`>(h1u-mQy*%9(VTjv8fR};aNPlaOOFvU6 z1|2DSVRqPWN+V{}?-@K0r&L%kj2Y<1hjndCUOJ+Rs>Y%FDptdi=r&PN))Lpe9FF*e zu90Of$+=!p{$27ze5PORB49&AM(&L>FEBQK0Noq?fHC65jw%lAnFvR=J7297uf2Ks zBc%{`nbDy#WU%PdgY8K2iEs0w`X~trYV<-+ zpwIf2B{rKKUVQU?UG`O3RP8TH-Fc9N-Y$OrT+nq|Sk!SD@4RWmLH53>-yt?(6~I!I zXU-*5ajFTWL#5PUfHQF-8)>kn^F)VqkwcthYB#7_OUYYPsg)fAGYf|+Q7Mx{)8LHr zlP=I_4chRDGq}*eB}%B=ERrn`kKE|yb*Ah!;~-rv4E!eF1#$uNf- z?_)Yqqehh>`BJW4lBqHP7k|lBcIm>s$AIaR5Wq(wQkidAZPxoZ?p|qa3P8p4l07a{ zT1vvj$J|5Rk>QQXVzSi+ricTJ#cL~VZaTPHl_YT?ErC{IWi6YGm6gqv!vU-@m_DvG zr$ZLZZ{e7qb^U!;&`YjlmObylC9ee@y}|@fUThUWNLPcv z>Bk8UCxN=iv7vk!H>xna@-f}cuub?mwI9V~5#PpxBS({zkyadl_Rgn9IN;Vr#gXCc zbk-HZ2{CP)A%=b1be=#|p*31sT+zO3%xBg1Si$cR37&-87c9CCp2lE*Qgx?bKOBp^ zQCsI({WxkmHF@#r*T9LqFKX z)%l?JE{}b~Ld!xq%{)P?h><5zw}q18HAl@D!O9VTsV>giV}!Y8Y|#i0*-AK%ZtyF% z{&hrYgNO00HKHqXTwS1;jtHQQspNy#H8mES0V`OF;zuyNT5gXRsU~>}oq~ilU8K!0 zkV{=-Ee$w%fKW7hQiUi*6w;a{#W#?Xk&{~uVIv-(cTD`~q|@9M;4d=GnlKrRi{&RD(2ca=rJ+8SoqEt&o& z`%NrU9`u{%`lV^M;Z-<@fSkQ|@6VpE!iL$u5u67rpC^vho7U2OTd6!&xvhFt*8$$s z?rUbbxww|Sqgbj)4fz{yFM&VK;rHi&|3{(pOCkB+dltD}v2t7=p)+!p;E>m6wsjZV zg`S+~cIl^jM}6$utjZ5VQ#Yk(F|mjI zz}0&_xV*XqG#YOi^e-?%Od(0BEP2AVSdVt1AEIn9o9kZ#{V1Su(}$;kNnPd+%9@_8 z<|<8IIoSiGk)w2mx!fi#T0^lP%2>AfCl{#9w6G&=b*d~HAj_@<>5h^40$5N3fa6Ww z$;rg~EjWIUw(wqjh{uVWiPP|3vFKL{gr!J5=gzz?YHAW&pmJ8RT3LWm+IZbLX4lQ-xZ(Lld?o>FCm+I_ zkCdusvxs;@F@?*4$;HU%hFYzqm4mL6n4^J&plyzxi{VDw?+s8t;!H_Q6cas$`9f%A z-LX06%0cB>{`{n)w8aH}iiPAx2U|y{%8R# z1CIoQQwqLGm9~fXbk&rPS2>xXPgG^T4CO(1ivd2+~|MM60pAFiA7ZXJVd?AP}W@NCSs&~&>PE<>Zgz2lXB6&K0 z&Gw@e{EJj^QCFA4V&qQwKNCy2Xp-)cfF3nb&eMsnlC(Hi&Sij$%qD_nmyT;{Okg~ zmIkhbteUi+w#aQ*DIp0<9D zHXe;OA;GeqrR=u848CrBPKicYnT91^niXwa86Dq|rEEUIigjLk6cH#lo)j%DDR->GWe{b+kxr z&q0>Of!yzXKJLlSshugKiG-ewK3e@*~82qu(WN|sI@uR{2aoOYh)SVfBN~04;@H3hq zgGh7=TaBm2wh1#Do#xY%)F3bI%Xi*K^Q8k@fo+`S5P?4&k%h5T1?!|OF<3GPF8 zTDG&Q>4G*Am9Yu9gp-To`>qcrIfU`xr_HYCgN~*B1ir!AXX2sapMhxOCCY+xq#mM47$a{(A6oFJHaw?)W;i z|Jt0*+xGhOFiFX2=k57;l;Fjgz19Byw##?@&(J!Z&Fk)XHPp|Oz0v*ad22BOrAo)+ zX>{>btxB8w*WSWM0Ocd$_twvy)_KZD8ymfJwYAjLI$EA*N3kd7b*_-3>D7)E*Qf+9 zaRqn(Fc0{s*r^#SPDA$bTqNV9q$sl)(x`!4({Mpy(bMoldQpvZ)x&0}AaUv;n9)N? zN7MQ*+sZ9YLxJnk0RMavBM~H=wt}#&HCvnjSHG*wCS@hiIsQF3&y#P8$YhWvU$ij|>lH?_>wF;4G+btN$Yy z6fXBRnn7=Dfvx2CJ730roX$J#ZWi0`jf5o?|EL92%qE@QZb~CwCgRe|W&r|SCfp}O z6Z~R@oI?oe`lF&TnR&{|F{JCrzuKv7`kIGtL8tSTknRJfm*dptR){&&=C6SpEW8|H z1^CkbL2>5P%EbhFKOGxP?u*jG_s=*9Hydm=gPUyH-9Eklj&fQx@gYxlpQYVxFdV)@ zjiO*vX1K||kykyX8<{a?eg8PQTRmP!@lkC)m7GsD^FsD@J-RFGf1SGA_IQ}-nty%F z+H8M(`*=S_Cj9Pmw^K?6Blm5??W3nFLL6C_*Y)H!EMHBYsM~RG_00WRxLq{i>&MGIBlmRXIKA}lHEYQWzHu3|YR~r~@bA%V=)bZeng`#yAs|gUO;b%D-Efk z^%=p*xM;oSoY@K$)J6S0p|ay=%VZdK*KScK;$CDiFLOBmvX3GCS1NtbVpD71jV8xH zs;AL$wCJ)hpTb=P4>eg(=!*i?PkvpLhYS7&*ZZlXm!+SgZqu2qZfBZCvL057yBC!g zoHY0`!No+*2m%LRJ?%XvRx9RS@z>Vj9ru5G!=sUEIk7$_rCiccTaQXnM6aM^p3ku5vo_kAe0-!|*NQq;t`{(~ zFcp8i{!t}d?K*lWWHn1`7Q4aZQYo=Sf-VyUDiUZQLdARL9(7=%nI_g+WE3`L56tM% z+%vPnGspjyHY)(>LAveC+ijpMdZ!U#65WQeWCZqDt|EN!f6AAmfTR+ytqWFN{+0}< zeW8p@daA@2KDSRg+r_I zt>dtY-LQ&$h%=*j4*PE*)8_pD$JRM;SK4jcx?2`Pq;Rxlkt#+G{b(A71Vwi%9atiglkeIlCV7FIkRUgEb7_dB<=+&%hhm9 zLq$H~nx;P(V>wnx47M(^lOXR-bAg(BaGzAf-c+WUY$j!^8gN}Y$L*T29ekT#bz>kV z?sx$9o6rbz?fnEerqzPEI6io{1Z)ae$|CN z=S=)Bp-d-7Ib}7t$rKf|Q)yMPk3-(Qw)V}T=Rail+cDO>SI@OV-<*KcWv2bQBf~hZ zFktrmcV_li2I#O|c{4x-{ScQ*O%HQBYeTA5OLIo#YT<*<8T2sb?q{o8M?lLF{Nhh8U9(Hb$X!Lem8N|c2N&E< zTJ*hByvO2_+WKFbNh|NQ(C``==}j&5KNEA`BL-g9PN`Q_RU6opZ7nNTX0+PMT1+&p z)zziU{-k-;wh4u%@#xi-S%;=&+@c_wwJ{^ujnIuukPY8l z8GEps(m0CS*Gtsurkiz9EV!B1-tER4OU5P9%G_5=sJGDA7ih|Rs#&_tTqX`$N3a-= z+(=L-RgDIBI-Z=D6jszI+(}Ux6ag7Gsw zh-**v=rZW>{V<@05n8oLKZl^)p{6{GOl}DZS!3G7WPT&lof1o9(~ zqs+MLgHjMwbtIo!k54E;cHihT*7^BW=A2Q&ETs&mUSDT`pL0Xg09D`!bq8RLuHMyI z#2O%Tr>{|mVgEpO0QQ>oT#s8%uT`b7r5RuCGQJqWOM|bl<*lzg*=}8U(@?e5RIF=h zai2?FrKNScpnX_dn$I+|T~leH+FYPqnc!GiU>q5s^IlQt_BWP9(YB5wlz?EInV_4T zAe*!{Z$F!LWlIxg)670qShrHtCM=|>lXlQbHEU{4gF&%ABwwQwZ%oND>0+3)aUQRA zlNh_$?ZBM{?r36By3m+gu4yDCrC}%Q-Wz_T#aMC?hLoNyzILXp(V0|LSinTOEB=<6`Y&}ef(A&OzdD2 zmXbZAb@MWKD9wn37HJc;Wbl8c2R-!(KcimNITa+;ExEvlKV2NU{`psDthp_bS2&1`rUR$4 zF@*!tP6!Z$|1+Siti<7aubc_+jOM;Quq}mt8vNwX(gq$xVZ4K3d`Lw4j0Aq*4{fFt z`)%O!p%m;v*1r*#i;qcoNg<99EBIR96xuEQte%=BACsk?kk(n&VqY0EHht3<6Ex<0e5g{aZ$I7Y~E9dAXmHKEkCj#6=_a+yKS4i=oFxAot?E znY0e&+(e8n1KXU7X=8|^XYM<(*}>)_%UW96X=v#ChE-YJ9DVs38a+Xl@ZuH`={&X4 zs*GQi8G5%an^mhZ*;^UtQ%170uK3FM?1rhhjq3Cwl-bapinq7j90nd&mNE-2T!?$U zEx~`WW;p*rQE}A>PQU*dyY6>(_2ik6Y#EFBb#8dT!2w}(eGPHJ zd$*f%Uk`kJyzzZ0FEp~j2Y^~7U0;rXO^t)eu9sJZoARN|WI2jQ3GWXH-lFiH)TH0a zMYiS<@=C#7%k=BWnyK_6F#m5NDLJb}J&y-m92`=Ur9fH3ukO(J$vD^p0!J!CVX9;!%}0LHK|RUd+J!pSfW#sVx1DDnuu#S{l*l`c z#9&ct<>6rraMH?v?@rm<%lN1&%FLdQKhG9-gR-q*4h1m6-x*#U4lGZE)McR68EK?% zl(#30{qRZ>X<4?eq|?>ZX{;<{9h{<`G<~^Ag&QG@iz{*0JlJmqs>j>rp8$S7d!1++ zhwV(#?}~{gfC|2l$`Ar?HuMyPK&vw@-8C>7E)u~iN?OHlaD1)I%X?FY3yxax(e(wG zW)MR|U!yi7FulBTHl_xz;epO~K6)lDGa~CmqXAq?;p3*M$9AgKrr#x_=8Tika3At> zJt4X>OCS#pZ>qI*x2^TOwbjIvA9Mlggtf4#XY2FjXr$`*+QUj!TGso8-}mCl8Tzl! zkE<^gCLHg?H_Vpt zl2)?Q5cX_Pt~de;`0BO2{#|cNiZ5!{?yKJ0N4;_jU~7Mmqy( zDH$E_tes-eULbyB-L(kp=F!o&UGi6Q+J$k_jxk1umA$#(e(P=QVruE`{xKxR(c}0i zYF&xMuV*rjn$70{PW8;}Ole+{gL8x3)0)+6fyn8R?K@aJx0sT*4NDw_AR zROzOP{VnY5OdLc$v~7gwdfCwGB=cor*XQq)UP+WLRY*sxMqx0KlHTiYuN^5$;P3Z+ zKemgy@ZBv`)7y(>tmDW{t@>+58Vz5 z>pLzEO#PU|pHB(kcM>?TNUnl;Az(oe36?FopegMLfy-!yStw3@Vb{g|k%XO`fgF7> zU*8t$4u_9*WS&If78 z(+q_y1l@j#htI`=vH@au3zTp43uXl5=_L2K@vwjF)_!p3UZ9h4u948ySxZDr+&cWU z)51hJt|sgO8g6@mdc2FpJtAeFjIdA6!rE@A$<6O%XsRJ3-WI2gGVE6ZS1( zmF_wZD9rgmznCCZglB_LY6Cfu!!;#E2JYi&9?^*%QR;q;z*s*??hU4q-O?Kcw~01e zLa*!8E`Eo4MTKdL3uGrF!Hq*g2$oM8ypvgzemgm~tl#*LzY#Kt&S~VI!zA_tqCLUv zYXf5lk%xF5EJ-^yt5J61@&iV6#x}52dj2)d_La%}YUc=vfOa2-?KJ{1!o~N<2U<(U z3D}&ISoEN*tBkraEY6pa=x#A^+g4Y86#|KHFbrYvK@XNZC6WwbFzT0Y27q7~diXHa zS=Yg)$sFs}Wxh7rjKBWs<1Y1J1SET+f}( z&W)~?BFOqhpCk-;R#n2}u46Q?CD>S$XeT78r^GaJ@;&W0(z2wSu&AGuA@9ND65r(# zl`6!|y?5+&q@%QFD0*t6@ZjxkSQ{qN{vcVL^Z}`;LJ<`IPrCKI*tO40Y@4`LjA4%zjmMS-DldXqGZnk>`}1aV-Fr zGJd}2Sw`_Insh|UX|#PVjz1c);*T~OazSc$A?zONE*)Q`$`O4t-Vh}M^WlVell%I} z`eI%8C<2P=w1j#q=k)&}cCQ`!e2WoeoMH99h*U`0>h=haixZgpNvgh`!REHntxnk` zC-BJgl!tN8Mx(qoB?~5aspYvs$p}h@3q6k@L{OOMVYkLTz%>IN{gN}vRW+EyJUdh- zA+%YVVp#@=CoKC)Ot5GoBc;Q@O@^O8v`DP9&GFA%Ec?-bJ-+jrs%kxpGCH6@O$wMX zj(%OP#~wFv^O4nK4VT>emxlM>#y6wtPN}hxXD=i7&^uQp25UExEE-EBW@$PJy2j7N znwh4ttG*e@9Y}T1+~g7&DgtGX45p1HWA9kI|XY~^0mp3rVJEoCYP7+kPsa@T9FnO^$|FZ zk)BF;^G|`8!NV0-HHf5T3gv=w%i3zKfIw4yq!|(^f1d=tK2Gacue$JbVAUO&XU;py^) z6<`32n|`;;4chEovscf_yIWuNI9=#lO1IP*eYPmBn~UuUF~tqA~# z%5K@(G)Q)4@j@JE-Shxx3i$x9d^t>XS7yGQwT1*;5|VY+EFhk?&lx9bCasmhDE9pg zVY765QVcvB>l7X@6Myl>^Z^HQLj}rWcsl03^FQ(BG+K1|Y`Hl=qf#`UU|@k8Q?w;BI75jD(H}2ffD`XCIz4dY8d6 z^T178>C@D!1>AM`F%69wm^aAsC54t6%;)nCF|c28fK}9uX)7`tPxpbrk&ET;*EeWW zCPwVZN1Ox1;(1@LnvZie50h^N>q!zq-4CnfC0|mmwo?LD4Vw^8`TW0quIT5x#fs&~ zHuZ=`w!~4JT)p4dUow$f()jmBv%z-|S(wM&KvZOR9Dw3atRbQ@L;T*N89w*I71!}l zc(fGT*Z0!T+??5+--f|_i( zJ6zs!q%9HZSqRj+S{>H{Hy#e`FCSyz!yG``OZWN=lU7Jtx%gMYc`|(R&mvD(l=}UR zD(s@{wPLp|F!tJ+>8CxEmGr{Hq}z)O-8{{5)3k4Yq`4M}+{lD!&gR0Xv=*_`|7=Xl zGHD_l@b-?~cn58Ji3v0Hm`XM>HP%4HQc6jT#%(5|{#6jQk=uTKOu;l})vg1PG_SZq zq-bb|+tWXgO3f{`U*pW$Ha7N{m~hbA3W|wc5DZ&-yq?+nyQ~a&NLNy~A>zuCF&BLO z3Hg^OpuaY*Km7|-!-o_LYr}%(*J0?NIz70jnY&M4^_za4jc7v@cdF9F*H^k=Rvowj zfExcA<-pe6B{ZGJafcLs4m~@t(jzX$f;m#lj#Mc1q@Pbl#VEDN=)OQxFZ8AfK3k zfH!10YH8z>%16dA+&J#_-E=$yTy(KzT1XeI^yb;U>&C{zQ{{t~lrjeeNyjJ)R7Mq?LnbH`aoI0y|E>0B2*biki|S zH4ML5qn4Fh5rJS(8wqP*a^Q?AcC=f>DY7179C%b+D<_i-OF6#$f%BxOE~4>V0Ibk7 z&a$8E(G!Mio+`*6$JjYaBC^Hg_?Mw{g-0VFKg%z&tq*~Cr02mXn<2mKwYJJfu_o%= zW5l;!+w*DCuqyl%C=w7$1E~j<7uGcAOfUKlu3$SYT*c;Xi48#BC|Q0c8xQCBYk1>l z=b1qe4D}n7o4VFTykuqRu21%sTxRQ~UCFq=I=d#=bR(@hEIT6_+YI`>;vp*laGV1I zAJy-q&3mdRIt%z(-Y;ekdn8n z8AkN=Yd79e+ghNUVfqs3?lYnMGfoU(_CN`u0^9G)i=%JHQ3=vobR>^#D@vuSQ(@~j z;L$53N=whFVD5~tc@rgJ5brinL#?I`PA9{y2zg=fxn&|QYy zA*{0nXX*hEC9(o=8sgv2v~Af%yv2^Oo_Iu6qL&xP`f6oTrec=r5|40MsxRC8i!;EI z2cpDF;`5AN>`su;IM+SqDoW3@RD=TN4}H(^Qu)lfda0NO<`NtGuL4C8nKwe28|A38 zO!OFPAErG#PA(_eF|=ML9FMBfqZBOgzVJ>Exb zHWSFtlirSP@nv-cwmN!UqlL87(n!Z`vedrooWN;hUT9KEWKBw_UsSRxud*pC(@?A_ zEh%rVDX%W6ZEk68Hgp`jTpV0Js0_ge&|grDws%4T!t>C+cb`m{7{NUJO9}?N2=gS^I78A|ys@3@A1uUqt-uE0S3iz-%Ty)Z9`e1cVa-$jCCv!!s z3K~;NBOREd#UtaxArW-aA>)BSuF3Rx)Ov%j)kXF)2`u)G3>wck;bp}YC1^TdX*iU- zje%ZRuA#x{VJh1$X!0k>5`k8&c;W)KQ9YgjSxp)D+VcQ-Oys}(Ov7qw9{6}WVDfCL zdJF1{tsc*(7Da)NuiR60^%5+{tFJXj!4;4z^c(1(V=KCdkHcz(cx9%8Q(1O$j81eS zmjvW2r1DVfdt}c#b`)(1gwX~fwt}$T4Z7}${yqYgwHIzr!-jZ}oAP=?_^VucDUG~1 z5bVV-t}4b<(T9MfDl2Wo)>u!pibt%XHhY5e;m1N$HI;(sR9hJ|Mx~IpZxv1^+0U0s zQNlouKHNv;aI|?AK3g6^5fmBMngk&60s}KUXRf5!pjo(~?vCqYLJ*1h+yJ1kL;5VH z4gFd-pNVw-Ha8$=7!bT9aE_IsDm9&y%=VI2&#BeIzO*HRmD-)-M7W_woAblNyo)ph ztBvUz^NX1cO>9XAgN_XY?ey4UIS>L= z4s@aJX$RfsWf$|4{9A-96AUB(f2{aet7<-FwN4Lj+-WvL=IZKl%)GPhI^bb8?T2-; zLhk2YjL}7~Q(3c=o}ZMb-A8}^?d<}4sdcSMf>IUrehs?Ei=$9e-fXvg0(U#uRyc@q ztvMxpxL4>*XzyiQ4~krvOy@i58#X4mZ2hP@Ls|DMqLu}#!a+7gLfB~=3`Xv~!3-oH z&0x?^9S%2#=~)pVNsMLbA8EF9PFXyZ-Oim`vtZO1^pMr+sMSUS*%P^lZKRBJks+Ct zCA^s@)E#rGG_smIY3FBYSm^5t^6f5;mdZ93@kx^PVM673+U0T9@p}f{fVrAIUE_{3 zO#GP1p4LUKwl%S~HIa5Aa16x0_MbMP+91Q+Fg(3KWzywiv1UU7F_K3jbg3x3zZ<{K zPc9cxtZAi>(y*rL7@johiwWr(3BS`h7udQRnKf4(<(kL+(Y9t=P{!S8CbjwFB9h}l{j9XeH7|YehAIc^bUii_s+a~XbN?$i&7Z5yawn|=-7%bG10UsikV;nwvkuaTPSw4hR_ z*49o&dbWXkDLoWo;E{h}uzte>}Zc7kn%9{1Ke?8&KaEN>9J!0u~&RBS8Trp7r@E`?th7?3SJl&;nj1 zrdi;tf$cF}_kyi^ja}fnk5kalOELs0NX~b!O z5xG2>ZOmg5cB_S{rziBK4uywj5d#%(rP*Fpa;}jD4(E)T2Yno{SKIO+U46_{MxEF6 z^tMIu1AX!_g$ob&Z8ELKVaI9oDI~aga*}-;~d-eePa@`W!>Vqb0xMo-P=E3=#qQ$yqi8HUjQC&6Z`;v_x9n zbA8ikg1pH(B#Zq!R?*fZ$zllR=xCx$a-tyFK&-Fu|DmWQQ;e?Wn;izOSF!(CZdsxrAk#O;Ap6DJSKvqY@OS|b-5oNbAGqalS1iF@ z@pD-h9`$$#(49s2o%;@5Lj#DI_WNz&8rzeK)%3nnLlr{*WsG_@t~;5_!*;|$ztBH3 zp8s*{9>Z*!qT|IcUJk&vXCkfTR1_S)Iw7)s4Mu!ME;A)GZ@I<_P2SFxJ++A$Sv?f>`@IBkeJpY5SS zJxpQ(m|fRaxgBz*Xo zPP&_(%^RT2up!N6nN%elEUy~tIdZNhf+{LmIZP6R2iEG52yW#cU9l35wZZqOuvCGd zw1E>D*4k(1$rey7l1LfNaZw!<#N5#e2?4)1TFy?(DYJ0&I+2kGph~#%>pS%Ew{W?x zPfAccsHm?lmLL0eI%LOGGJ=EMy?2ZMI=UgTt8W!-?=|l497cN>04M!dffek|4QE|+ z-WrejnT@v%c;wS}{rZlWid_~&%OBR!J*MUI(;21#zc|p$Bg;P<|J@^_(Sv;$FjK7h zR_!kjF@1WP$e{tNvN4%`oiDFw7y(@c|9ZF;2S5YxJ2{&Gp+*GVzTbWf{clC(X12u^ z`VFd{_2|5+v}pWMab3s|+5Tm*ALoF4i6g1+b6;G$x}`Yd&kdBJ*X-r4Laa?gWH z=5lM!&F-sU66J}n<@S811A>i@!|Q%JGvneybJ2EXzSYU`tVYP=a#Iu_$!?RS2=M*rg z4P_P0huKATN#@Son0{VZE5bz}GcMD#e~Qw%;b|6JFh7R^{H0D$m6nc$JOI>(tau4o z(q?vCVRGx&3D{ik#YJ6aQ>orX&iq-|+R&BBarf|nv)zRW`JaG1L~NYz+AOEA_zDQz zfxh3ucf9y#AR%I30j6Kg)bBewGihR1fdNUL01^luC2xDba~Mr7|fib@fj+1FZ2t$O&1-r-WUfWvcO$sf(wbDaa0Pwl< zRWqyUAcn&ElIN}0cPBnLd#T}dG8EQfI*YF&ScWB<%&+qKuENHr5y89e`4;rr z^!wB8fxav2?U8^0Q=sbW-wd|C0=7J6jIYM!8L%rki?i{!V!XY_pO+)xR}{v>5YW#8 z{;w9fD@Drl8dR5wF`1Pj?ma@@qi%e==%$ovF0*GSn)*yVTD;eFDUrqO`m>N$oP7X< zrIHNOz-`PBqbE5H&}&eQp7v%IE%zZH-F2@mp{9vwLN!`2B{>`jL@ydVU!8W{dHy_l zvi17d-@K4CmAPDVay?ok=4!%SsX6G+yb$AL#p7yzcpb=-z0_)UY`E(!0m&G0&f;hx zxQ?q6BhWhc^n6(NvoyWZ;`O@Q4N1d@)a7%zKOER=>W)g9)Zy^heI1xe|id);jSTp7CT`@EtGGwTW{=h+ogSnq6*a zaF=6Obx2fV7t%1Xm2~H@I#Rr_tFa5%lEy7JIt*N}Jiz62Iv4KhwSjS+QK=S@C4mPi z1qRuUPpxPvHkvy*Svr|JstX9&%Q(qsxVamsYY0l(U-~AtPQpc;)uAwPX9ylmg{pDW zFM8XjHd(e-dF0j!<#uSNZ_L`Ifqj=e3R;e+p;ZI4e`NPQ>9I7t#j~0E7KrcK@ zS>LH`9&yhN8u~e%<`+}srz&oI?e&(+#k0|6IlWQy)WAN>k6BjMaz!8B!G*1!XIb%nA!A*XT9dm#Cl?)|G93jaQ)7qv(aIsZvZ6|vl@Ry z96@-Q9C_R@WRsZjF!Ab#vElDQ0Y3e{ODH+j6}jBD3fK>6=I8IohsfZ+BVmmj%LdGC zqf4Co>FbzF2(z2)Mgq*#C^X33+HYD$XKxQKJtXf=XZI9(RcuP=wp6t{+OqRG=yE7X z7?}F$xqeWPQ?XNXGf>ZW5fT|$dq4IhE_hg!g?e#&NufIbDn*Gn?K=RM%>S-Xf{=AK zX;O(823&A^z}*Srci3I%77WNuQ5(^6z>bO?BsIM)Q5VzzkBX(uK7cga zHfoJep(-p0HA_)2X$0a@?HNgMbjUBKVP#CqPZOJ_?L9-&zpvBdTzS0~Ar}yEM05`$f9%fPm=O+aN(aU8$r{y5LQnFNJ+h;C{RvnV^UpvjNlHBuZfJZpd)PS*~mX?_Q=HYC5 z=zj4zV%Pn*tMqQPmCw$Ap3emN9nD*Z$a$5ju#oVY%=1B`R=sNhW>JcS!!Tj@6D52Tt-)N*?C%P9YW?dTR)B`k#^zyd|zc}lTkrCdT4!um3~)&xv7 z4wWj@0?p9HitZED-TN}T>(a}qpY=9y8b#n$s^NM9Y*CUj9@i~B0stsm=3SduAd;)&_IQM03it!3Ew>5SlO^fXi1A)84%Nj)?`5` z=Pi6SSuaJjIA&7W$)cW94-S?ddiyeYzRTm^hJt;y&#hlQ+5(cRKCfeNuK6+VTn(R# zzlH1n0_x17;#=lhSd4n&Pk=fQnT<;dSYRubdmCUIa}ql~eU))iv<>F_I$kB7j#sZD zj<0Q&u@I~=QL#&)v|%<%In{{P*=KYre46*hY;723c? z`|e(-xxEc-eLfKUWtuJP9(7r7OSB?c2SL2)tm;lM9XE2JOS7k~du6lEY(~!?+-B*F zG2zk;KPEGOd{3QzGY)+yV+*a>Ny%p{B=0O_;VFMT3j8~(H(~Pt$U6bZ`{BC) zP8{;%(ScP|M2S{Cg#Zy0V3S_-HNU?N2^3nONX7iz)9lPmAEBQFCLbydXk|w5?1bQ1 zg>kJVa7EHEbzru!=O9 z8Ck+^qL@_)S2fZ!xxQ}G?T1;0Rxn|Tr4j6a)3XJ}Et@h(=v7iC`4h!(M=k3;T&ujJ zsj*}(>M?PxzQEhf4Wv?s?Dwrj>#XsBSV6v2n?j4@&E+XS?MA&!r_7gyo`-*)(f>Gv zQ-&(nN$rvIY`M#uEGu*YyufnG9@owE zzAE4pIM4ZzvlQ|q2B*(A7ZMWW(2}#J6AvtGjWLYc%gLDSHZ1U~!Gh||qqCT}wx)>G zF|CZ^$!vb_Rt(sgQiDa+BRifB`>1!^SH@{|aV}`a*5VOm zQIMsu8uF)C+U>neQ%iZwb_0q1&2<9-V#o%gh0?GC#3;kZkifl~szaJ$Y>*-FLk1rY z`aQ3$A($Pwu;qw3+JUolV&)0N4OG(_%0A*1RQ~AE_7CD2*!ePO3Ptc0b3ThU{N^mV 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 z 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≧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 literal 0 HcmV?d00001 diff --git a/keyboards/stm32_f103_onekey/bootloader_defs.h b/keyboards/stm32_f103_onekey/bootloader_defs.h new file mode 100644 index 00000000..0f45203c --- /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_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 00000000..dfb1f9df --- /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 00000000..19b14fe6 --- /dev/null +++ b/keyboards/stm32_f103_onekey/config.h @@ -0,0 +1,75 @@ +/* +Copyright 2015 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +/* 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 00000000..15501dfa --- /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 00000000..1a450d63 --- /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 00000000..c3b0f084 --- /dev/null +++ b/keyboards/stm32_f103_onekey/keymaps/default/keymap.c @@ -0,0 +1,25 @@ +/* +Copyright 2012,2013 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#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 00000000..00613328 --- /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 00000000..f5c55f7d --- /dev/null +++ b/keyboards/stm32_f103_onekey/led.c @@ -0,0 +1,43 @@ +/* +Copyright 2012 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "hal.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ + if (usb_led & (1< + +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 . +*/ + +#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</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 /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /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 /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 /os/hal/boards/ +# or /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 00000000..dbf12c36 --- /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 +# /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 /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /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 /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 /os/hal/boards/ +# or /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 00000000..41bfa41a --- /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 +# /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 /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /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 /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 /os/hal/boards/ +# or /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 00000000..cb36996c --- /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 00000000..19b14fe6 --- /dev/null +++ b/keyboards/teensy_lc_onekey/config.h @@ -0,0 +1,75 @@ +/* +Copyright 2015 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + + +/* 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 00000000..b1d2cd55 --- /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 00000000..16886a01 --- /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-`) 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-` 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 00000000..a109b496 --- /dev/null +++ b/keyboards/teensy_lc_onekey/keymaps/default/keymap.c @@ -0,0 +1,32 @@ +/* +Copyright 2012,2013 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#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 00000000..fb141f88 --- /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 + * + * 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 00000000..dfa60c10 --- /dev/null +++ b/keyboards/teensy_lc_onekey/led.c @@ -0,0 +1,32 @@ +/* +Copyright 2012 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "hal.h" + +#include "led.h" + + +void led_set(uint8_t usb_led) { + if (usb_led & (1< + +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 . +*/ + +#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<. #include #include #include "action.h" +#if defined(__AVR__) #include +#endif #include "keycode.h" #include "action_macro.h" #include "report.h" @@ -30,12 +32,15 @@ along with this program. If not, see . #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 similarity index 94% rename from quantum/keymap.c rename to quantum/keymap_common.c index 74fd518c..76872ac5 100644 --- a/quantum/keymap.c +++ b/quantum/keymap_common.c @@ -19,7 +19,10 @@ along with this program. If not, see . #include "report.h" #include "keycode.h" #include "action_layer.h" +#if defined(__AVR__) #include +#include +#endif #include "action.h" #include "action_macro.h" #include "debug.h" @@ -32,7 +35,6 @@ along with this program. If not, see . extern keymap_config_t keymap_config; -#include #include /* 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 f5744658..a38c13f1 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -17,7 +17,9 @@ along with this program. If not, see . */ #include #include +#if defined(__AVR__) #include +#endif #include "wait.h" #include "print.h" #include "debug.h" diff --git a/quantum/quantum.c b/quantum/quantum.c index 270b976e..d59bd5a3 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 9b5d310b..3a0b7420 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -1,7 +1,12 @@ #ifndef QUANTUM_H #define QUANTUM_H +#if defined(__AVR__) #include +#include +#include +#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 -#include -#include #include "bootloader.h" #include "timer.h" #include "config_common.h" -#include #include "led.h" #include "action_util.h" #include diff --git a/readme.md b/readme.md index 6fa67c04..c24d951d 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 (@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 00000000..72be5e6d --- /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 00000000..0abb933a --- /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 f2a22e4f..d71fba9b 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 ff78d7f2..e16e11be 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 similarity index 100% rename from tmk_core/common/sleep_led.c rename to tmk_core/common/avr/sleep_led.c diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c index 30e8a0f2..90275a18 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c @@ -1,6 +1,6 @@ #include #include -#include +#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 00000000..8a533ab6 --- /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 00000000..5ff8ee86 --- /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 : + 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 + 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 : + 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 + 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 00000000..72e3d4f8 --- /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 00000000..678a100c --- /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 + +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 00000000..4c35cfcb --- /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<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<. */ #include #include -#include +#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 similarity index 98% rename from tmk_core/common/avr/eeconfig.c rename to tmk_core/common/eeconfig.c index 656938fb..140d2b85 100644 --- a/tmk_core/common/avr/eeconfig.c +++ b/tmk_core/common/eeconfig.c @@ -1,6 +1,6 @@ #include #include -#include +#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 00000000..2cc2ccee --- /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 +#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 f21d1346..194e4cc0 100644 --- a/tmk_core/common/magic.c +++ b/tmk_core/common/magic.c @@ -1,6 +1,8 @@ #include #include +#if defined(__AVR__) #include +#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 ca94e1e5..00489557 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 4f3dde65..0368bcd4 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 199b1bed..5b276562 100644 --- a/tmk_core/common/progmem.h +++ b/tmk_core/common/progmem.h @@ -5,8 +5,8 @@ # include #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 f6c0a315..0c799eca 100644 --- a/tmk_core/common/report.h +++ b/tmk_core/common/report.h @@ -84,6 +84,11 @@ along with this program. If not, see . # 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 40d00b0c..82727be0 100644 --- a/tmk_core/common/wait.h +++ b/tmk_core/common/wait.h @@ -9,9 +9,13 @@ extern "C" { # include # 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 00000000..3f4e0a71 --- /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 00000000..63e6641f --- /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 `/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 00000000..54bb6a8f --- /dev/null +++ b/tmk_core/protocol/chibios/main.c @@ -0,0 +1,147 @@ +/* + * (c) 2015 flabberast + * + * 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 00000000..e2c9d9bf --- /dev/null +++ b/tmk_core/protocol/chibios/usb_main.c @@ -0,0 +1,1372 @@ +/* + * (c) 2015 flabberast + * + * 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 = + * 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 + * + * 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 6b6714a6..f460d0ed 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: +Updates +------- +#### 2016/02/10 +flabbergast's Chibios protocol was merged from . 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 f8f77e89..96eba24d 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 00000000..88bbafe3 --- /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 00000000..d8865762 --- /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__) */ + + /** @} */ From c30aba0bce989d29458bd3b56090400cb0a91d03 Mon Sep 17 00:00:00 2001 From: fredizzimo Date: Sat, 2 Jul 2016 00:22:09 +0300 Subject: [PATCH 02/10] Add ChibiOS packages to the avr_setup script (#468) * Add ChibiOS packages to the avr_setup script * Add git as a dependency * Rename avr_setup.sh -> install_dependencies.sh Also fix the Vagrant welcome message to reflect the new directory structure. --- Vagrantfile | 4 +-- .../{avr_setup.sh => install_dependencies.sh} | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) rename util/{avr_setup.sh => install_dependencies.sh} (73%) diff --git a/Vagrantfile b/Vagrantfile index 42b43775..8cadeadd 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -78,7 +78,7 @@ Vagrant.configure(2) do |config| # add a # before ,args: and run 'vagrant up' to get a working # non-updated box and then attempt to troubleshoot or open a Github issue - config.vm.provision "shell", run: "always", path: "./util/avr_setup.sh", args: "-update" + config.vm.provision "shell", run: "always", path: "./util/install_dependencies.sh", args: "-update" config.vm.post_up_message = <<-EOT Log into the VM using 'vagrant ssh' on OSX or from Git Bash (Win) @@ -91,7 +91,7 @@ Vagrant.configure(2) do |config| Or you can copy and paste the example line below. - cd /vagrant; cd keyboard; cd ergodox_ez; make clean; make + cd /vagrant; cd keyboards; cd ergodox_ez; make clean; make EOT diff --git a/util/avr_setup.sh b/util/install_dependencies.sh similarity index 73% rename from util/avr_setup.sh rename to util/install_dependencies.sh index 916d0378..24564a2a 100644 --- a/util/avr_setup.sh +++ b/util/install_dependencies.sh @@ -16,7 +16,11 @@ if [[ -n "$(type -P pacman )" ]]; then avr-gcc \ avr-binutils \ avr-libc \ - dfu-util + dfu-util \ + arm-none-eabi-gcc \ + arm-none-eabi-binutils \ + arm-none-eabi-newlib \ + git elif [[ -n "$(type -P apt-get)" ]]; then # Debian and derivatives @@ -39,7 +43,11 @@ elif [[ -n "$(type -P apt-get)" ]]; then binutils-avr \ avr-libc \ dfu-programmer \ - dfu-util + dfu-util \ + gcc-arm-none-eabi \ + binutils-arm-none-eabi \ + libnewlib-arm-none-eabi \ + git elif [[ -n "$(type -P yum)" ]]; then # Fedora, CentOS or RHEL and derivatives @@ -57,7 +65,14 @@ elif [[ -n "$(type -P yum)" ]]; then avr-gcc \ avr-libc \ dfu-programmer \ - dfu-util + dfu-util \ + gcc-arm-none-eabi \ + binutils-arm-none-eabi \ + libnewlib-arm-none-eabi \ + git + # The listed eabi pacackes do unfortunately not exist for CentOS, + # But at least in Fedora they do, so try to install them anyway + # TODO: Build them from sources, if the installation fails elif [[ -n "$(type -P zypper)" ]]; then # openSUSE @@ -69,6 +84,9 @@ elif [[ -n "$(type -P zypper)" ]]; then kernel-devel \ patch \ wget \ - dfu-programmer + dfu-programmer \ + git + # TODO: The avr and eabi tools are not available as default packages, so we need + # another way to install them fi From 1b319151aa8f4efb32a9146022d9de8c40eb5540 Mon Sep 17 00:00:00 2001 From: fredizzimo Date: Sat, 2 Jul 2016 04:57:59 +0300 Subject: [PATCH 03/10] Add warning when submodules are not updated (#469) * Add warning when submodules are not updated * Sh compatible syntax for dirty submodule check --- tmk_core/rules.mk | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tmk_core/rules.mk b/tmk_core/rules.mk index 96eba24d..7d3d8f9a 100644 --- a/tmk_core/rules.mk +++ b/tmk_core/rules.mk @@ -16,7 +16,6 @@ # - # Output format. (can be srec, ihex, binary) FORMAT = ihex @@ -243,6 +242,12 @@ MSG_COMPILING_CPP = Compiling: MSG_ASSEMBLING = Assembling: MSG_CLEANING = Cleaning project: MSG_CREATING_LIBRARY = Creating library: +MSG_SUBMODULE_DIRTY = $(WARN_COLOR)WARNING:$(NO_COLOR)\n \ + Some git sub-modules are out of date or modified, please consider runnning:$(BOLD)\n\ + git submodule sync --recursive\n\ + git submodule update --init --recursive$(NO_COLOR)\n\n\ + You can ignore this warning if you are not compiling any ChibiOS keyboards,\n\ + or if you have modified the ChibiOS libraries yourself. \n\n # Define all object files. @@ -304,6 +309,13 @@ lib: $(LIBNAME) # the following magic strings to be generated by the compile job. begin: @$(SECHO) $(MSG_BEGIN) + git submodule status --recursive | \ + while IFS= read -r x; do \ + case "$$x" in \ + \ *) ;; \ + *) printf "$(MSG_SUBMODULE_DIRTY)";break;; \ + esac \ + done end: @$(SECHO) $(MSG_END) From 27354ae8776d55b361c02be43577184d6af7ac21 Mon Sep 17 00:00:00 2001 From: Seth Chandler Date: Fri, 1 Jul 2016 23:50:51 -0400 Subject: [PATCH 04/10] add HHKB support to satan (#470) * add HHKB support * fix indentation --- keyboards/satan/keymaps/sethbc/keymap.c | 149 ++++++++++++++++++++++++ keyboards/satan/satan.h | 40 ++++++- 2 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 keyboards/satan/keymaps/sethbc/keymap.c diff --git a/keyboards/satan/keymaps/sethbc/keymap.c b/keyboards/satan/keymaps/sethbc/keymap.c new file mode 100644 index 00000000..0ea4a7ae --- /dev/null +++ b/keyboards/satan/keymaps/sethbc/keymap.c @@ -0,0 +1,149 @@ +#include "satan.h" + +#ifdef RGBLIGHT_ENABLE +#include "rgblight.h" +#endif + +// Used for SHIFT_ESC +#define MODS_CTRL_MASK (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)) + +// Each layer gets a name for readability, which is then used in the keymap matrix below. +// The underscores don't mean anything - you can have a layer called STUFF or any other name. +// Layer names don't all need to be of the same length, obviously, and you can also skip them +// entirely and just use numbers. +#define _BL 0 +#define _FL 1 + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Keymap _BL: (Base Layer) Default Layer + * ,-----------------------------------------------------------. + * |Esc~| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| \ | ~ | + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]|bksp | + * |-----------------------------------------------------------| + * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift| fn | + * |-----------------------------------------------------------| + * |Ctrl|Gui |Alt | Space |Alt |Gui |FN |Ctrl | + * `-----------------------------------------------------------' + */ +[_BL] = KEYMAP_HHKB( + F(0), KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSLS, KC_GRV, \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSPC, \ + KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, \ + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, MO(_FL), \ + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, KC_MENU, KC_RCTL), + +[_FL] = KEYMAP_HHKB( + #ifdef RGBLIGHT_ENABLE + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, RESET, \ + KC_CAPS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \ + KC_TRNS, KC_VOLD, KC_VOLU, KC_MUTE, KC_TRNS, KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), + #else + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, RESET, \ + KC_CAPS, KC_TRNS, F(1), F(2), F(3), KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_SLCK, KC_PAUS, KC_UP, KC_TRNS, KC_BSPC, \ + KC_TRNS, KC_VOLD, F(4), F(5), F(6), KC_TRNS, KC_PAST, KC_PSLS, KC_HOME, KC_PGUP, KC_LEFT, KC_RGHT, KC_PENT, \ + KC_TRNS, F(7), F(8), KC_TRNS, KC_TRNS, KC_TRNS, KC_PPLS, KC_PMNS, KC_END, KC_PGDN, KC_DOWN, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS), + #endif +}; + +enum function_id { + SHIFT_ESC, + #ifdef RGBLIGHT_ENABLE + RGBLED_TOGGLE, + RGBLED_STEP_MODE, + RGBLED_INCREASE_HUE, + RGBLED_DECREASE_HUE, + RGBLED_INCREASE_SAT, + RGBLED_DECREASE_SAT, + RGBLED_INCREASE_VAL, + RGBLED_DECREASE_VAL + #endif +}; + +const uint16_t PROGMEM fn_actions[] = { + [0] = ACTION_FUNCTION(SHIFT_ESC), + #ifdef RGBLIGHT_ENABLE + [1] = ACTION_FUNCTION(RGBLED_TOGGLE), + [2] = ACTION_FUNCTION(RGBLED_STEP_MODE), + [3] = ACTION_FUNCTION(RGBLED_INCREASE_HUE), + [4] = ACTION_FUNCTION(RGBLED_DECREASE_HUE), + [5] = ACTION_FUNCTION(RGBLED_INCREASE_SAT), + [6] = ACTION_FUNCTION(RGBLED_DECREASE_SAT), + [7] = ACTION_FUNCTION(RGBLED_INCREASE_VAL), + [8] = ACTION_FUNCTION(RGBLED_DECREASE_VAL), + #endif +}; + +void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) { + static uint8_t shift_esc_shift_mask; + switch (id) { + case SHIFT_ESC: + shift_esc_shift_mask = get_mods()&MODS_CTRL_MASK; + if (record->event.pressed) { + if (shift_esc_shift_mask) { + add_key(KC_GRV); + send_keyboard_report(); + } else { + add_key(KC_ESC); + send_keyboard_report(); + } + } else { + if (shift_esc_shift_mask) { + del_key(KC_GRV); + send_keyboard_report(); + } else { + del_key(KC_ESC); + send_keyboard_report(); + } + } + break; + //led operations + #ifdef RGBLIGHT_ENABLE + case RGBLED_TOGGLE: + if (record->event.pressed) { + rgblight_toggle(); + } + break; + case RGBLED_INCREASE_HUE: + if (record->event.pressed) { + rgblight_increase_hue(); + } + break; + case RGBLED_DECREASE_HUE: + if (record->event.pressed) { + rgblight_decrease_hue(); + } + break; + case RGBLED_INCREASE_SAT: + if (record->event.pressed) { + rgblight_increase_sat(); + } + break; + case RGBLED_DECREASE_SAT: + if (record->event.pressed) { + rgblight_decrease_sat(); + } + break; + case RGBLED_INCREASE_VAL: + if (record->event.pressed) { + rgblight_increase_val(); + } + break; + case RGBLED_DECREASE_VAL: + if (record->event.pressed) { + rgblight_decrease_val(); + } + break; + case RGBLED_STEP_MODE: + if (record->event.pressed) { + rgblight_step(); + } + break; + #endif + } +} diff --git a/keyboards/satan/satan.h b/keyboards/satan/satan.h index 67a48515..fa171191 100644 --- a/keyboards/satan/satan.h +++ b/keyboards/satan/satan.h @@ -26,13 +26,43 @@ k40, k41, k42, k45, k4a, k4b, k4c, k4d \ ) \ { \ - {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \ - {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \ - {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2d}, \ - {k30, KC_NO, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, KC_NO, k3d}, \ - {k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, KC_NO, k4a, k4b, k4c, k4d} \ + {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \ + {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \ + {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2d}, \ + {k30, KC_NO, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, KC_NO, k3d}, \ + {k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, KC_NO, k4a, k4b, k4c, k4d} \ } +/* Satan HHKB matrix layout + * ,------------------------------------------------------------. + * | 00 |01| 02| 03| 04| 05| 06| 07| 08| 09| 0a| 0b| 0c| 0d| 49 | + * |------------------------------------------------------------| + * | 10 | 11| 12| 13| 14| 15| 16| 17| 18| 19| 1a| 1b| 1c| 1d | + * |------------------------------------------------------------| + * | 20 | 21| 22| 23| 24| 25| 26| 27| 28| 29| 2a| 2b| 2d | + * |------------------------------------------------------------| + * | 30 | 32| 33| 34| 35| 36| 37| 38| 39| 3a| 3b| 3d | 3c | + * |------------------------------------------------------------| + * | 40 | 41 | 42 | 45 | 4a | 4b | 4c | 4d | + * `------------------------------------------------------------' + */ + +#define KEYMAP_HHKB( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k49, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2d, \ + k30, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3d, k3c, \ + k40, k41, k42, k45, k4a, k4b, k4c, k4d \ +) \ +{ \ + {k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d}, \ + {k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d}, \ + {k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2d}, \ + {k30, KC_NO, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3d}, \ + {k40, k41, k42, KC_NO, KC_NO, k45, KC_NO, KC_NO, KC_NO, k49, k4a, k4b, k4c, k4d} \ +} + + void matrix_init_user(void); void matrix_scan_user(void); From 54209dc672f0c67cf21fcd7dc376c3bbae0db9ae Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 3 Jul 2016 13:44:24 +1200 Subject: [PATCH 05/10] Add my keymap to KC60 --- keyboards/kc60/keymaps/wigguno/Makefile | 24 +++++++++ keyboards/kc60/keymaps/wigguno/keymap.c | 62 ++++++++++++++++++++++++ keyboards/kc60/keymaps/wigguno/readme.md | 14 ++++++ 3 files changed, 100 insertions(+) create mode 100644 keyboards/kc60/keymaps/wigguno/Makefile create mode 100644 keyboards/kc60/keymaps/wigguno/keymap.c create mode 100644 keyboards/kc60/keymaps/wigguno/readme.md diff --git a/keyboards/kc60/keymaps/wigguno/Makefile b/keyboards/kc60/keymaps/wigguno/Makefile new file mode 100644 index 00000000..0d7d918d --- /dev/null +++ b/keyboards/kc60/keymaps/wigguno/Makefile @@ -0,0 +1,24 @@ + + +# Build Options +# change yes to no to disable +# +BOOTMAGIC_ENABLE ?= yes # Virtual DIP switch configuration(+1000) +MOUSEKEY_ENABLE ?= no # Mouse keys(+4700) +EXTRAKEY_ENABLE ?= yes # Audio control and System control(+450) +CONSOLE_ENABLE ?= no # Console for debug(+400) +COMMAND_ENABLE ?= no # Commands for debug and configuration +KEYBOARD_LOCK_ENABLE ?= yes # Allow locking of keyboard via magic key +# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE +SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend +# if this doesn't work, see here: https://github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work +NKRO_ENABLE ?= yes # USB Nkey Rollover +BACKLIGHT_ENABLE ?= yes # Enable keyboard backlight functionality +MIDI_ENABLE ?= no # MIDI controls +UNICODE_ENABLE ?= no # Unicode +BLUETOOTH_ENABLE ?= no # Enable Bluetooth with the Adafruit EZ-Key HID +AUDIO_ENABLE ?= no # Audio output on port C6 + +ifndef QUANTUM_DIR + include ../../../../Makefile +endif diff --git a/keyboards/kc60/keymaps/wigguno/keymap.c b/keyboards/kc60/keymaps/wigguno/keymap.c new file mode 100644 index 00000000..50b1d0f9 --- /dev/null +++ b/keyboards/kc60/keymaps/wigguno/keymap.c @@ -0,0 +1,62 @@ +// This keymap was designed to close to the default kc60 layout, with some useful changes, such as adding media keys. +// It also moves the reset key off the base layer, as in the default kc60 layout for this firmware. +// I have swapped FN and RGUI as my rainbow keyset has them in the opposite order. + +#include "kc60.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + + /* Basic QWERTY + * ,-----------------------------------------------------------. + * |Esc | 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backsp | + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \ | + * |-----------------------------------------------------------| + * |CAPS | A| S| D| F| G| H| J| K| L| ;| '|Return | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift | + * |-----------------------------------------------------------| + * |Ctrl|Gui |Alt | Space |Alt |FN |Gui |Ctrl | + * `-----------------------------------------------------------' + */ + [0] = KEYMAP( + KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, \ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, \ + KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_NO, KC_ENT, \ + KC_LSFT, KC_NO, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_NO, KC_RSFT, \ + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(1), KC_RGUI, KC_RCTL \ + ), + + /* + * ,-----------------------------------------------------------. + * | ` |F1| F2| F3| F4| F5| F6| F7| F8| F9|F10|F11|F12| Del | + * |-----------------------------------------------------------| + * | | | Up| | | | | | | | PS| | | | + * |-----------------------------------------------------------| + * | |Lft|Dwn|Rgt| |BL-|BL+| | | | | | | + * |-----------------------------------------------------------| + * | |Prv| PP|Nxt| | | | |Hom|End| | | + * |-----------------------------------------------------------| + * | Rst| | | BL | | | | | + * `-----------------------------------------------------------' + * PS = Print Screen + * PP = Play/Pause + */ + [1] = KEYMAP( /* Function Layer */ + KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DELETE, \ + KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_TRNS, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, BL_DEC, BL_INC, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, \ + KC_TRNS, KC_TRNS, KC_MPRV, KC_MPLY, KC_MNXT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_HOME, KC_END, KC_TRNS, KC_TRNS, KC_TRNS, \ + RESET, KC_TRNS, KC_TRNS, BL_TOGG, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS \ + ), +}; + +const uint16_t PROGMEM fn_actions[] = { + +}; + +const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt) +{ + // MACRODOWN only works in this function + return MACRO_NONE; +}; diff --git a/keyboards/kc60/keymaps/wigguno/readme.md b/keyboards/kc60/keymaps/wigguno/readme.md new file mode 100644 index 00000000..55a9f60c --- /dev/null +++ b/keyboards/kc60/keymaps/wigguno/readme.md @@ -0,0 +1,14 @@ +Wigguno's KC60 Layout +====================== + +## Quantum MK Firmware +For the full Quantum feature list, see [the parent readme.md](/readme.md). + +## Changes from default QMK layout +The default QMK layout for KC60 does not have a function layer. It also has the bootloader-mode reset key bound. This keymap fixes both of these by adding a sensible function layer (including moving the reset key onto it, far away from the FN key). + +### Changes from the default KC60 layout +The default KC60 layout is good, but it was missing media keys. I've added previous, play/pause and next. I've also removed some of the keys from the function layer I didn't use. + +### Build +To enable NKRO you must be in the keymaps/wigguno directory when running make. From f4febd2cf7eb76ba2a76be1dfa48b7b5f4fd37ea Mon Sep 17 00:00:00 2001 From: Richard Date: Sun, 3 Jul 2016 13:49:10 +1200 Subject: [PATCH 06/10] Fix other KC60 Keymap Makefiles so they compile properly --- keyboards/kc60/keymaps/stanleylai/Makefile | 2 +- keyboards/kc60/keymaps/ws2812/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/keyboards/kc60/keymaps/stanleylai/Makefile b/keyboards/kc60/keymaps/stanleylai/Makefile index f7e4e2fe..b8b2beda 100644 --- a/keyboards/kc60/keymaps/stanleylai/Makefile +++ b/keyboards/kc60/keymaps/stanleylai/Makefile @@ -21,5 +21,5 @@ SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend NKRO_ENABLE ?= yes # USB Nkey Rollover ifndef QUANTUM_DIR - include ../../Makefile + include ../../../../Makefile endif diff --git a/keyboards/kc60/keymaps/ws2812/Makefile b/keyboards/kc60/keymaps/ws2812/Makefile index d97e4d9f..891c4441 100644 --- a/keyboards/kc60/keymaps/ws2812/Makefile +++ b/keyboards/kc60/keymaps/ws2812/Makefile @@ -21,5 +21,5 @@ SLEEP_LED_ENABLE ?= no # Breathing sleep LED during USB suspend NKRO_ENABLE ?= no # USB Nkey Rollover ifndef QUANTUM_DIR - include ../../Makefile + include ../../../../Makefile endif From 8e88d55bfd7c88cb15845e0c6415e4e892532861 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 4 Jul 2016 11:45:58 -0400 Subject: [PATCH 07/10] reverts #343 for the most part (#474) --- quantum/matrix.c | 292 +++++++++++++++++++--------------- tmk_core/common/avr/suspend.c | 6 +- tmk_core/common/bootmagic.c | 16 +- tmk_core/common/keyboard.c | 107 +++++++------ tmk_core/common/matrix.h | 57 +++---- 5 files changed, 261 insertions(+), 217 deletions(-) diff --git a/quantum/matrix.c b/quantum/matrix.c index a38c13f1..09491702 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -26,32 +26,46 @@ along with this program. If not, see . #include "util.h" #include "matrix.h" -#ifdef MATRIX_HAS_GHOST -# error "The universal matrix.c file cannot be used for this keyboard." -#endif +/* Set 0 if debouncing isn't needed */ +/* + * This constant define not debouncing time in msecs, but amount of matrix + * scan loops which should be made to get stable debounced results. + * + * On Ergodox matrix scan rate is relatively low, because of slow I2C. + * Now it's only 317 scans/second, or about 3.15 msec/scan. + * According to Cherry specs, debouncing time is 5 msec. + * + * And so, there is no sense to have DEBOUNCE higher than 2. + */ #ifndef DEBOUNCING_DELAY # define DEBOUNCING_DELAY 5 #endif +static uint8_t debouncing = DEBOUNCING_DELAY; static const uint8_t row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; static const uint8_t col_pins[MATRIX_COLS] = MATRIX_COL_PINS; -/* matrix state */ -#if DIODE_DIRECTION == COL2ROW + +/* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; -#else -static matrix_col_t matrix[MATRIX_COLS]; +static matrix_row_t matrix_debouncing[MATRIX_ROWS]; + +#if DIODE_DIRECTION == ROW2COL + static matrix_row_t matrix_reversed[MATRIX_COLS]; + static matrix_row_t matrix_reversed_debouncing[MATRIX_COLS]; #endif -static int8_t debouncing_delay = -1; -#if DIODE_DIRECTION == COL2ROW -static void toggle_row(uint8_t row); -static matrix_row_t read_cols(void); +#if MATRIX_COLS > 16 + #define SHIFTER 1UL #else -static void toggle_col(uint8_t col); -static matrix_col_t read_rows(void); + #define SHIFTER 1 #endif +static matrix_row_t read_cols(void); +static void init_cols(void); +static void unselect_rows(void); +static void select_row(uint8_t row); + __attribute__ ((weak)) void matrix_init_quantum(void) { matrix_init_kb(); @@ -80,10 +94,12 @@ __attribute__ ((weak)) void matrix_scan_user(void) { } +inline uint8_t matrix_rows(void) { return MATRIX_ROWS; } +inline uint8_t matrix_cols(void) { return MATRIX_COLS; } @@ -113,161 +129,179 @@ uint8_t matrix_cols(void) { // } void matrix_init(void) { - /* frees PORTF by setting the JTD bit twice within four cycles */ + // To use PORTF disable JTAG with writing JTD bit twice within four cycles. #ifdef __AVR_ATmega32U4__ MCUCR |= _BV(JTD); MCUCR |= _BV(JTD); #endif - /* initializes the I/O pins */ -#if DIODE_DIRECTION == COL2ROW - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - /* DDRxn */ - _SFR_IO8((row_pins[r] >> 4) + 1) |= _BV(row_pins[r] & 0xF); - toggle_row(r); - } - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - /* PORTxn */ - _SFR_IO8((col_pins[c] >> 4) + 2) |= _BV(col_pins[c] & 0xF); - } -#else - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - /* DDRxn */ - _SFR_IO8((col_pins[c] >> 4) + 1) |= _BV(col_pins[c] & 0xF); - toggle_col(c); - } - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - /* PORTxn */ - _SFR_IO8((row_pins[r] >> 4) + 2) |= _BV(row_pins[r] & 0xF); + + // 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; } -#endif + matrix_init_quantum(); } +uint8_t matrix_scan(void) +{ + #if DIODE_DIRECTION == COL2ROW -uint8_t matrix_scan(void) { - static matrix_row_t debouncing_matrix[MATRIX_ROWS]; - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - toggle_row(r); - matrix_row_t state = read_cols(); - if (debouncing_matrix[r] != state) { - debouncing_matrix[r] = state; - debouncing_delay = DEBOUNCING_DELAY; - } - toggle_row(r); - } - if (debouncing_delay >= 0) { - dprintf("Debouncing delay remaining: %X\n", debouncing_delay); - --debouncing_delay; - if (debouncing_delay >= 0) { - wait_ms(1); - } - else { - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - matrix[r] = debouncing_matrix[r]; + 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 = DEBOUNCING_DELAY; } + unselect_rows(); } - matrix_scan_quantum(); - return 1; -} - -static void toggle_row(uint8_t row) { - /* PINxn */ - _SFR_IO8((row_pins[row] >> 4)) = _BV(row_pins[row] & 0xF); -} -static matrix_row_t read_cols(void) { - matrix_row_t state = 0; - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - /* PINxn */ - if (!(_SFR_IO8((col_pins[c] >> 4)) & _BV(col_pins[c] & 0xF))) { - state |= (matrix_row_t)1 << c; + if (debouncing) { + if (--debouncing) { + wait_us(1); + } else { + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + matrix[i] = matrix_debouncing[i]; + } } } - return state; -} - -matrix_row_t matrix_get_row(uint8_t row) { - return matrix[row]; -} - #else -uint8_t matrix_scan(void) { - static matrix_col_t debouncing_matrix[MATRIX_COLS]; - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - toggle_col(c); - matrix_col_t state = read_rows(); - if (debouncing_matrix[c] != state) { - debouncing_matrix[c] = state; - debouncing_delay = DEBOUNCING_DELAY; + for (uint8_t i = 0; i < MATRIX_COLS; i++) { + select_row(i); + wait_us(30); // without this wait read unstable value. + matrix_row_t rows = read_cols(); + if (matrix_reversed_debouncing[i] != rows) { + matrix_reversed_debouncing[i] = rows; + if (debouncing) { + debug("bounce!: "); debug_hex(debouncing); debug("\n"); + } + debouncing = DEBOUNCING_DELAY; } - toggle_col(c); + unselect_rows(); } - if (debouncing_delay >= 0) { - dprintf("Debouncing delay remaining: %X\n", debouncing_delay); - --debouncing_delay; - if (debouncing_delay >= 0) { - wait_ms(1); - } - else { - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - matrix[c] = debouncing_matrix[c]; + + if (debouncing) { + if (--debouncing) { + wait_us(1); + } else { + for (uint8_t i = 0; i < MATRIX_COLS; i++) { + matrix_reversed[i] = matrix_reversed_debouncing[i]; } } } + for (uint8_t y = 0; y < MATRIX_ROWS; y++) { + matrix_row_t row = 0; + for (uint8_t x = 0; x < MATRIX_COLS; x++) { + row |= ((matrix_reversed[x] & (1<> y) << x; + } + matrix[y] = row; + } +#endif + matrix_scan_quantum(); + return 1; } -static void toggle_col(uint8_t col) { - /* PINxn */ - _SFR_IO8((col_pins[col] >> 4)) = _BV(col_pins[col] & 0xF); +bool matrix_is_modified(void) +{ + if (debouncing) return false; + return true; } -static matrix_col_t read_rows(void) { - matrix_col_t state = 0; - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - /* PINxn */ - if (!(_SFR_IO8((row_pins[r] >> 4)) & _BV(row_pins[r] & 0xF))) { - state |= (matrix_col_t)1 << r; - } +inline +bool matrix_is_on(uint8_t row, uint8_t col) +{ + return (matrix[row] & ((matrix_row_t)1= 0; --c) { - if (matrix[c] & mask) { - state |= (matrix_row_t)1 << c; - } +uint8_t matrix_key_count(void) +{ + uint8_t count = 0; + for (uint8_t i = 0; i < MATRIX_ROWS; i++) { + count += bitpop16(matrix[i]); } - return state; + return count; } +static void init_cols(void) +{ +#if DIODE_DIRECTION == COL2ROW + for(int x = 0; x < MATRIX_COLS; x++) { + int pin = col_pins[x]; +#else + for(int x = 0; x < MATRIX_ROWS; x++) { + int pin = row_pins[x]; #endif - -bool matrix_is_modified(void) { - if (debouncing_delay >= 0) return false; - return true; + _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); + _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); + } } -bool matrix_is_on(uint8_t row, uint8_t col) { - return matrix_get_row(row) & (matrix_row_t)1 << col; -} +static matrix_row_t read_cols(void) +{ + matrix_row_t result = 0; -void matrix_print(void) { - dprintln("Human-readable matrix state:"); - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - dprintf("State of row %X: %016b\n", r, bitrev16(matrix_get_row(r))); +#if DIODE_DIRECTION == COL2ROW + for(int x = 0; x < MATRIX_COLS; x++) { + int pin = col_pins[x]; +#else + for(int x = 0; x < MATRIX_ROWS; x++) { + int pin = row_pins[x]; +#endif + result |= (_SFR_IO8(pin >> 4) & _BV(pin & 0xF)) ? 0 : (SHIFTER << x); } + return result; } -uint8_t matrix_key_count(void) { - uint8_t count = 0; - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - count += bitpop16(matrix_get_row(r)); +static void unselect_rows(void) +{ +#if DIODE_DIRECTION == COL2ROW + for(int x = 0; x < MATRIX_ROWS; x++) { + int pin = row_pins[x]; +#else + for(int x = 0; x < MATRIX_COLS; x++) { + int pin = col_pins[x]; +#endif + _SFR_IO8((pin >> 4) + 1) &= ~_BV(pin & 0xF); + _SFR_IO8((pin >> 4) + 2) |= _BV(pin & 0xF); } - return count; +} + +static void select_row(uint8_t row) +{ + +#if DIODE_DIRECTION == COL2ROW + int pin = row_pins[row]; +#else + int pin = col_pins[row]; +#endif + _SFR_IO8((pin >> 4) + 1) |= _BV(pin & 0xF); + _SFR_IO8((pin >> 4) + 2) &= ~_BV(pin & 0xF); } diff --git a/tmk_core/common/avr/suspend.c b/tmk_core/common/avr/suspend.c index a6f3c644..8a7272bb 100644 --- a/tmk_core/common/avr/suspend.c +++ b/tmk_core/common/avr/suspend.c @@ -114,8 +114,10 @@ bool suspend_wakeup_condition(void) matrix_power_up(); matrix_scan(); matrix_power_down(); - if (matrix_key_count()) return true; - return false; + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + if (matrix_get_row(r)) return true; + } + return false; } // run immediately after wakeup diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c index 90275a18..6730a2a4 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c @@ -106,13 +106,15 @@ void bootmagic(void) } } -static bool scan_keycode(uint8_t keycode) { - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { +static bool scan_keycode(uint8_t keycode) +{ + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { matrix_row_t matrix_row = matrix_get_row(r); - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - if (matrix_row & (matrix_row_t)1 << c) { - keypos_t key = (keypos_t){ .row = r, .col = c }; - if (keycode == keymap_key_to_keycode(0, key)) return true; + for (uint8_t c = 0; c < MATRIX_COLS; c++) { + if (matrix_row & ((matrix_row_t)1<. #endif #ifdef MATRIX_HAS_GHOST -static bool is_row_ghosting(uint8_t row){ - matrix_row_t state = matrix_get_row(row); - /* no ghosting happens when only one key in the row is pressed */ - if (!(state - 1 & state)) return false; - /* ghosting occurs when two keys in the same column are pressed */ - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - if (r != row && matrix_get_row(r) & state) return true; +static bool has_ghost_in_row(uint8_t row) +{ + matrix_row_t matrix_row = matrix_get_row(row); + // No ghost exists when less than 2 keys are down on the row + if (((matrix_row - 1) & matrix_row) == 0) + return false; + + // Ghost occurs when the row shares column line with other row + for (uint8_t i=0; i < MATRIX_ROWS; i++) { + if (i != row && (matrix_get_row(i) & matrix_row)) + return true; } return false; } - #endif __attribute__ ((weak)) @@ -100,72 +103,86 @@ void keyboard_init(void) { #endif } -/* does routine keyboard jobs */ -void keyboard_task(void) { - static uint8_t led_status; +/* + * Do keyboard routine jobs: scan mantrix, light LEDs, ... + * This is repeatedly called as fast as possible. + */ +void keyboard_task(void) +{ + static matrix_row_t matrix_prev[MATRIX_ROWS]; +#ifdef MATRIX_HAS_GHOST + static matrix_row_t matrix_ghost[MATRIX_ROWS]; +#endif + static uint8_t led_status = 0; + matrix_row_t matrix_row = 0; + matrix_row_t matrix_change = 0; + matrix_scan(); - for (int8_t r = MATRIX_ROWS - 1; r >= 0; --r) { - static matrix_row_t previous_matrix[MATRIX_ROWS]; - matrix_row_t state = matrix_get_row(r); - matrix_row_t changes = state ^ previous_matrix[r]; - if (changes) { + for (uint8_t r = 0; r < MATRIX_ROWS; r++) { + matrix_row = matrix_get_row(r); + matrix_change = matrix_row ^ matrix_prev[r]; + if (matrix_change) { #ifdef MATRIX_HAS_GHOST - static matrix_row_t deghosting_matrix[MATRIX_ROWS]; - if (is_row_ghosting(r)) { - /* debugs the deghosting mechanism */ - /* doesn't update previous_matrix until the ghosting has stopped - * in order to prevent the last key from being lost + if (has_ghost_in_row(r)) { + /* Keep track of whether ghosted status has changed for + * debugging. But don't update matrix_prev until un-ghosted, or + * the last key would be lost. */ - if (debug_matrix && deghosting_matrix[r] != state) { + if (debug_matrix && matrix_ghost[r] != matrix_row) { matrix_print(); } - deghosting_matrix[r] = state; + matrix_ghost[r] = matrix_row; continue; } - deghosting_matrix[r] = state; + matrix_ghost[r] = matrix_row; #endif if (debug_matrix) matrix_print(); - for (int8_t c = MATRIX_COLS - 1; c >= 0; --c) { - matrix_row_t mask = (matrix_row_t)1 << c; - if (changes & mask) { - keyevent_t event; - event.key = (keypos_t){ .row = r, .col = c }; - event.pressed = state & mask; - /* the time should not be 0 */ - event.time = timer_read() | 1; - action_exec(event); - /* records the processed key event */ - previous_matrix[r] ^= mask; - /* processes one key event per call */ - goto event_processed; + for (uint8_t c = 0; c < MATRIX_COLS; c++) { + if (matrix_change & ((matrix_row_t)1<. #include #include -#if MATRIX_COLS <= 8 -typedef uint8_t matrix_row_t; -#elif MATRIX_COLS <= 16 -typedef uint16_t matrix_row_t; -#elif MATRIX_COLS <= 32 -typedef uint32_t matrix_row_t; + +#if (MATRIX_COLS <= 8) +typedef uint8_t matrix_row_t; +#elif (MATRIX_COLS <= 16) +typedef uint16_t matrix_row_t; +#elif (MATRIX_COLS <= 32) +typedef uint32_t matrix_row_t; #else -# error "There are too many columns." +#error "MATRIX_COLS: invalid value" #endif -#if DIODE_DIRECTION == ROW2COL -# if MATRIX_ROWS <= 8 -typedef uint8_t matrix_col_t; -# elif MATRIX_ROWS <= 16 -typedef uint16_t matrix_col_t; -# elif MATRIX_ROWS <= 32 -typedef uint32_t matrix_col_t; -# else -# error "There are too many rows." -# endif -#endif +#define MATRIX_IS_ON(row, col) (matrix_get_row(row) && (1< Date: Mon, 4 Jul 2016 17:55:32 +0200 Subject: [PATCH 08/10] fix typos --- doc/keycode.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/keycode.txt b/doc/keycode.txt index 44d7e27c..c1134f9b 100644 --- a/doc/keycode.txt +++ b/doc/keycode.txt @@ -62,7 +62,7 @@ KC_NONUS_HASH KC_NUHS 32 Keyboard Non-US # and ~ KC_SCOLON KC_SCLN 33 Keyboard ; and : KC_QUOTE KC_QUOT 34 Keyboard ‘ and “ KC_GRAVE KC_GRV 35 Keyboard Grave Accent and Tilde -KC_COMMA KC_COMM 36 Keyboard, and < +KC_COMMA KC_COMM 36 Keyboard , and < KC_DOT 37 Keyboard . and > KC_SLASH KC_SLSH 38 Keyboard / and ? KC_CAPSLOCK KC_CAPS 39 Keyboard Caps Lock @@ -92,7 +92,7 @@ KC_LEFT 50 Keyboard LeftArrow1 KC_DOWN 51 Keyboard DownArrow1 KC_UP 52 Keyboard UpArrow1 KC_NUMLOCK KC_NLCK 53 Keypad Num Lock and Clear11 -KC_KP_SLASH KC_PSLS 54 Keypad /1 +KC_KP_SLASH KC_PSLS 54 Keypad / KC_KP_ASTERISK KC_PAST 55 Keypad * KC_KP_MINUS KC_PMNS 56 Keypad - KC_KP_PLUS KC_PPLS 57 Keypad + From eafaba6b532a2f013955599fc7aa5c599e638fd3 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 4 Jul 2016 12:01:10 -0400 Subject: [PATCH 09/10] Improves debounce --- keyboards/ergodox_ez/config.h | 10 ++-------- keyboards/ergodox_ez/matrix.c | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/keyboards/ergodox_ez/config.h b/keyboards/ergodox_ez/config.h index 6a391ffb..2bb56731 100644 --- a/keyboards/ergodox_ez/config.h +++ b/keyboards/ergodox_ez/config.h @@ -27,7 +27,7 @@ along with this program. If not, see . #define DEVICE_VER 0x0001 #define MANUFACTURER ErgoDox EZ #define PRODUCT ErgoDox EZ -#define DESCRIPTION t.m.k. keyboard firmware for Ergodox +#define DESCRIPTION QMK keyboard firmware for Ergodox EZ /* key matrix size */ #define MATRIX_ROWS 14 @@ -40,12 +40,6 @@ along with this program. If not, see . #define TAPPING_TOGGLE 1 -#define COLS (int []){ F1, F0, B0, C7, F4, F5, F6, F7, D4, D6, B4, D7 } -#define ROWS (int []){ D0, D5, B5, B6 } - -/* COL2ROW or ROW2COL */ -#define DIODE_DIRECTION COL2ROW - /* define if matrix has ghost */ //#define MATRIX_HAS_GHOST @@ -53,7 +47,7 @@ along with this program. If not, see . #define BACKLIGHT_LEVELS 3 /* Set 0 if debouncing isn't needed */ -#define DEBOUNCE 2 +#define DEBOUNCE 5 #define TAPPING_TERM 200 #define IGNORE_MOD_TAP_INTERRUPT // this makes it possible to do rolling combos (zx) with keys that convert to other keys on hold (z becomes ctrl when you hold it, and when this option isn't enabled, z rapidly followed by x actually sends Ctrl-x. That's bad.) diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c index b87fddba..1bacff2a 100644 --- a/keyboards/ergodox_ez/matrix.c +++ b/keyboards/ergodox_ez/matrix.c @@ -179,7 +179,7 @@ uint8_t matrix_scan(void) if (debouncing) { if (--debouncing) { - _delay_ms(1); + _delay_ms(2); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; From 86a7b060efb6f94115f5b1f6d9e3703aa3d6b392 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 4 Jul 2016 12:13:41 -0400 Subject: [PATCH 10/10] Adds wait to i2c (debounce) --- keyboards/ergodox_ez/matrix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keyboards/ergodox_ez/matrix.c b/keyboards/ergodox_ez/matrix.c index 1bacff2a..9c1efa1d 100644 --- a/keyboards/ergodox_ez/matrix.c +++ b/keyboards/ergodox_ez/matrix.c @@ -27,7 +27,7 @@ along with this program. If not, see . #include #include #include -#include +#include "wait.h" #include "action_layer.h" #include "print.h" #include "debug.h" @@ -166,6 +166,7 @@ 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(i); if (matrix_debouncing[i] != cols) { matrix_debouncing[i] = cols; @@ -179,7 +180,7 @@ uint8_t matrix_scan(void) if (debouncing) { if (--debouncing) { - _delay_ms(2); + wait_us(1); } else { for (uint8_t i = 0; i < MATRIX_ROWS; i++) { matrix[i] = matrix_debouncing[i]; @@ -267,7 +268,6 @@ static matrix_row_t read_cols(uint8_t row) return data; } } else { - _delay_us(30); // without this wait read unstable value. // read from teensy return (PINF&(1<<0) ? 0 : (1<<0)) |