Squashed 'tmk_core/' content from commit 05caacc
authortmk <hasu@tmk-kbd.com>
Thu, 9 Apr 2015 16:32:04 +0000 (01:32 +0900)
committertmk <hasu@tmk-kbd.com>
Thu, 9 Apr 2015 16:32:04 +0000 (01:32 +0900)
git-subtree-dir: tmk_core
git-subtree-split: 05caaccec92694bb24c8c3c3a9940b96efd4605c

533 files changed:
.gitignore [new file with mode: 0644]
.gitmodules [new file with mode: 0644]
README.md [new file with mode: 0644]
common.mk [new file with mode: 0644]
common/action.c [new file with mode: 0644]
common/action.h [new file with mode: 0644]
common/action_code.h [new file with mode: 0644]
common/action_layer.c [new file with mode: 0644]
common/action_layer.h [new file with mode: 0644]
common/action_macro.c [new file with mode: 0644]
common/action_macro.h [new file with mode: 0644]
common/action_tapping.c [new file with mode: 0644]
common/action_tapping.h [new file with mode: 0644]
common/action_util.c [new file with mode: 0644]
common/action_util.h [new file with mode: 0644]
common/avr/bootloader.c [new file with mode: 0644]
common/avr/eeconfig.c [new file with mode: 0644]
common/avr/suspend.c [new file with mode: 0644]
common/avr/suspend_avr.h [new file with mode: 0644]
common/avr/timer.c [new file with mode: 0644]
common/avr/timer_avr.h [new file with mode: 0644]
common/avr/xprintf.S [new file with mode: 0644]
common/avr/xprintf.h [new file with mode: 0644]
common/backlight.c [new file with mode: 0644]
common/backlight.h [new file with mode: 0644]
common/bootloader.h [new file with mode: 0644]
common/bootmagic.c [new file with mode: 0644]
common/bootmagic.h [new file with mode: 0644]
common/command.c [new file with mode: 0644]
common/command.h [new file with mode: 0644]
common/debug.c [new file with mode: 0644]
common/debug.h [new file with mode: 0644]
common/eeconfig.h [new file with mode: 0644]
common/host.c [new file with mode: 0644]
common/host.h [new file with mode: 0644]
common/host_driver.h [new file with mode: 0644]
common/keyboard.c [new file with mode: 0644]
common/keyboard.h [new file with mode: 0644]
common/keycode.h [new file with mode: 0644]
common/keymap.c [new file with mode: 0644]
common/keymap.h [new file with mode: 0644]
common/led.h [new file with mode: 0644]
common/matrix.h [new file with mode: 0644]
common/mbed/bootloader.c [new file with mode: 0644]
common/mbed/suspend.c [new file with mode: 0644]
common/mbed/timer.c [new file with mode: 0644]
common/mbed/xprintf.cpp [new file with mode: 0644]
common/mbed/xprintf.h [new file with mode: 0644]
common/mousekey.c [new file with mode: 0644]
common/mousekey.h [new file with mode: 0644]
common/nodebug.h [new file with mode: 0644]
common/print.c [new file with mode: 0644]
common/print.h [new file with mode: 0644]
common/progmem.h [new file with mode: 0644]
common/report.h [new file with mode: 0644]
common/sendchar.h [new file with mode: 0644]
common/sendchar_null.c [new file with mode: 0644]
common/sendchar_uart.c [new file with mode: 0644]
common/sleep_led.c [new file with mode: 0644]
common/sleep_led.h [new file with mode: 0644]
common/suspend.h [new file with mode: 0644]
common/timer.h [new file with mode: 0644]
common/uart.c [new file with mode: 0644]
common/uart.h [new file with mode: 0644]
common/util.c [new file with mode: 0644]
common/util.h [new file with mode: 0644]
common/wait.h [new file with mode: 0644]
doc/COPYING.GPLv2 [new file with mode: 0644]
doc/COPYING.GPLv3 [new file with mode: 0644]
doc/FUSE.txt [new file with mode: 0644]
doc/POWER.txt [new file with mode: 0644]
doc/USB_NKRO.txt [new file with mode: 0644]
doc/build.md [new file with mode: 0644]
doc/keycode.txt [new file with mode: 0644]
doc/keymap.md [new file with mode: 0644]
doc/other_projects.md [new file with mode: 0644]
ldscript_keymap_avr5.x [new file with mode: 0644]
protocol.mk [new file with mode: 0644]
protocol/adb.c [new file with mode: 0644]
protocol/adb.h [new file with mode: 0644]
protocol/bluefruit.mk [new file with mode: 0644]
protocol/bluefruit/bluefruit.c [new file with mode: 0644]
protocol/bluefruit/bluefruit.h [new file with mode: 0644]
protocol/bluefruit/main.c [new file with mode: 0644]
protocol/ibm4704.c [new file with mode: 0644]
protocol/ibm4704.h [new file with mode: 0644]
protocol/iwrap.mk [new file with mode: 0644]
protocol/iwrap/iWRAP4.txt [new file with mode: 0644]
protocol/iwrap/iWRAP5.txt [new file with mode: 0644]
protocol/iwrap/iwrap.c [new file with mode: 0644]
protocol/iwrap/iwrap.h [new file with mode: 0644]
protocol/iwrap/main.c [new file with mode: 0644]
protocol/iwrap/mux_exit.rb [new file with mode: 0644]
protocol/iwrap/suart.S [new file with mode: 0644]
protocol/iwrap/suart.h [new file with mode: 0644]
protocol/iwrap/wd.h [new file with mode: 0644]
protocol/lufa.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/HID_EEPROM_Loader/HID_EEPROM_Loader.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/HID_EEPROM_Loader/makefile [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_atprogram.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_avrdude.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_build.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_core.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_cppcheck.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_dfu.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_doxygen.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_hid.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Build/lufa_sources.mk [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/DriverStubs/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/DriverStubs/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/DriverStubs/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/DriverStubs/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/LUFAConfig.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/CodeTemplates/makefile_template [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/ArchitectureSpecific.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/Architectures.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/Attributes.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/BoardTypes.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/Common.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/CompilerSpecific.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Common/Endianness.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Doxygen.conf [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/BuildSystem.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/BuildingLinkableLibraries.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/ChangeLog.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/CompileTimeTokens.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/CompilingApps.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/ConfiguringApps.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/DevelopingWithLUFA.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/DeviceSupport.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/DirectorySummaries.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Donating.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/ExportingLibrary.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/FutureChanges.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/GettingStarted.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Groups.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step1.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step2.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step3.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step4.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_1.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_2.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/AS5_AS6_Import/AS5_AS6_Import_Step5_3.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/Author.jpg [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/LUFA.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Images/LUFA_thumb.png [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/KnownIssues.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/LUFAPoweredProjects.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/LibraryResources.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/LicenseInfo.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/MainPage.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/MigrationInformation.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/ProgrammingApps.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/SoftwareBootloaderJump.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Style/Footer.htm [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/Style/Style.css [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/VIDAndPIDValues.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/DoxygenPages/WritingBoardDrivers.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/ADAFRUITU4/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/ATAVRUSBRF01/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BENITO/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BENITO/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BIGMULTIO/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BLACKCAT/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BUI/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BUMBLEB/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BUMBLEB/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/BUMBLEB/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/CULV3/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/CULV3/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/DUCE/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/EVK527/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/EVK527/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/EVK527/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/EVK527/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/JMDBU2/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/JMDBU2/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MAXIMUS/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MICROPENDOUS/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MICROPENDOUS/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MICROSIN162/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MICROSIN162/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MINIMUS/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MINIMUS/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/MULTIO/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEX162/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEX162/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEX32U4/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEX32U4/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEXISPMK2/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/OLIMEXT32U4/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/RZUSBSTICK/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/SPARKFUN8U2/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK525/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK525/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK525/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK525/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK526/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK526/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK526/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/STK526/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/TEENSY/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/TUL/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/TUL/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/UDIP/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/UDIP/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/UNO/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USB2AX/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USB2AX/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBFOO/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBFOO/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBKEY/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBKEY/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBKEY/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBKEY/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBTINYMKII/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/USBTINYMKII/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/XPLAIN/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/AVR8/XPLAIN/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/Temperature.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/Temperature.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1100/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1100/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1100/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1101/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1101/Joystick.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1101/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1104/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/UC3/EVK1104/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/A3BU_XPLAINED/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Buttons.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/Dataflash.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Board/XMEGA/B1_XPLAINED/LEDs.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Misc/AT45DB321C.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Misc/AT45DB642D.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Misc/RingBuffer.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Misc/TerminalCodes.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/ADC.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/ADC_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/SPI_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/SerialSPI_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/Serial_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/AVR8/TWI_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/SPI.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/Serial.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/SerialSPI.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/TWI.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/XMEGA/SPI_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/XMEGA/SerialSPI_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/Peripheral/XMEGA/Serial_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/AndroidAccessoryClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/AudioClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/CDCClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/AndroidAccessoryClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/AudioClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/CDCClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/HIDClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/HIDParser.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/HIDParser.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/HIDReportData.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/MIDIClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/MassStorageClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/PrinterClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/RNDISClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Common/StillImageClassCommon.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/AudioClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/AudioClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/CDCClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/CDCClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/HIDClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/HIDClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/MIDIClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/MassStorageClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Device/RNDISClassDevice.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/HIDClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/AndroidAccessoryClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/AudioClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/AudioClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/CDCClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/CDCClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/HIDClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/HIDClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/MIDIClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/MIDIClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/MassStorageClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/PrinterClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/RNDISClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/RNDISClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/StillImageClassHost.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/Host/StillImageClassHost.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/MIDIClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/MassStorageClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/PrinterClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/RNDISClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Class/StillImageClass.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/OTG_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_R.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_Control_W.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Template/Template_Endpoint_RW.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/Template/Template_Pipe_RW.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/ConfigDescriptors.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/ConfigDescriptors.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Device.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/DeviceStandardReq.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/DeviceStandardReq.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Endpoint.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/EndpointStream.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Events.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Events.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Host.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/HostStandardReq.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/HostStandardReq.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/OTG.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/Pipe.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/PipeStream.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/StdDescriptors.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/StdRequestType.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Device_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Device_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/EndpointStream_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Endpoint_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Host_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Host_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/PipeStream_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Pipe_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_R.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_Control_W.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Template/Template_Endpoint_RW.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/Template/Template_Pipe_RW.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/USBController_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/USBController_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/UC3/USBInterrupt_UC3.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/USBController.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/USBInterrupt.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/USBMode.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/USBTask.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/USBTask.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/EndpointStream_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Endpoint_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Host_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/PipeStream_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Pipe_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_R.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_Control_W.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/Template/Template_Endpoint_RW.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/USBController_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/Core/XMEGA/USBInterrupt_XMEGA.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Drivers/USB/USB.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/License.txt [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/Platform.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/UC3/ClockManagement.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/UC3/Exception.S [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/UC3/InterruptManagement.c [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/UC3/InterruptManagement.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Platform/XMEGA/ClockManagement.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/Version.h [new file with mode: 0644]
protocol/lufa/LUFA-120730/LUFA/makefile [new file with mode: 0644]
protocol/lufa/LUFA-120730/README.txt [new file with mode: 0644]
protocol/lufa/LUFA-git [new submodule]
protocol/lufa/descriptor.c [new file with mode: 0644]
protocol/lufa/descriptor.h [new file with mode: 0644]
protocol/lufa/lufa.c [new file with mode: 0644]
protocol/lufa/lufa.h [new file with mode: 0644]
protocol/m0110.c [new file with mode: 0644]
protocol/m0110.h [new file with mode: 0644]
protocol/mbed/HIDKeyboard.cpp [new file with mode: 0644]
protocol/mbed/HIDKeyboard.h [new file with mode: 0644]
protocol/mbed/mbed_driver.cpp [new file with mode: 0644]
protocol/mbed/mbed_driver.h [new file with mode: 0644]
protocol/news.c [new file with mode: 0644]
protocol/news.h [new file with mode: 0644]
protocol/next_kbd.c [new file with mode: 0644]
protocol/next_kbd.h [new file with mode: 0644]
protocol/pjrc.mk [new file with mode: 0644]
protocol/pjrc/MEMO.txt [new file with mode: 0644]
protocol/pjrc/main.c [new file with mode: 0644]
protocol/pjrc/pjrc.c [new file with mode: 0644]
protocol/pjrc/pjrc.h [new file with mode: 0644]
protocol/pjrc/usb.c [new file with mode: 0644]
protocol/pjrc/usb.h [new file with mode: 0644]
protocol/pjrc/usb_debug.c [new file with mode: 0644]
protocol/pjrc/usb_debug.h [new file with mode: 0644]
protocol/pjrc/usb_extra.c [new file with mode: 0644]
protocol/pjrc/usb_extra.h [new file with mode: 0644]
protocol/pjrc/usb_keyboard.c [new file with mode: 0644]
protocol/pjrc/usb_keyboard.h [new file with mode: 0644]
protocol/pjrc/usb_mouse.c [new file with mode: 0644]
protocol/pjrc/usb_mouse.h [new file with mode: 0644]
protocol/ps2.h [new file with mode: 0644]
protocol/ps2_busywait.c [new file with mode: 0644]
protocol/ps2_interrupt.c [new file with mode: 0644]
protocol/ps2_io.h [new file with mode: 0644]
protocol/ps2_io_avr.c [new file with mode: 0644]
protocol/ps2_io_mbed.c [new file with mode: 0644]
protocol/ps2_mouse.c [new file with mode: 0644]
protocol/ps2_mouse.h [new file with mode: 0644]
protocol/ps2_usart.c [new file with mode: 0644]
protocol/serial.h [new file with mode: 0644]
protocol/serial_mouse.h [new file with mode: 0644]
protocol/serial_mouse_microsoft.c [new file with mode: 0644]
protocol/serial_mouse_mousesystems.c [new file with mode: 0644]
protocol/serial_soft.c [new file with mode: 0644]
protocol/serial_uart.c [new file with mode: 0644]
protocol/usb_hid.mk [new file with mode: 0644]
protocol/usb_hid/README [new file with mode: 0644]
protocol/usb_hid/USB_Host_Shield_2.0 [new submodule]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Arduino.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/CDC.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Client.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/HID.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/HardwareSerial.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/IPAddress.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Platform.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Print.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Printable.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Server.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Stream.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Tone.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/USBAPI.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/USBCore.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/USBDesc.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/Udp.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/WCharacter.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/WInterrupts.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/WMath.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/WString.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/binary.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/main.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/new.cpp [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/new.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_analog.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_digital.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_private.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_pulse.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/cores/arduino/wiring_shift.c [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/variants/eightanaloginputs/pins_arduino.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/variants/leonardo/pins_arduino.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/variants/mega/pins_arduino.h [new file with mode: 0644]
protocol/usb_hid/arduino-1.0.1/variants/standard/pins_arduino.h [new file with mode: 0644]
protocol/usb_hid/leonardo_led.h [new file with mode: 0644]
protocol/usb_hid/override_Serial.cpp [new file with mode: 0644]
protocol/usb_hid/override_wiring.c [new file with mode: 0644]
protocol/usb_hid/parser.cpp [new file with mode: 0644]
protocol/usb_hid/parser.h [new file with mode: 0644]
protocol/usb_hid/test/Makefile [new file with mode: 0644]
protocol/usb_hid/test/config.h [new file with mode: 0644]
protocol/usb_hid/test/test.cpp [new file with mode: 0644]
protocol/usb_hid/usb_hid.h [new file with mode: 0644]
protocol/vusb.mk [new file with mode: 0644]
protocol/vusb/main.c [new file with mode: 0644]
protocol/vusb/sendchar_usart.c [new file with mode: 0644]
protocol/vusb/usbdrv/Changelog.txt [new file with mode: 0644]
protocol/vusb/usbdrv/CommercialLicense.txt [new file with mode: 0644]
protocol/vusb/usbdrv/License.txt [new file with mode: 0644]
protocol/vusb/usbdrv/Readme.txt [new file with mode: 0644]
protocol/vusb/usbdrv/USB-ID-FAQ.txt [new file with mode: 0644]
protocol/vusb/usbdrv/USB-IDs-for-free.txt [new file with mode: 0644]
protocol/vusb/usbdrv/asmcommon.inc [new file with mode: 0644]
protocol/vusb/usbdrv/oddebug.c [new file with mode: 0644]
protocol/vusb/usbdrv/oddebug.h [new file with mode: 0644]
protocol/vusb/usbdrv/usbconfig-prototype.h [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrv.c [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrv.h [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm.S [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm.asm [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm12.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm128.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm15.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm16.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm165.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm18-crc.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbdrvasm20.inc [new file with mode: 0644]
protocol/vusb/usbdrv/usbportability.h [new file with mode: 0644]
protocol/vusb/vusb.c [new file with mode: 0644]
protocol/vusb/vusb.h [new file with mode: 0644]
rules.mk [new file with mode: 0644]
tool/mbed/common.mk [new file with mode: 0644]
tool/mbed/gcc.mk [new file with mode: 0644]
tool/mbed/lpc-vector-checksum.c [new file with mode: 0644]
tool/mbed/lpc11u35_501.mk [new file with mode: 0644]
tool/mbed/mbed.mk [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f3f4687
--- /dev/null
@@ -0,0 +1,13 @@
+.dep
+*.o
+*.eep
+*.elf
+*.hex
+*.lss
+*.lst
+*.map
+*.sym
+tags
+*~
+build/
+*.bak
diff --git a/.gitmodules b/.gitmodules
new file mode 100644 (file)
index 0000000..e21f449
--- /dev/null
@@ -0,0 +1,6 @@
+[submodule "protocol/lufa/LUFA-git"]
+       path = protocol/lufa/LUFA-git
+       url = https://github.com/abcminiuser/lufa.git
+[submodule "protocol/usb_hid/USB_Host_Shield_2.0"]
+       path = protocol/usb_hid/USB_Host_Shield_2.0
+       url = https://github.com/felis/USB_Host_Shield_2.0.git
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..dd03e14
--- /dev/null
+++ b/README.md
@@ -0,0 +1,296 @@
+TMK Keyboard Firmware Collection
+================================
+This is a keyboard firmware with some useful features for Atmel AVR controller.
+
+Source code is available here: <http://github.com/tmk/tmk_keyboard>
+
+
+Features
+--------
+These features can be used in your keyboard.
+
+* Multi-layer Keymap  - Multiple keyboard layouts with layer switching
+* Mouse key           - Mouse control with keyboard
+* System Control Key  - Power Down, Sleep, Wake Up and USB Remote Wake up
+* Media Control Key   - Volume Down/Up, Mute, Next/Prev track, Play, Stop and etc
+* USB NKRO            - 120 keys(+ 8 modifiers) simultaneously
+* PS/2 mouse support  - PS/2 mouse(TrackPoint) as composite device
+* Keyboard protocols  - PS/2, ADB, M0110, Sun and other old keyboard protocols
+* User Function       - Customizable function of key with writing code
+* Macro               - Very primitive at this time
+* Keyboard Tricks     - Oneshot modifier and modifier with tapping feature
+* Debug Console       - Messages for debug and interaction with firmware
+* Virtual DIP Switch  - Configurations stored EEPROM(Boot Magic)
+* Locking CapsLock    - Mechanical switch support for CapsLock
+* Breathing Sleep LED - Sleep indicator with charm during USB suspend
+* Backlight           - Control backlight levels
+
+
+Projects
+--------
+You can find some keyboard specific projects under `converter` and `keyboard` directory.
+
+### converter
+* [ps2_usb](converter/ps2_usb/)             - [PS/2 keyboard to USB][GH_ps2]
+* [adb_usb](converter/adb_usb/)             - [ADB keyboard to USB][GH_adb]
+* [m0110_usb](converter/m0110_usb)          - [Macintosh 128K/512K/Plus keyboard to USB][GH_m0110]
+* [terminal_usb](converter/terminal_usb/)   - [IBM Model M terminal keyboard(PS/2 scancode set3) to USB][GH_terminal]
+* [news_usb](converter/news_usb/)           - [Sony NEWS keyboard to USB][GH_news]
+* [x68k_usb](converter/x68k_usb/)           - [Sharp X68000 keyboard to USB][GH_x68k]
+* [sun_usb](converter/sun_usb/)             - [Sun] to USB(type4, 5 and 3?)
+* [pc98_usb](converter/pc98_usb/)           - [PC98] to USB
+* [usb_usb](converter/usb_usb/)             - USB to USB(experimental)
+* [ascii_usb](converter/ascii_usb/)         - ASCII(Serial console terminal) to USB
+* [ibm4704_usb](converter/ibm4704_usb)      - [IBM 4704 keyboard Converter][GH_ibm4704]
+
+### keyboard
+* [hhkb](keyboard/hhkb/)                    - [Happy Hacking Keyboard pro][GH_hhkb] **my main board**
+* [gh60](keyboard/gh60/)                    - [GH60] DIY 60% keyboard [prototype][GH60_proto] **my second board**
+* [hbkb](keyboard/hbkb/)                    - [Happy Buckling spring keyboard][GH_hbkb](IBM Model M 60% mod)
+* [hid_liber](keyboard/hid_liber/)          - [HID liberation][HID_liber] controller (by alaricljs)
+* [phantom](keyboard/phantom/)              - [Phantom] keyboard (by Tranquilite)
+* [IIgs_Standard](keyboard/IIgs/)           - Apple [IIGS] keyboard mod(by JeffreySung)
+* [macway](keyboard/macway/)                - [Compact keyboard mod][GH_macway] [retired]
+* [KMAC](keyboard/kmac/)                    - Korean custom keyboard
+* [Lightsaber](keyboard/lightsaber/)        - Korean custom keyboard
+* [Infinity](keyboard/infinity/)            - Massdrop [Infinity keyboard][Infinity]
+* [NerD](keyboard/nerd/)                    - Korean custom keyboard
+* [KittenPaw](keyboard/kitten_paw)          - Custom Majestouch controller
+* [Lightpad](keyboard/lightpad)             - Korean custom keypad
+* [ghost_squid](keyboard/ghost_squid/)      - [The Ghost Squid][ghost_squid] controller for [Cooler Master QuickFire XT][cmxt]
+
+### Extenal projects using tmk_keyboard
+* [ErgoDox_cub-uanic][cub-uanic]            - Split Ergonomic Keyboard [ErgoDox][ergodox_org]
+* [mcdox][mcdox_tmk]                        - [mcdox][mcdox]
+
+
+[GH_macway]:    http://geekhack.org/showwiki.php?title=Island:11930
+[GH_hhkb]:      http://geekhack.org/showwiki.php?title=Island:12047
+[GH_ps2]:       http://geekhack.org/showwiki.php?title=Island:14618
+[GH_adb]:       http://geekhack.org/showwiki.php?title=Island:14290
+[GH_hhkb_bt]:   http://geekhack.org/showwiki.php?title=Island:20851
+[GH_m0110]:     http://geekhack.org/showwiki.php?title=Island:24965
+[GH_news]:      http://geekhack.org/showwiki.php?title=Island:25759
+[GH_terminal]:  http://geekhack.org/showwiki.php?title=Island:27272
+[GH_x68k]:      http://geekhack.org/showwiki.php?title=Island:29060
+[GH_hbkb]:      http://geekhack.org/showwiki.php?title=Island:29483
+[GH_ibm4704]:   http://geekhack.org/index.php?topic=54706.0
+[HID_liber]:    http://deskthority.net/wiki/HID_Liberation_Device_-_DIY_Instructions
+[Phantom]:      http://geekhack.org/index.php?topic=26742
+[GH60]:         http://geekhack.org/index.php?topic=34959
+[GH60_proto]:   http://geekhack.org/index.php?topic=37570.0
+[PC98]:         http://en.wikipedia.org/wiki/NEC_PC-9801
+[Sun]:          http://en.wikipedia.org/wiki/Sun-3
+[IIGS]:         http://en.wikipedia.org/wiki/Apple_IIGS
+[Infinity]:     https://www.massdrop.com/buy/infinity-keyboard-kit
+[ghost_squid]:  http://deskthority.net/wiki/Costar_replacement_controllers#The_Ghost_Squid
+[cmxt]:         http://gaming.coolermaster.com/en/products/keyboards/quickfirext/
+[ergodox_org]:  http://ergodox.org/
+[cub-uanic]:    https://github.com/cub-uanic/tmk_keyboard/tree/master/keyboard/ergodox
+[mcdox]:        https://github.com/DavidMcEwan/mcdox
+[mcdox_tmk]:    https://github.com/DavidMcEwan/tmk_keyboard/tree/master/keyboard/mcdox
+
+
+
+License
+-------
+**GPLv2** or later. Some protocol files are under **Modified BSD License**.
+LUFA, PJRC and V-USB stack have their own license respectively.
+
+
+
+Build Firmware and Program Controller
+-------------------------------------
+See [doc/build.md](doc/build.md).
+
+
+
+Change your keymap
+------------------
+See [doc/keymap.md](doc/keymap.md).
+
+
+
+Magic Commands
+--------------
+To see help press `Magic` + `H`.
+
+ `Magic` key bind may be `LShift` + `RShift` in many project, but `Power` key on ADB converter. `Magic` keybind can be vary on each project, check `config.h` in project directory.
+
+Following commands can be also executed with `Magic` + key. In console mode `Magic` keybind is not needed.
+
+    ----- Command Help -----
+    c:      enter console mode
+    d:      toggle debug enable
+    x:      toggle matrix debug
+    k:      toggle keyboard debug
+    m:      toggle mouse debug
+    v:      print device version & info
+    t:      print timer count
+    s:      print status
+    e:     print eeprom config
+    n:     toggle NKRO
+    0/F10:  switch to Layer0
+    1/F1:   switch to Layer1
+    2/F2:   switch to Layer2
+    3/F3:   switch to Layer3
+    4/F4:   switch to Layer4
+    PScr:   power down/remote wake-up
+    Caps:   Lock Keyboard(Child Proof)
+    Paus:   jump to bootloader
+
+**TBD**
+
+### Boot Magic Configuration - Virtual DIP Switch
+Boot Magic are executed during boot up time. Press Magic key below then plug in keyboard cable.
+Note that you must use keys of **Layer 0** as Magic keys. These settings are stored in EEPROM so that retain your configure over power cycles.
+
+To avoid configuring accidentally additive salt key `KC_SPACE` also needs to be pressed along with the following configuration keys. The salt key is configurable in `config.h`. See [common/bootmagic.h](common/bootmagic.h).
+
+#### General
+- Skip reading EEPROM to start with default configuration(`ESC`)
+- Clear configuration stored in EEPROM to reset configuration(`Backspace`)
+
+#### Bootloader
+- Kick up Bootloader(`B`)
+
+#### Debug
+- Debug enable(`D`)
+- Debug matrix enable(`D`+`X`)
+- Debug keyboard enable(`D`+`K`)
+- Debug mouse enable(`D`+`M`)
+
+#### Keymap
+- Swap Control and CapsLock(`Left Control`)
+- Change CapsLock to Control(`Caps Lock`)
+- Swap LeftAlt and Gui(`Left Alt`)
+- Swap RightAlt and Gui(`Right Alt`)
+- Disable Gui(`Left Gui`)
+- Swap Grave and Escape(`Grave`)
+- Swap BackSlash and BackSpace(`Back Slash`)
+- Enable NKRO on boot(`N`)
+
+#### Default Layer
+- Set Default Layer to 0(`0`)
+- Set Default Layer to 1(`1`)
+- Set Default Layer to 2(`2`)
+- Set Default Layer to 3(`3`)
+- Set Default Layer to 4(`4`)
+- Set Default Layer to 5(`5`)
+- Set Default Layer to 6(`6`)
+- Set Default Layer to 7(`7`)
+
+#### Caution
+Unintentional use of this feature will cause user confusion.
+
+TODO: Magic key combination to avoid unintentional press during plug in
+
+**TBD**
+
+
+Mechanical Locking support
+--------------------------
+This feature makes it possible for you to use mechanical switch for `CapsLock`, `NumLock` or `ScrollLock`. To enable this feature define these macros in `config.h` and use `KC_LCAP`, `KC_LNUM` or `KC_LSCR` in keymap for locking key instead of normal `KC_CAPS`, `KC_NLCK` or `KC_SLCK`. Resync option tries to keep lock switch state consistent with keyboard LED state.
+    #define LOCKING_SUPPORT_ENABLE
+    #define LOCKING_RESYNC_ENABLE
+
+
+Start Your Own Project
+-----------------------
+**TBD**
+### Config.h Options
+#### 1. USB vendor/product ID and device description
+    #define VENDOR_ID       0xFEED
+    #define PRODUCT_ID      0xBEEF
+    #define MANUFACTURER    t.m.k.
+    #define PRODUCT         Macway mod
+    #define DESCRIPTION     t.m.k. keyboard firmware for Macway mod
+
+#### 2. Keyboard matrix configuration
+    #define MATRIX_ROWS 8
+    #define MATRIX_COLS 8
+    #define MATRIX_HAS_GHOST
+
+
+
+Architecture
+------------
+    Architecture Diagram
+                               +---------------+---------------+-------------+
+                               |    Host       |   Keyboard    | Matrix, LED |
+       ___________             |-----------+-+ +-------------+ | +-----------|
+      /          /| Keys/Mouse | Protocol  |d| | Action      | | | Protocol  |
+     /__________/ |<-----------|  LUFA     |r| |  Layer, Tap | | |  Matrix   |
+     |.--------.| |   LED      |  V-USB    |i| |-------------| | |  PS/2,IBM |             __________________
+     ||        || |----------->|  PJRC     |v| | Keymap      | | |  ADB,M0110|  Keys      / /_/_/_/_/_/_/_/ /|
+     ||  Host  || |  Console   |  iWRAP(BT)|e| | Mousekey    | | |  SUN/NEWS |<----------/ /_/_/_/_/_/_/_/ / /
+     ||________||/.<-----------|  UART     |r| | Report      | | |  X68K/PC98| Control  / /_/_/_/_/_/_/_/ / /
+     `_========_'/|            |---------------------------------------------|-------->/___ /_______/ ___/ /
+     |_o______o_|/             | Sendchar, Print, Debug, Command, ...        |         |_________________|/
+                               +---------------------------------------------+              Keyboard
+
+
+
+Debugging
+--------
+Use PJRC's `hid_listen` to see debug messages. You can use the tool for debug even if firmware use LUFA stack.
+
+You can use xprintf() to display debug info on `hid_listen`, see `common/xprintf.h`.
+
+
+
+Files and Directories
+-------------------
+### Top
+* common/       - common codes
+* protocol/     - keyboard protocol support
+* keyboard/     - keyboard projects
+* converter/    - protocol converter projects
+* doc/          - documents
+* common.mk     - Makefile for common
+* protocol.mk    - Makefile for protocol
+* rules.mk      - Makefile for build rules
+
+### Common
+* host.h
+* host_driver.h
+* keyboard.h
+* command.h
+* keymap.h
+* action.h
+* keycode.h
+* matrix.h
+* led.h
+* mousekey.h
+* report.h
+* debug.h
+* print.h
+* bootloader.h
+* sendchar.h
+* timer.h
+* util.h
+
+### Keyboard Protocols
+* lufa/     - LUFA USB stack
+* pjrc/     - PJRC USB stack
+* vusb/     - Objective Development V-USB
+* iwrap/    - Bluetooth HID for Bluegiga iWRAP
+* ps2.c     - PS/2 protocol
+* adb.c     - Apple Desktop Bus protocol
+* m0110.c   - Macintosh 128K/512K/Plus keyboard protocol
+* news.c    - Sony NEWS keyboard protocol
+* x68k.c    - Sharp X68000 keyboard protocol
+* serial_soft.c - Asynchronous Serial protocol implemented by software
+
+
+
+Coding Style
+-------------
+- Doesn't use Tab to indent, use 4-spaces instead.
+
+
+
+Other Keyboard Firmware Projects
+------------------
+You can learn a lot about keyboard firmware from these. See [doc/other_projects.md](doc/other_projects.md).
diff --git a/common.mk b/common.mk
new file mode 100644 (file)
index 0000000..d22adff
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,77 @@
+COMMON_DIR = common
+SRC += $(COMMON_DIR)/host.c \
+       $(COMMON_DIR)/keyboard.c \
+       $(COMMON_DIR)/action.c \
+       $(COMMON_DIR)/action_tapping.c \
+       $(COMMON_DIR)/action_macro.c \
+       $(COMMON_DIR)/action_layer.c \
+       $(COMMON_DIR)/action_util.c \
+       $(COMMON_DIR)/keymap.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
+
+
+# Option modules
+ifdef BOOTMAGIC_ENABLE
+    SRC += $(COMMON_DIR)/bootmagic.c
+    SRC += $(COMMON_DIR)/avr/eeconfig.c
+    OPT_DEFS += -DBOOTMAGIC_ENABLE
+endif
+
+ifdef MOUSEKEY_ENABLE
+    SRC += $(COMMON_DIR)/mousekey.c
+    OPT_DEFS += -DMOUSEKEY_ENABLE
+    OPT_DEFS += -DMOUSE_ENABLE
+endif
+
+ifdef EXTRAKEY_ENABLE
+    OPT_DEFS += -DEXTRAKEY_ENABLE
+endif
+
+ifdef CONSOLE_ENABLE
+    OPT_DEFS += -DCONSOLE_ENABLE
+else
+    OPT_DEFS += -DNO_PRINT
+    OPT_DEFS += -DNO_DEBUG
+endif
+
+ifdef COMMAND_ENABLE
+    SRC += $(COMMON_DIR)/command.c
+    OPT_DEFS += -DCOMMAND_ENABLE
+endif
+
+ifdef NKRO_ENABLE
+    OPT_DEFS += -DNKRO_ENABLE
+endif
+
+ifdef USB_6KRO_ENABLE
+    OPT_DEFS += -DUSB_6KRO_ENABLE
+endif
+
+ifdef SLEEP_LED_ENABLE
+    SRC += $(COMMON_DIR)/sleep_led.c
+    OPT_DEFS += -DSLEEP_LED_ENABLE
+    OPT_DEFS += -DNO_SUSPEND_POWER_DOWN
+endif
+
+ifdef BACKLIGHT_ENABLE
+    SRC += $(COMMON_DIR)/backlight.c
+    OPT_DEFS += -DBACKLIGHT_ENABLE
+endif
+
+ifdef KEYMAP_SECTION_ENABLE
+    OPT_DEFS += -DKEYMAP_SECTION_ENABLE
+    EXTRALDFLAGS = -Wl,-L$(TMK_DIR),-Tldscript_keymap_avr5.x
+endif
+
+# Version string
+OPT_DEFS += -DVERSION=$(shell (git describe --always --dirty || echo 'unknown') 2> /dev/null)
+
+
+# Search Path
+VPATH += $(TMK_DIR)/common
diff --git a/common/action.c b/common/action.c
new file mode 100644 (file)
index 0000000..ec8eeae
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "host.h"
+#include "keycode.h"
+#include "keyboard.h"
+#include "mousekey.h"
+#include "command.h"
+#include "led.h"
+#include "backlight.h"
+#include "action_layer.h"
+#include "action_tapping.h"
+#include "action_macro.h"
+#include "action_util.h"
+#include "action.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+void action_exec(keyevent_t event)
+{
+    if (!IS_NOEVENT(event)) {
+        dprint("\n---- action_exec: start -----\n");
+        dprint("EVENT: "); debug_event(event); dprintln();
+    }
+
+    keyrecord_t record = { .event = event };
+
+#ifndef NO_ACTION_TAPPING
+    action_tapping_process(record);
+#else
+    process_action(&record);
+    if (!IS_NOEVENT(record.event)) {
+        dprint("processed: "); debug_record(record); dprintln();
+    }
+#endif
+}
+
+void process_action(keyrecord_t *record)
+{
+    keyevent_t event = record->event;
+#ifndef NO_ACTION_TAPPING
+    uint8_t tap_count = record->tap.count;
+#endif
+
+    if (IS_NOEVENT(event)) { return; }
+
+    action_t action = layer_switch_get_action(event.key);
+    dprint("ACTION: "); debug_action(action);
+#ifndef NO_ACTION_LAYER
+    dprint(" layer_state: "); layer_debug();
+    dprint(" default_layer_state: "); default_layer_debug();
+#endif
+    dprintln();
+
+    switch (action.kind.id) {
+        /* Key and Mods */
+        case ACT_LMODS:
+        case ACT_RMODS:
+            {
+                uint8_t mods = (action.kind.id == ACT_LMODS) ?  action.key.mods :
+                                                                action.key.mods<<4;
+                if (event.pressed) {
+                    if (mods) {
+                        add_weak_mods(mods);
+                        send_keyboard_report();
+                    }
+                    register_code(action.key.code);
+                } else {
+                    unregister_code(action.key.code);
+                    if (mods) {
+                        del_weak_mods(mods);
+                        send_keyboard_report();
+                    }
+                }
+            }
+            break;
+#ifndef NO_ACTION_TAPPING
+        case ACT_LMODS_TAP:
+        case ACT_RMODS_TAP:
+            {
+                uint8_t mods = (action.kind.id == ACT_LMODS_TAP) ?  action.key.mods :
+                                                                    action.key.mods<<4;
+                switch (action.layer_tap.code) {
+    #ifndef NO_ACTION_ONESHOT
+                    case MODS_ONESHOT:
+                        // Oneshot modifier
+                        if (event.pressed) {
+                            if (tap_count == 0) {
+                                register_mods(mods);
+                            }
+                            else if (tap_count == 1) {
+                                dprint("MODS_TAP: Oneshot: start\n");
+                                set_oneshot_mods(mods);
+                            }
+                            else {
+                                register_mods(mods);
+                            }
+                        } else {
+                            if (tap_count == 0) {
+                                clear_oneshot_mods();
+                                unregister_mods(mods);
+                            }
+                            else if (tap_count == 1) {
+                                // Retain Oneshot mods
+                            }
+                            else {
+                                clear_oneshot_mods();
+                                unregister_mods(mods);
+                            }
+                        }
+                        break;
+    #endif
+                    case MODS_TAP_TOGGLE:
+                        if (event.pressed) {
+                            if (tap_count <= TAPPING_TOGGLE) {
+                                register_mods(mods);
+                            }
+                        } else {
+                            if (tap_count < TAPPING_TOGGLE) {
+                                unregister_mods(mods);
+                            }
+                        }
+                        break;
+                    default:
+                        if (event.pressed) {
+                            if (tap_count > 0) {
+                                if (record->tap.interrupted) {
+                                    dprint("MODS_TAP: Tap: Cancel: add_mods\n");
+                                    // ad hoc: set 0 to cancel tap
+                                    record->tap.count = 0;
+                                    register_mods(mods);
+                                } else {
+                                    dprint("MODS_TAP: Tap: register_code\n");
+                                    register_code(action.key.code);
+                                }
+                            } else {
+                                dprint("MODS_TAP: No tap: add_mods\n");
+                                register_mods(mods);
+                            }
+                        } else {
+                            if (tap_count > 0) {
+                                dprint("MODS_TAP: Tap: unregister_code\n");
+                                unregister_code(action.key.code);
+                            } else {
+                                dprint("MODS_TAP: No tap: add_mods\n");
+                                unregister_mods(mods);
+                            }
+                        }
+                        break;
+                }
+            }
+            break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+        /* other HID usage */
+        case ACT_USAGE:
+            switch (action.usage.page) {
+                case PAGE_SYSTEM:
+                    if (event.pressed) {
+                        host_system_send(action.usage.code);
+                    } else {
+                        host_system_send(0);
+                    }
+                    break;
+                case PAGE_CONSUMER:
+                    if (event.pressed) {
+                        host_consumer_send(action.usage.code);
+                    } else {
+                        host_consumer_send(0);
+                    }
+                    break;
+            }
+            break;
+#endif
+#ifdef MOUSEKEY_ENABLE
+        /* Mouse key */
+        case ACT_MOUSEKEY:
+            if (event.pressed) {
+                mousekey_on(action.key.code);
+                mousekey_send();
+            } else {
+                mousekey_off(action.key.code);
+                mousekey_send();
+            }
+            break;
+#endif
+#ifndef NO_ACTION_LAYER
+        case ACT_LAYER:
+            if (action.layer_bitop.on == 0) {
+                /* Default Layer Bitwise Operation */
+                if (!event.pressed) {
+                    uint8_t shift = action.layer_bitop.part*4;
+                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
+                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
+                    switch (action.layer_bitop.op) {
+                        case OP_BIT_AND: default_layer_and(bits | mask); break;
+                        case OP_BIT_OR:  default_layer_or(bits | mask);  break;
+                        case OP_BIT_XOR: default_layer_xor(bits | mask); break;
+                        case OP_BIT_SET: default_layer_and(mask); default_layer_or(bits); break;
+                    }
+                }
+            } else {
+                /* Layer Bitwise Operation */
+                if (event.pressed ? (action.layer_bitop.on & ON_PRESS) :
+                                    (action.layer_bitop.on & ON_RELEASE)) {
+                    uint8_t shift = action.layer_bitop.part*4;
+                    uint32_t bits = ((uint32_t)action.layer_bitop.bits)<<shift;
+                    uint32_t mask = (action.layer_bitop.xbit) ? ~(((uint32_t)0xf)<<shift) : 0;
+                    switch (action.layer_bitop.op) {
+                        case OP_BIT_AND: layer_and(bits | mask); break;
+                        case OP_BIT_OR:  layer_or(bits | mask);  break;
+                        case OP_BIT_XOR: layer_xor(bits | mask); break;
+                        case OP_BIT_SET: layer_and(mask); layer_or(bits); break;
+                    }
+                }
+            }
+            break;
+    #ifndef NO_ACTION_TAPPING
+        case ACT_LAYER_TAP:
+        case ACT_LAYER_TAP_EXT:
+            switch (action.layer_tap.code) {
+                case 0xe0 ... 0xef:
+                    /* layer On/Off with modifiers(left only) */
+                    if (event.pressed) {
+                        layer_on(action.layer_tap.val);
+                        register_mods(action.layer_tap.code & 0x0f);
+                    } else {
+                        layer_off(action.layer_tap.val);
+                        unregister_mods(action.layer_tap.code & 0x0f);
+                    }
+                    break;
+                case OP_TAP_TOGGLE:
+                    /* tap toggle */
+                    if (event.pressed) {
+                        if (tap_count < TAPPING_TOGGLE) {
+                            layer_invert(action.layer_tap.val);
+                        }
+                    } else {
+                        if (tap_count <= TAPPING_TOGGLE) {
+                            layer_invert(action.layer_tap.val);
+                        }
+                    }
+                    break;
+                case OP_ON_OFF:
+                    event.pressed ? layer_on(action.layer_tap.val) :
+                                    layer_off(action.layer_tap.val);
+                    break;
+                case OP_OFF_ON:
+                    event.pressed ? layer_off(action.layer_tap.val) :
+                                    layer_on(action.layer_tap.val);
+                    break;
+                case OP_SET_CLEAR:
+                    event.pressed ? layer_move(action.layer_tap.val) :
+                                    layer_clear();
+                    break;
+                default:
+                    /* tap key */
+                    if (event.pressed) {
+                        if (tap_count > 0) {
+                            dprint("KEYMAP_TAP_KEY: Tap: register_code\n");
+                            register_code(action.layer_tap.code);
+                        } else {
+                            dprint("KEYMAP_TAP_KEY: No tap: On on press\n");
+                            layer_on(action.layer_tap.val);
+                        }
+                    } else {
+                        if (tap_count > 0) {
+                            dprint("KEYMAP_TAP_KEY: Tap: unregister_code\n");
+                            unregister_code(action.layer_tap.code);
+                        } else {
+                            dprint("KEYMAP_TAP_KEY: No tap: Off on release\n");
+                            layer_off(action.layer_tap.val);
+                        }
+                    }
+                    break;
+            }
+            break;
+    #endif
+#endif
+        /* Extentions */
+#ifndef NO_ACTION_MACRO
+        case ACT_MACRO:
+            action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
+            break;
+#endif
+#ifdef BACKLIGHT_ENABLE
+        case ACT_BACKLIGHT:
+            if (!event.pressed) {
+                switch (action.backlight.opt) {
+                    case BACKLIGHT_INCREASE:
+                        backlight_increase();
+                        break;
+                    case BACKLIGHT_DECREASE:
+                        backlight_decrease();
+                        break;
+                    case BACKLIGHT_TOGGLE:
+                        backlight_toggle();
+                        break;
+                    case BACKLIGHT_STEP:
+                        backlight_step();
+                        break;
+                    case BACKLIGHT_LEVEL:
+                        backlight_level(action.backlight.level);
+                        break;
+                }
+            }
+            break;
+#endif
+        case ACT_COMMAND:
+            break;
+#ifndef NO_ACTION_FUNCTION
+        case ACT_FUNCTION:
+            action_function(record, action.func.id, action.func.opt);
+            break;
+#endif
+        default:
+            break;
+    }
+}
+
+
+
+
+/*
+ * Utilities for actions.
+ */
+void register_code(uint8_t code)
+{
+    if (code == KC_NO) {
+        return;
+    }
+
+#ifdef LOCKING_SUPPORT_ENABLE
+    else if (KC_LOCKING_CAPS == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        // Resync: ignore if caps lock already is on
+        if (host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK)) return;
+#endif
+        add_key(KC_CAPSLOCK);
+        send_keyboard_report();
+        del_key(KC_CAPSLOCK);
+        send_keyboard_report();
+    }
+
+    else if (KC_LOCKING_NUM == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        if (host_keyboard_leds() & (1<<USB_LED_NUM_LOCK)) return;
+#endif
+        add_key(KC_NUMLOCK);
+        send_keyboard_report();
+        del_key(KC_NUMLOCK);
+        send_keyboard_report();
+    }
+
+    else if (KC_LOCKING_SCROLL == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        if (host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK)) return;
+#endif
+        add_key(KC_SCROLLLOCK);
+        send_keyboard_report();
+        del_key(KC_SCROLLLOCK);
+        send_keyboard_report();
+    }
+#endif
+
+    else if IS_KEY(code) {
+        // TODO: should push command_proc out of this block?
+        if (command_proc(code)) return;
+
+#ifndef NO_ACTION_ONESHOT
+/* TODO: remove
+        if (oneshot_state.mods && !oneshot_state.disabled) {
+            uint8_t tmp_mods = get_mods();
+            add_mods(oneshot_state.mods);
+
+            add_key(code);
+            send_keyboard_report();
+
+            set_mods(tmp_mods);
+            send_keyboard_report();
+            oneshot_cancel();
+        } else 
+*/
+#endif
+        {
+            add_key(code);
+            send_keyboard_report();
+        }
+    }
+    else if IS_MOD(code) {
+        add_mods(MOD_BIT(code));
+        send_keyboard_report();
+    }
+    else if IS_SYSTEM(code) {
+        host_system_send(KEYCODE2SYSTEM(code));
+    }
+    else if IS_CONSUMER(code) {
+        host_consumer_send(KEYCODE2CONSUMER(code));
+    }
+}
+
+void unregister_code(uint8_t code)
+{
+    if (code == KC_NO) {
+        return;
+    }
+
+#ifdef LOCKING_SUPPORT_ENABLE
+    else if (KC_LOCKING_CAPS == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        // Resync: ignore if caps lock already is off
+        if (!(host_keyboard_leds() & (1<<USB_LED_CAPS_LOCK))) return;
+#endif
+        add_key(KC_CAPSLOCK);
+        send_keyboard_report();
+        del_key(KC_CAPSLOCK);
+        send_keyboard_report();
+    }
+
+    else if (KC_LOCKING_NUM == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        if (!(host_keyboard_leds() & (1<<USB_LED_NUM_LOCK))) return;
+#endif
+        add_key(KC_NUMLOCK);
+        send_keyboard_report();
+        del_key(KC_NUMLOCK);
+        send_keyboard_report();
+    }
+
+    else if (KC_LOCKING_SCROLL == code) {
+#ifdef LOCKING_RESYNC_ENABLE
+        if (!(host_keyboard_leds() & (1<<USB_LED_SCROLL_LOCK))) return;
+#endif
+        add_key(KC_SCROLLLOCK);
+        send_keyboard_report();
+        del_key(KC_SCROLLLOCK);
+        send_keyboard_report();
+    }
+#endif
+
+    else if IS_KEY(code) {
+        del_key(code);
+        send_keyboard_report();
+    }
+    else if IS_MOD(code) {
+        del_mods(MOD_BIT(code));
+        send_keyboard_report();
+    }
+    else if IS_SYSTEM(code) {
+        host_system_send(0);
+    }
+    else if IS_CONSUMER(code) {
+        host_consumer_send(0);
+    }
+}
+
+void register_mods(uint8_t mods)
+{
+    if (mods) {
+        add_mods(mods);
+        send_keyboard_report();
+    }
+}
+
+void unregister_mods(uint8_t mods)
+{
+    if (mods) {
+        del_mods(mods);
+        send_keyboard_report();
+    }
+}
+
+void clear_keyboard(void)
+{
+    clear_mods();
+    clear_keyboard_but_mods();
+}
+
+void clear_keyboard_but_mods(void)
+{
+    clear_weak_mods();
+    clear_keys();
+    send_keyboard_report();
+#ifdef MOUSEKEY_ENABLE
+    mousekey_clear();
+    mousekey_send();
+#endif
+#ifdef EXTRAKEY_ENABLE
+    host_system_send(0);
+    host_consumer_send(0);
+#endif
+}
+
+bool is_tap_key(keypos_t key)
+{
+    action_t action = layer_switch_get_action(key);
+
+    switch (action.kind.id) {
+        case ACT_LMODS_TAP:
+        case ACT_RMODS_TAP:
+        case ACT_LAYER_TAP:
+        case ACT_LAYER_TAP_EXT:
+            return true;
+        case ACT_MACRO:
+        case ACT_FUNCTION:
+            if (action.func.opt & FUNC_TAP) { return true; }
+            return false;
+    }
+    return false;
+}
+
+
+/*
+ * debug print
+ */
+void debug_event(keyevent_t event)
+{
+    dprintf("%04X%c(%u)", (event.key.row<<8 | event.key.col), (event.pressed ? 'd' : 'u'), event.time);
+}
+
+void debug_record(keyrecord_t record)
+{
+    debug_event(record.event);
+#ifndef NO_ACTION_TAPPING
+    dprintf(":%u%c", record.tap.count, (record.tap.interrupted ? '-' : ' '));
+#endif
+}
+
+void debug_action(action_t action)
+{
+    switch (action.kind.id) {
+        case ACT_LMODS:             dprint("ACT_LMODS");             break;
+        case ACT_RMODS:             dprint("ACT_RMODS");             break;
+        case ACT_LMODS_TAP:         dprint("ACT_LMODS_TAP");         break;
+        case ACT_RMODS_TAP:         dprint("ACT_RMODS_TAP");         break;
+        case ACT_USAGE:             dprint("ACT_USAGE");             break;
+        case ACT_MOUSEKEY:          dprint("ACT_MOUSEKEY");          break;
+        case ACT_LAYER:             dprint("ACT_LAYER");             break;
+        case ACT_LAYER_TAP:         dprint("ACT_LAYER_TAP");         break;
+        case ACT_LAYER_TAP_EXT:     dprint("ACT_LAYER_TAP_EXT");     break;
+        case ACT_MACRO:             dprint("ACT_MACRO");             break;
+        case ACT_COMMAND:           dprint("ACT_COMMAND");           break;
+        case ACT_FUNCTION:          dprint("ACT_FUNCTION");          break;
+        default:                    dprint("UNKNOWN");               break;
+    }
+    dprintf("[%X:%02X]", action.kind.param>>8, action.kind.param&0xff);
+}
diff --git a/common/action.h b/common/action.h
new file mode 100644 (file)
index 0000000..8a4736d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+Copyright 2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_H
+#define ACTION_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "keyboard.h"
+#include "keycode.h"
+#include "action_code.h"
+#include "action_macro.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* tapping count and state */
+typedef struct {
+    bool    interrupted :1;
+    bool    reserved2   :1;
+    bool    reserved1   :1;
+    bool    reserved0   :1;
+    uint8_t count       :4;
+} tap_t;
+
+/* Key event container for recording */
+typedef struct {
+    keyevent_t  event;
+#ifndef NO_ACTION_TAPPING
+    tap_t tap;
+#endif
+} keyrecord_t;
+
+/* Execute action per keyevent */
+void action_exec(keyevent_t event);
+
+/* action for key */
+action_t action_for_key(uint8_t layer, keypos_t key);
+
+/* macro */
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt);
+
+/* user defined special function */
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt);
+
+/* Utilities for actions.  */
+void process_action(keyrecord_t *record);
+void register_code(uint8_t code);
+void unregister_code(uint8_t code);
+void register_mods(uint8_t mods);
+void unregister_mods(uint8_t mods);
+//void set_mods(uint8_t mods);
+void clear_keyboard(void);
+void clear_keyboard_but_mods(void);
+void layer_switch(uint8_t new_layer);
+bool is_tap_key(keypos_t key);
+
+/* debug */
+void debug_event(keyevent_t event);
+void debug_record(keyrecord_t record);
+void debug_action(action_t action);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ACTION_H */
diff --git a/common/action_code.h b/common/action_code.h
new file mode 100644 (file)
index 0000000..bc40e2c
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_CODE_H
+#define ACTION_CODE_H
+
+/* Action codes
+ * ============
+ * 16bit code: action_kind(4bit) + action_parameter(12bit)
+ *
+ *
+ * Key Actions(00xx)
+ * -----------------
+ * ACT_MODS(000r):
+ * 000r|0000|0000 0000    No action code
+ * 000r|0000|0000 0001    Transparent code
+ * 000r|0000| keycode     Key
+ * 000r|mods|0000 0000    Modifiers
+ * 000r|mods| keycode     Modifiers+Key(Modified key)
+ *   r: Left/Right flag(Left:0, Right:1)
+ *
+ * ACT_MODS_TAP(001r):
+ * 001r|mods|0000 0000    Modifiers with OneShot
+ * 001r|mods|0000 0001    Modifiers with tap toggle
+ * 001r|mods|0000 00xx    (reserved)
+ * 001r|mods| keycode     Modifiers with Tap Key(Dual role)
+ *
+ *
+ * Other Keys(01xx)
+ * ----------------
+ * ACT_USAGE(0100): TODO: Not needed?
+ * 0100|00| usage(10)     System control(0x80) - General Desktop page(0x01)
+ * 0100|01| usage(10)     Consumer control(0x01) - Consumer page(0x0C)
+ * 0100|10| usage(10)     (reserved)
+ * 0100|11| usage(10)     (reserved)
+ *
+ * ACT_MOUSEKEY(0110): TODO: Not needed?
+ * 0101|xxxx| keycode     Mouse key
+ *
+ * 011x|xxxx xxxx xxxx    (reseved)
+ *
+ *
+ * Layer Actions(10xx)
+ * -------------------
+ * ACT_LAYER(1000):
+ * 1000|oo00|pppE BBBB   Default Layer Bitwise operation
+ *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
+ *   ppp:   4-bit chunk part(0-7)
+ *   EBBBB: bits and extra bit
+ * 1000|ooee|pppE BBBB   Layer Bitwise Operation
+ *   oo:    operation(00:AND, 01:OR, 10:XOR, 11:SET)
+ *   ppp:   4-bit chunk part(0-7)
+ *   EBBBB: bits and extra bit
+ *   ee:    on event(01:press, 10:release, 11:both)
+ *
+ * 1001|xxxx|xxxx xxxx   (reserved)
+ * 1001|oopp|BBBB BBBB   8-bit Bitwise Operation???
+ *
+ * ACT_LAYER_TAP(101x):
+ * 101E|LLLL| keycode    On/Off with tap key
+ * 101E|LLLL|1110 mods   On/Off with modifiers(0xE0-EF)
+ * 101E|LLLL|1111 0000   Invert with tap toggle(0xF0)
+ * 101E|LLLL|1111 0001   On/Off
+ * 101E|LLLL|1111 0010   Off/On
+ * 101E|LLLL|1111 0011   Set/Clear
+ * 101E|LLLL|1111 xxxx   Reserved(0xF4-FF)
+ *   ELLLL: layer 0-31(E: extra bit for layer 16-31)
+ *
+ *
+ * Extensions(11xx)
+ * ----------------
+ * ACT_MACRO(1100):
+ * 1100|opt | id(8)      Macro play?
+ * 1100|1111| id(8)      Macro record?
+ *
+ * ACT_BACKLIGHT(1101):
+ * 1101|opt |level(8)    Backlight commands
+ *
+ * ACT_COMMAND(1110):
+ * 1110|opt | id(8)      Built-in Command exec
+ *
+ * ACT_FUNCTION(1111):
+ * 1111| address(12)     Function?
+ * 1111|opt | id(8)      Function?
+ */
+enum action_kind_id {
+    /* Key Actions */
+    ACT_MODS            = 0b0000,
+    ACT_LMODS           = 0b0000,
+    ACT_RMODS           = 0b0001,
+    ACT_MODS_TAP        = 0b0010,
+    ACT_LMODS_TAP       = 0b0010,
+    ACT_RMODS_TAP       = 0b0011,
+    /* Other Keys */
+    ACT_USAGE           = 0b0100,
+    ACT_MOUSEKEY        = 0b0101,
+    /* Layer Actions */
+    ACT_LAYER           = 0b1000,
+    ACT_LAYER_TAP       = 0b1010, /* Layer  0-15 */
+    ACT_LAYER_TAP_EXT   = 0b1011, /* Layer 16-31 */
+    /* Extensions */
+    ACT_MACRO           = 0b1100,
+    ACT_BACKLIGHT       = 0b1101,
+    ACT_COMMAND         = 0b1110,
+    ACT_FUNCTION        = 0b1111
+};
+
+
+/* Action Code Struct
+ *
+ * NOTE:
+ * In avr-gcc bit field seems to be assigned from LSB(bit0) to MSB(bit15).
+ * AVR looks like a little endian in avr-gcc.
+ * Not portable across compiler/endianness?
+ *
+ * Byte order and bit order of 0x1234:
+ *   Big endian:                Little endian:
+ *   --------------------       --------------------
+ *   FEDC BA98  7654 3210       0123 4567  89AB CDEF
+ *   0001 0010  0011 0100       0010 1100  0100 1000
+ *     0x12       0x34            0x34       0x12
+ */
+typedef union {
+    uint16_t code;
+    struct action_kind {
+        uint16_t param  :12;
+        uint8_t  id     :4;
+    } kind;
+    struct action_key {
+        uint8_t  code   :8;
+        uint8_t  mods   :4;
+        uint8_t  kind   :4;
+    } key;
+    struct action_layer_bitop {
+        uint8_t  bits   :4;
+        uint8_t  xbit   :1;
+        uint8_t  part   :3;
+        uint8_t  on     :2;
+        uint8_t  op     :2;
+        uint8_t  kind   :4;
+    } layer_bitop;
+    struct action_layer_tap {
+        uint8_t  code   :8;
+        uint8_t  val    :5;
+        uint8_t  kind   :3;
+    } layer_tap;
+    struct action_usage {
+        uint16_t code   :10;
+        uint8_t  page   :2;
+        uint8_t  kind   :4;
+    } usage;
+    struct action_backlight {
+        uint8_t  level  :8;
+        uint8_t  opt    :4;
+        uint8_t  kind   :4;
+    } backlight;
+    struct action_command {
+        uint8_t  id     :8;
+        uint8_t  opt    :4;
+        uint8_t  kind   :4;
+    } command;
+    struct action_function {
+        uint8_t  id     :8;
+        uint8_t  opt    :4;
+        uint8_t  kind   :4;
+    } func;
+} action_t;
+
+
+/* action utility */
+#define ACTION_NO                       0
+#define ACTION_TRANSPARENT              1
+#define ACTION(kind, param)             ((kind)<<12 | (param))
+
+
+/*
+ * Key Actions
+ */
+/* Mod bits:    43210
+ *   bit 0      ||||+- Control
+ *   bit 1      |||+-- Shift
+ *   bit 2      ||+--- Alt
+ *   bit 3      |+---- Gui
+ *   bit 4      +----- LR flag(Left:0, Right:1)
+ */
+enum mods_bit {
+    MOD_LCTL = 0x01,
+    MOD_LSFT = 0x02,
+    MOD_LALT = 0x04,
+    MOD_LGUI = 0x08,
+    MOD_RCTL = 0x11,
+    MOD_RSFT = 0x12,
+    MOD_RALT = 0x14,
+    MOD_RGUI = 0x18,
+};
+enum mods_codes {
+    MODS_ONESHOT = 0x00,
+    MODS_TAP_TOGGLE = 0x01,
+};
+#define ACTION_KEY(key)                 ACTION(ACT_MODS, (key))
+#define ACTION_MODS(mods)               ACTION(ACT_MODS, ((mods)&0x1f)<<8 | 0)
+#define ACTION_MODS_KEY(mods, key)      ACTION(ACT_MODS, ((mods)&0x1f)<<8 | (key))
+#define ACTION_MODS_TAP_KEY(mods, key)  ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | (key))
+#define ACTION_MODS_ONESHOT(mods)       ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_ONESHOT)
+#define ACTION_MODS_TAP_TOGGLE(mods)    ACTION(ACT_MODS_TAP, ((mods)&0x1f)<<8 | MODS_TAP_TOGGLE)
+
+
+/*
+ * Other Keys
+ */
+enum usage_pages {
+    PAGE_SYSTEM,
+    PAGE_CONSUMER
+};
+#define ACTION_USAGE_SYSTEM(id)         ACTION(ACT_USAGE, PAGE_SYSTEM<<10 | (id))
+#define ACTION_USAGE_CONSUMER(id)       ACTION(ACT_USAGE, PAGE_CONSUMER<<10 | (id))
+#define ACTION_MOUSEKEY(key)            ACTION(ACT_MOUSEKEY, key)
+
+
+
+/* 
+ * Layer Actions
+ */
+enum layer_param_on {
+    ON_PRESS    = 1,
+    ON_RELEASE  = 2,
+    ON_BOTH     = 3,
+};
+enum layer_param_bit_op {
+    OP_BIT_AND = 0,
+    OP_BIT_OR  = 1,
+    OP_BIT_XOR = 2,
+    OP_BIT_SET = 3,
+};
+enum layer_pram_tap_op {
+    OP_TAP_TOGGLE = 0xF0,
+    OP_ON_OFF,
+    OP_OFF_ON,
+    OP_SET_CLEAR,
+};
+#define ACTION_LAYER_BITOP(op, part, bits, on)      (ACT_LAYER<<12 | (op)<<10 | (on)<<8 | (part)<<5 | ((bits)&0x1f))
+#define ACTION_LAYER_TAP(layer, key)                (ACT_LAYER_TAP<<12 | (layer)<<8 | (key))
+/* Default Layer */
+#define ACTION_DEFAULT_LAYER_SET(layer)             ACTION_DEFAULT_LAYER_BIT_SET((layer)/4, 1<<((layer)%4))
+/* Layer Operation */
+#define ACTION_LAYER_CLEAR(on)                      ACTION_LAYER_BIT_AND(0, 0, (on))
+#define ACTION_LAYER_MOMENTARY(layer)               ACTION_LAYER_ON_OFF(layer)
+#define ACTION_LAYER_TOGGLE(layer)                  ACTION_LAYER_INVERT(layer, ON_RELEASE)
+#define ACTION_LAYER_INVERT(layer, on)              ACTION_LAYER_BIT_XOR((layer)/4,   1<<((layer)%4),  (on))
+#define ACTION_LAYER_ON(layer, on)                  ACTION_LAYER_BIT_OR( (layer)/4,   1<<((layer)%4),  (on))
+#define ACTION_LAYER_OFF(layer, on)                 ACTION_LAYER_BIT_AND((layer)/4, ~(1<<((layer)%4)), (on))
+#define ACTION_LAYER_SET(layer, on)                 ACTION_LAYER_BIT_SET((layer)/4,   1<<((layer)%4),  (on))
+#define ACTION_LAYER_ON_OFF(layer)                  ACTION_LAYER_TAP((layer), OP_ON_OFF)
+#define ACTION_LAYER_OFF_ON(layer)                  ACTION_LAYER_TAP((layer), OP_OFF_ON)
+#define ACTION_LAYER_SET_CLEAR(layer)               ACTION_LAYER_TAP((layer), OP_SET_CLEAR)
+#define ACTION_LAYER_MODS(layer, mods)              ACTION_LAYER_TAP((layer), 0xe0 | (mods)&0x0f)
+/* With Tapping */
+#define ACTION_LAYER_TAP_KEY(layer, key)            ACTION_LAYER_TAP((layer), (key))
+#define ACTION_LAYER_TAP_TOGGLE(layer)              ACTION_LAYER_TAP((layer), OP_TAP_TOGGLE)
+/* Bitwise Operation */
+#define ACTION_LAYER_BIT_AND(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), (on))
+#define ACTION_LAYER_BIT_OR( part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_OR,  (part), (bits), (on))
+#define ACTION_LAYER_BIT_XOR(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), (on))
+#define ACTION_LAYER_BIT_SET(part, bits, on)        ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), (on))
+/* Default Layer Bitwise Operation */
+#define ACTION_DEFAULT_LAYER_BIT_AND(part, bits)    ACTION_LAYER_BITOP(OP_BIT_AND, (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_OR( part, bits)    ACTION_LAYER_BITOP(OP_BIT_OR,  (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_XOR(part, bits)    ACTION_LAYER_BITOP(OP_BIT_XOR, (part), (bits), 0)
+#define ACTION_DEFAULT_LAYER_BIT_SET(part, bits)    ACTION_LAYER_BITOP(OP_BIT_SET, (part), (bits), 0)
+
+
+/*
+ * Extensions
+ */
+enum backlight_opt {
+    BACKLIGHT_INCREASE = 0,
+    BACKLIGHT_DECREASE = 1,
+    BACKLIGHT_TOGGLE   = 2,
+    BACKLIGHT_STEP     = 3,
+    BACKLIGHT_LEVEL    = 4,
+};
+/* Macro */
+#define ACTION_MACRO(id)                ACTION(ACT_MACRO, (id))
+#define ACTION_MACRO_TAP(id)            ACTION(ACT_MACRO, FUNC_TAP<<8 | (id))
+#define ACTION_MACRO_OPT(id, opt)       ACTION(ACT_MACRO, (opt)<<8 | (id))
+/* Backlight */
+#define ACTION_BACKLIGHT_INCREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_INCREASE << 8)
+#define ACTION_BACKLIGHT_DECREASE()     ACTION(ACT_BACKLIGHT, BACKLIGHT_DECREASE << 8)
+#define ACTION_BACKLIGHT_TOGGLE()       ACTION(ACT_BACKLIGHT, BACKLIGHT_TOGGLE << 8)
+#define ACTION_BACKLIGHT_STEP()         ACTION(ACT_BACKLIGHT, BACKLIGHT_STEP << 8)
+#define ACTION_BACKLIGHT_LEVEL(level)   ACTION(ACT_BACKLIGHT, BACKLIGHT_LEVEL << 8 | level)
+/* Command */
+#define ACTION_COMMAND(id, opt)         ACTION(ACT_COMMAND,  (opt)<<8 | (addr))
+/* Function */
+enum function_opts {
+    FUNC_TAP = 0x8,     /* indciates function is tappable */
+};
+#define ACTION_FUNCTION(id)             ACTION(ACT_FUNCTION, (id))
+#define ACTION_FUNCTION_TAP(id)         ACTION(ACT_FUNCTION, FUNC_TAP<<8 | (id))
+#define ACTION_FUNCTION_OPT(id, opt)    ACTION(ACT_FUNCTION, (opt)<<8 | (id))
+
+#endif /* ACTION_CODE_H */
diff --git a/common/action_layer.c b/common/action_layer.c
new file mode 100644 (file)
index 0000000..c535615
--- /dev/null
@@ -0,0 +1,138 @@
+#include <stdint.h>
+#include "keyboard.h"
+#include "action.h"
+#include "util.h"
+#include "action_layer.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+/* 
+ * Default Layer State
+ */
+uint32_t default_layer_state = 0;
+
+static void default_layer_state_set(uint32_t state)
+{
+    debug("default_layer_state: ");
+    default_layer_debug(); debug(" to ");
+    default_layer_state = state;
+    default_layer_debug(); debug("\n");
+    clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void default_layer_debug(void)
+{
+    dprintf("%08lX(%u)", default_layer_state, biton32(default_layer_state));
+}
+
+void default_layer_set(uint32_t state)
+{
+    default_layer_state_set(state);
+}
+
+#ifndef NO_ACTION_LAYER
+void default_layer_or(uint32_t state)
+{
+    default_layer_state_set(default_layer_state | state);
+}
+void default_layer_and(uint32_t state)
+{
+    default_layer_state_set(default_layer_state & state);
+}
+void default_layer_xor(uint32_t state)
+{
+    default_layer_state_set(default_layer_state ^ state);
+}
+#endif
+
+
+#ifndef NO_ACTION_LAYER
+/* 
+ * Keymap Layer State
+ */
+uint32_t layer_state = 0;
+
+static void layer_state_set(uint32_t state)
+{
+    dprint("layer_state: ");
+    layer_debug(); dprint(" to ");
+    layer_state = state;
+    layer_debug(); dprintln();
+    clear_keyboard_but_mods(); // To avoid stuck keys
+}
+
+void layer_clear(void)
+{
+    layer_state_set(0);
+}
+
+void layer_move(uint8_t layer)
+{
+    layer_state_set(1UL<<layer);
+}
+
+void layer_on(uint8_t layer)
+{
+    layer_state_set(layer_state | (1UL<<layer));
+}
+
+void layer_off(uint8_t layer)
+{
+    layer_state_set(layer_state & ~(1UL<<layer));
+}
+
+void layer_invert(uint8_t layer)
+{
+    layer_state_set(layer_state ^ (1UL<<layer));
+}
+
+void layer_or(uint32_t state)
+{
+    layer_state_set(layer_state | state);
+}
+void layer_and(uint32_t state)
+{
+    layer_state_set(layer_state & state);
+}
+void layer_xor(uint32_t state)
+{
+    layer_state_set(layer_state ^ state);
+}
+
+void layer_debug(void)
+{
+    dprintf("%08lX(%u)", layer_state, biton32(layer_state));
+}
+#endif
+
+
+
+action_t layer_switch_get_action(keypos_t key)
+{
+    action_t action;
+    action.code = ACTION_TRANSPARENT;
+
+#ifndef NO_ACTION_LAYER
+    uint32_t layers = layer_state | default_layer_state;
+    /* check top layer first */
+    for (int8_t i = 31; i >= 0; i--) {
+        if (layers & (1UL<<i)) {
+            action = action_for_key(i, key);
+            if (action.code != ACTION_TRANSPARENT) {
+                return action;
+            }
+        }
+    }
+    /* fall back to layer 0 */
+    action = action_for_key(0, key);
+    return action;
+#else
+    action = action_for_key(biton32(default_layer_state), key);
+    return action;
+#endif
+}
diff --git a/common/action_layer.h b/common/action_layer.h
new file mode 100644 (file)
index 0000000..b6da353
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_LAYER_H
+#define ACTION_LAYER_H
+
+#include <stdint.h>
+#include "keyboard.h"
+#include "action.h"
+
+
+/*
+ * Default Layer
+ */
+extern uint32_t default_layer_state;
+void default_layer_debug(void);
+void default_layer_set(uint32_t state);
+
+#ifndef NO_ACTION_LAYER
+/* bitwise operation */
+void default_layer_or(uint32_t state);
+void default_layer_and(uint32_t state);
+void default_layer_xor(uint32_t state);
+#else
+#define default_layer_or(state)
+#define default_layer_and(state)
+#define default_layer_xor(state)
+#endif
+
+
+/*
+ * Keymap Layer
+ */
+#ifndef NO_ACTION_LAYER
+extern uint32_t layer_state;
+void layer_debug(void);
+void layer_clear(void);
+void layer_move(uint8_t layer);
+void layer_on(uint8_t layer);
+void layer_off(uint8_t layer);
+void layer_invert(uint8_t layer);
+/* bitwise operation */
+void layer_or(uint32_t state);
+void layer_and(uint32_t state);
+void layer_xor(uint32_t state);
+#else
+#define layer_state             0
+#define layer_clear()
+#define layer_move(layer)
+#define layer_on(layer)
+#define layer_off(layer)
+#define layer_invert(layer)
+
+#define layer_or(state)
+#define layer_and(state)
+#define layer_xor(state)
+#define layer_debug()
+#endif
+
+
+/* return action depending on current layer status */
+action_t layer_switch_get_action(keypos_t key);
+
+#endif
diff --git a/common/action_macro.c b/common/action_macro.c
new file mode 100644 (file)
index 0000000..ba93fc8
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "action.h"
+#include "action_util.h"
+#include "action_macro.h"
+#include "wait.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+
+#ifndef NO_ACTION_MACRO
+
+#define MACRO_READ()  (macro = MACRO_GET(macro_p++))
+void action_macro_play(const macro_t *macro_p)
+{
+    macro_t macro = END;
+    uint8_t interval = 0;
+
+    if (!macro_p) return;
+    while (true) {
+        switch (MACRO_READ()) {
+            case KEY_DOWN:
+                MACRO_READ();
+                dprintf("KEY_DOWN(%02X)\n", macro);
+                if (IS_MOD(macro)) {
+                    add_weak_mods(MOD_BIT(macro));
+                } else {
+                    register_code(macro);
+                }
+                break;
+            case KEY_UP:
+                MACRO_READ();
+                dprintf("KEY_UP(%02X)\n", macro);
+                if (IS_MOD(macro)) {
+                    del_weak_mods(MOD_BIT(macro));
+                } else {
+                    unregister_code(macro);
+                }
+                break;
+            case WAIT:
+                MACRO_READ();
+                dprintf("WAIT(%u)\n", macro);
+                { uint8_t ms = macro; while (ms--) wait_ms(1); }
+                break;
+            case INTERVAL:
+                interval = MACRO_READ();
+                dprintf("INTERVAL(%u)\n", interval);
+                break;
+            case 0x04 ... 0x73:
+                dprintf("DOWN(%02X)\n", macro);
+                register_code(macro);
+                break;
+            case 0x84 ... 0xF3:
+                dprintf("UP(%02X)\n", macro);
+                unregister_code(macro&0x7F);
+                break;
+            case END:
+            default:
+                return;
+        }
+        // interval
+        { uint8_t ms = interval; while (ms--) wait_ms(1); }
+    }
+}
+#endif
diff --git a/common/action_macro.h b/common/action_macro.h
new file mode 100644 (file)
index 0000000..aedc32e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_MACRO_H
+#define ACTION_MACRO_H
+#include <stdint.h>
+#include "progmem.h"
+
+
+#define MACRO_NONE      0
+#define MACRO(...)      ({ static const macro_t __m[] PROGMEM = { __VA_ARGS__ }; &__m[0]; })
+#define MACRO_GET(p)    pgm_read_byte(p)
+
+typedef uint8_t macro_t;
+
+
+#ifndef NO_ACTION_MACRO
+void action_macro_play(const macro_t *macro_p);
+#else
+#define action_macro_play(macro)
+#endif
+
+
+
+/* Macro commands
+ *   code(0x04-73)                      // key down(1byte)
+ *   code(0x04-73) | 0x80               // key up(1byte)
+ *   { KEY_DOWN, code(0x04-0xff) }      // key down(2bytes)
+ *   { KEY_UP,   code(0x04-0xff) }      // key up(2bytes)
+ *   WAIT                               // wait milli-seconds
+ *   INTERVAL                           // set interval between macro commands
+ *   END                                // stop macro execution
+ *
+ * Ideas(Not implemented):
+ *   modifiers
+ *   system usage
+ *   consumer usage
+ *   unicode usage
+ *   function call
+ *   conditionals
+ *   loop
+ */
+enum macro_command_id{
+    /* 0x00 - 0x03 */
+    END                 = 0x00,
+    KEY_DOWN,
+    KEY_UP,
+
+    /* 0x04 - 0x73 (reserved for keycode down) */
+
+    /* 0x74 - 0x83 */
+    WAIT                = 0x74,
+    INTERVAL,
+
+    /* 0x84 - 0xf3 (reserved for keycode up) */
+
+    /* 0xf4 - 0xff */
+};
+
+
+/* TODO: keycode:0x04-0x73 can be handled by 1byte command  else 2bytes are needed
+ * if keycode between 0x04 and 0x73
+ *      keycode / (keycode|0x80)
+ * else
+ *      {KEY_DOWN, keycode} / {KEY_UP, keycode}
+*/
+#define DOWN(key)       KEY_DOWN, (key)
+#define UP(key)         KEY_UP, (key)
+#define TYPE(key)       DOWN(key), UP(key)
+#define WAIT(ms)        WAIT, (ms)
+#define INTERVAL(ms)    INTERVAL, (ms)
+
+/* key down */
+#define D(key)          DOWN(KC_##key)
+/* key up */
+#define U(key)          UP(KC_##key)
+/* key type */
+#define T(key)          TYPE(KC_##key)
+/* wait */
+#define W(ms)           WAIT(ms)
+/* interval */
+#define I(ms)           INTERVAL(ms)
+
+/* for backward comaptibility */
+#define MD(key)         DOWN(KC_##key)
+#define MU(key)         UP(KC_##key)
+
+
+#endif /* ACTION_MACRO_H */
diff --git a/common/action_tapping.c b/common/action_tapping.c
new file mode 100644 (file)
index 0000000..826c233
--- /dev/null
@@ -0,0 +1,376 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+#include "action_layer.h"
+#include "action_tapping.h"
+#include "keycode.h"
+#include "timer.h"
+
+#ifdef DEBUG_ACTION
+#include "debug.h"
+#else
+#include "nodebug.h"
+#endif
+
+#ifndef NO_ACTION_TAPPING
+
+#define IS_TAPPING()            !IS_NOEVENT(tapping_key.event)
+#define IS_TAPPING_PRESSED()    (IS_TAPPING() && tapping_key.event.pressed)
+#define IS_TAPPING_RELEASED()   (IS_TAPPING() && !tapping_key.event.pressed)
+#define IS_TAPPING_KEY(k)       (IS_TAPPING() && KEYEQ(tapping_key.event.key, (k)))
+#define WITHIN_TAPPING_TERM(e)  (TIMER_DIFF_16(e.time, tapping_key.event.time) < TAPPING_TERM)
+
+
+static keyrecord_t tapping_key = {};
+static keyrecord_t waiting_buffer[WAITING_BUFFER_SIZE] = {};
+static uint8_t waiting_buffer_head = 0;
+static uint8_t waiting_buffer_tail = 0;
+
+static bool process_tapping(keyrecord_t *record);
+static bool waiting_buffer_enq(keyrecord_t record);
+static void waiting_buffer_clear(void);
+static bool waiting_buffer_typed(keyevent_t event);
+static bool waiting_buffer_has_anykey_pressed(void);
+static void waiting_buffer_scan_tap(void);
+static void debug_tapping_key(void);
+static void debug_waiting_buffer(void);
+
+
+void action_tapping_process(keyrecord_t record)
+{
+    if (process_tapping(&record)) {
+        if (!IS_NOEVENT(record.event)) {
+            debug("processed: "); debug_record(record); debug("\n");
+        }
+    } else {
+        if (!waiting_buffer_enq(record)) {
+            // clear all in case of overflow.
+            debug("OVERFLOW: CLEAR ALL STATES\n");
+            clear_keyboard();
+            waiting_buffer_clear();
+            tapping_key = (keyrecord_t){};
+        }
+    }
+
+    // process waiting_buffer
+    if (!IS_NOEVENT(record.event) && waiting_buffer_head != waiting_buffer_tail) {
+        debug("---- action_exec: process waiting_buffer -----\n");
+    }
+    for (; waiting_buffer_tail != waiting_buffer_head; waiting_buffer_tail = (waiting_buffer_tail + 1) % WAITING_BUFFER_SIZE) {
+        if (process_tapping(&waiting_buffer[waiting_buffer_tail])) {
+            debug("processed: waiting_buffer["); debug_dec(waiting_buffer_tail); debug("] = ");
+            debug_record(waiting_buffer[waiting_buffer_tail]); debug("\n\n");
+        } else {
+            break;
+        }
+    }
+    if (!IS_NOEVENT(record.event)) {
+        debug("\n");
+    }
+}
+
+
+/* Tapping
+ *
+ * Rule: Tap key is typed(pressed and released) within TAPPING_TERM.
+ *       (without interfering by typing other key)
+ */
+/* return true when key event is processed or consumed. */
+bool process_tapping(keyrecord_t *keyp)
+{
+    keyevent_t event = keyp->event;
+
+    // if tapping
+    if (IS_TAPPING_PRESSED()) {
+        if (WITHIN_TAPPING_TERM(event)) {
+            if (tapping_key.tap.count == 0) {
+                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+                    // first tap!
+                    debug("Tapping: First tap(0->1).\n");
+                    tapping_key.tap.count = 1;
+                    debug_tapping_key();
+                    process_action(&tapping_key);
+
+                    // copy tapping state
+                    keyp->tap = tapping_key.tap;
+                    // enqueue
+                    return false;
+                }
+#if TAPPING_TERM >= 500
+                /* Process a key typed within TAPPING_TERM
+                 * This can register the key before settlement of tapping,
+                 * useful for long TAPPING_TERM but may prevent fast typing.
+                 */
+                else if (IS_RELEASED(event) && waiting_buffer_typed(event)) {
+                    debug("Tapping: End. No tap. Interfered by typing key\n");
+                    process_action(&tapping_key);
+                    tapping_key = (keyrecord_t){};
+                    debug_tapping_key();
+                    // enqueue
+                    return false;
+                }
+#endif
+                /* Process release event of a key pressed before tapping starts
+                 * Without this unexpected repeating will occur with having fast repeating setting
+                 * https://github.com/tmk/tmk_keyboard/issues/60
+                 */
+                else if (IS_RELEASED(event) && !waiting_buffer_typed(event)) {
+                    // Modifier should be retained till end of this tapping.
+                    action_t action = layer_switch_get_action(event.key);
+                    switch (action.kind.id) {
+                        case ACT_LMODS:
+                        case ACT_RMODS:
+                            if (action.key.mods && !action.key.code) return false;
+                            if (IS_MOD(action.key.code)) return false;
+                            break;
+                        case ACT_LMODS_TAP:
+                        case ACT_RMODS_TAP:
+                            if (action.key.mods && keyp->tap.count == 0) return false;
+                            if (IS_MOD(action.key.code)) return false;
+                            break;
+                    }
+                    // Release of key should be process immediately.
+                    debug("Tapping: release event of a key pressed before tapping\n");
+                    process_action(keyp);
+                    return true;
+                }
+                else {
+                    // set interrupted flag when other key preesed during tapping
+                    if (event.pressed) {
+                        tapping_key.tap.interrupted = true;
+                    }
+                    // enqueue 
+                    return false;
+                }
+            }
+            // tap_count > 0
+            else {
+                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+                    debug("Tapping: Tap release("); debug_dec(tapping_key.tap.count); debug(")\n");
+                    keyp->tap = tapping_key.tap;
+                    process_action(keyp);
+                    tapping_key = *keyp;
+                    debug_tapping_key();
+                    return true;
+                }
+                else if (is_tap_key(event.key) && event.pressed) {
+                    if (tapping_key.tap.count > 1) {
+                        debug("Tapping: Start new tap with releasing last tap(>1).\n");
+                        // unregister key
+                        process_action(&(keyrecord_t){
+                                .tap = tapping_key.tap,
+                                .event.key = tapping_key.event.key,
+                                .event.time = event.time,
+                                .event.pressed = false
+                        });
+                    } else {
+                        debug("Tapping: Start while last tap(1).\n");
+                    }
+                    tapping_key = *keyp;
+                    waiting_buffer_scan_tap();
+                    debug_tapping_key();
+                    return true;
+                }
+                else {
+                    if (!IS_NOEVENT(event)) {
+                        debug("Tapping: key event while last tap(>0).\n");
+                    }
+                    process_action(keyp);
+                    return true;
+                }
+            }
+        }
+        // after TAPPING_TERM
+        else {
+            if (tapping_key.tap.count == 0) {
+                debug("Tapping: End. Timeout. Not tap(0): ");
+                debug_event(event); debug("\n");
+                process_action(&tapping_key);
+                tapping_key = (keyrecord_t){};
+                debug_tapping_key();
+                return false;
+            }  else {
+                if (IS_TAPPING_KEY(event.key) && !event.pressed) {
+                    debug("Tapping: End. last timeout tap release(>0).");
+                    keyp->tap = tapping_key.tap;
+                    process_action(keyp);
+                    tapping_key = (keyrecord_t){};
+                    return true;
+                }
+                else if (is_tap_key(event.key) && event.pressed) {
+                    if (tapping_key.tap.count > 1) {
+                        debug("Tapping: Start new tap with releasing last timeout tap(>1).\n");
+                        // unregister key
+                        process_action(&(keyrecord_t){
+                                .tap = tapping_key.tap,
+                                .event.key = tapping_key.event.key,
+                                .event.time = event.time,
+                                .event.pressed = false
+                        });
+                    } else {
+                        debug("Tapping: Start while last timeout tap(1).\n");
+                    }
+                    tapping_key = *keyp;
+                    waiting_buffer_scan_tap();
+                    debug_tapping_key();
+                    return true;
+                }
+                else {
+                    if (!IS_NOEVENT(event)) {
+                        debug("Tapping: key event while last timeout tap(>0).\n");
+                    }
+                    process_action(keyp);
+                    return true;
+                }
+            }
+        }
+    } else if (IS_TAPPING_RELEASED()) {
+        if (WITHIN_TAPPING_TERM(event)) {
+            if (event.pressed) {
+                if (IS_TAPPING_KEY(event.key)) {
+                    if (!tapping_key.tap.interrupted && tapping_key.tap.count > 0) {
+                        // sequential tap.
+                        keyp->tap = tapping_key.tap;
+                        if (keyp->tap.count < 15) keyp->tap.count += 1;
+                        debug("Tapping: Tap press("); debug_dec(keyp->tap.count); debug(")\n");
+                        process_action(keyp);
+                        tapping_key = *keyp;
+                        debug_tapping_key();
+                        return true;
+                    } else {
+                        // FIX: start new tap again
+                        tapping_key = *keyp;
+                        return true;
+                    }
+                } else if (is_tap_key(event.key)) {
+                    // Sequential tap can be interfered with other tap key.
+                    debug("Tapping: Start with interfering other tap.\n");
+                    tapping_key = *keyp;
+                    waiting_buffer_scan_tap();
+                    debug_tapping_key();
+                    return true;
+                } else {
+                    // should none in buffer
+                    // FIX: interrupted when other key is pressed
+                    tapping_key.tap.interrupted = true;
+                    process_action(keyp);
+                    return true;
+                }
+            } else {
+                if (!IS_NOEVENT(event)) debug("Tapping: other key just after tap.\n");
+                process_action(keyp);
+                return true;
+            }
+        } else {
+            // FIX: process_aciton here?
+            // timeout. no sequential tap.
+            debug("Tapping: End(Timeout after releasing last tap): ");
+            debug_event(event); debug("\n");
+            tapping_key = (keyrecord_t){};
+            debug_tapping_key();
+            return false;
+        }
+    }
+    // not tapping state
+    else {
+        if (event.pressed && is_tap_key(event.key)) {
+            debug("Tapping: Start(Press tap key).\n");
+            tapping_key = *keyp;
+            waiting_buffer_scan_tap();
+            debug_tapping_key();
+            return true;
+        } else {
+            process_action(keyp);
+            return true;
+        }
+    }
+}
+
+
+/*
+ * Waiting buffer
+ */
+bool waiting_buffer_enq(keyrecord_t record)
+{
+    if (IS_NOEVENT(record.event)) {
+        return true;
+    }
+
+    if ((waiting_buffer_head + 1) % WAITING_BUFFER_SIZE == waiting_buffer_tail) {
+        debug("waiting_buffer_enq: Over flow.\n");
+        return false;
+    }
+
+    waiting_buffer[waiting_buffer_head] = record;
+    waiting_buffer_head = (waiting_buffer_head + 1) % WAITING_BUFFER_SIZE;
+
+    debug("waiting_buffer_enq: "); debug_waiting_buffer();
+    return true;
+}
+
+void waiting_buffer_clear(void)
+{
+    waiting_buffer_head = 0;
+    waiting_buffer_tail = 0;
+}
+
+bool waiting_buffer_typed(keyevent_t event)
+{
+    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+        if (KEYEQ(event.key, waiting_buffer[i].event.key) && event.pressed !=  waiting_buffer[i].event.pressed) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool waiting_buffer_has_anykey_pressed(void)
+{
+    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+        if (waiting_buffer[i].event.pressed) return true;
+    }
+    return false;
+}
+
+/* scan buffer for tapping */
+void waiting_buffer_scan_tap(void)
+{
+    // tapping already is settled
+    if (tapping_key.tap.count > 0) return;
+    // invalid state: tapping_key released && tap.count == 0
+    if (!tapping_key.event.pressed) return;
+
+    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+        if (IS_TAPPING_KEY(waiting_buffer[i].event.key) &&
+                !waiting_buffer[i].event.pressed &&
+                WITHIN_TAPPING_TERM(waiting_buffer[i].event)) {
+            tapping_key.tap.count = 1;
+            waiting_buffer[i].tap.count = 1;
+            process_action(&tapping_key);
+
+            debug("waiting_buffer_scan_tap: found at ["); debug_dec(i); debug("]\n");
+            debug_waiting_buffer();
+            return;
+        }
+    }
+}
+
+
+/*
+ * debug print
+ */
+static void debug_tapping_key(void)
+{
+    debug("TAPPING_KEY="); debug_record(tapping_key); debug("\n");
+}
+
+static void debug_waiting_buffer(void)
+{
+    debug("{ ");
+    for (uint8_t i = waiting_buffer_tail; i != waiting_buffer_head; i = (i + 1) % WAITING_BUFFER_SIZE) {
+        debug("["); debug_dec(i); debug("]="); debug_record(waiting_buffer[i]); debug(" ");
+    }
+    debug("}\n");
+}
+
+#endif
diff --git a/common/action_tapping.h b/common/action_tapping.h
new file mode 100644 (file)
index 0000000..9b42d50
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_TAPPING_H
+#define ACTION_TAPPING_H
+
+
+
+/* period of tapping(ms) */
+#ifndef TAPPING_TERM
+#define TAPPING_TERM    200
+#endif
+
+/* tap count needed for toggling a feature */
+#ifndef TAPPING_TOGGLE
+#define TAPPING_TOGGLE  5
+#endif
+
+#define WAITING_BUFFER_SIZE 8
+
+
+#ifndef NO_ACTION_TAPPING
+void action_tapping_process(keyrecord_t record);
+#endif
+
+#endif
diff --git a/common/action_util.c b/common/action_util.c
new file mode 100644 (file)
index 0000000..dbee630
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "host.h"
+#include "report.h"
+#include "debug.h"
+#include "action_util.h"
+#include "timer.h"
+
+static inline void add_key_byte(uint8_t code);
+static inline void del_key_byte(uint8_t code);
+#ifdef NKRO_ENABLE
+static inline void add_key_bit(uint8_t code);
+static inline void del_key_bit(uint8_t code);
+#endif
+
+static uint8_t real_mods = 0;
+static uint8_t weak_mods = 0;
+
+#ifdef USB_6KRO_ENABLE
+#define RO_ADD(a, b) ((a + b) % KEYBOARD_REPORT_KEYS)
+#define RO_SUB(a, b) ((a - b + KEYBOARD_REPORT_KEYS) % KEYBOARD_REPORT_KEYS)
+#define RO_INC(a) RO_ADD(a, 1)
+#define RO_DEC(a) RO_SUB(a, 1)
+static int8_t cb_head = 0;
+static int8_t cb_tail = 0;
+static int8_t cb_count = 0;
+#endif
+
+// TODO: pointer variable is not needed
+//report_keyboard_t keyboard_report = {};
+report_keyboard_t *keyboard_report = &(report_keyboard_t){};
+
+#ifndef NO_ACTION_ONESHOT
+static int8_t oneshot_mods = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+static int16_t oneshot_time = 0;
+#endif
+#endif
+
+
+void send_keyboard_report(void) {
+    keyboard_report->mods  = real_mods;
+    keyboard_report->mods |= weak_mods;
+#ifndef NO_ACTION_ONESHOT
+    if (oneshot_mods) {
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+        if (TIMER_DIFF_16(timer_read(), oneshot_time) >= ONESHOT_TIMEOUT) {
+            dprintf("Oneshot: timeout\n");
+            clear_oneshot_mods();
+        }
+#endif
+        keyboard_report->mods |= oneshot_mods;
+        if (has_anykey()) {
+            clear_oneshot_mods();
+        }
+    }
+#endif
+    host_keyboard_send(keyboard_report);
+}
+
+/* key */
+void add_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+    if (keyboard_nkro) {
+        add_key_bit(key);
+        return;
+    }
+#endif
+    add_key_byte(key);
+}
+
+void del_key(uint8_t key)
+{
+#ifdef NKRO_ENABLE
+    if (keyboard_nkro) {
+        del_key_bit(key);
+        return;
+    }
+#endif
+    del_key_byte(key);
+}
+
+void clear_keys(void)
+{
+    // not clear mods
+    for (int8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
+        keyboard_report->raw[i] = 0;
+    }
+}
+
+
+/* modifier */
+uint8_t get_mods(void) { return real_mods; }
+void add_mods(uint8_t mods) { real_mods |= mods; }
+void del_mods(uint8_t mods) { real_mods &= ~mods; }
+void set_mods(uint8_t mods) { real_mods = mods; }
+void clear_mods(void) { real_mods = 0; }
+
+/* weak modifier */
+uint8_t get_weak_mods(void) { return weak_mods; }
+void add_weak_mods(uint8_t mods) { weak_mods |= mods; }
+void del_weak_mods(uint8_t mods) { weak_mods &= ~mods; }
+void set_weak_mods(uint8_t mods) { weak_mods = mods; }
+void clear_weak_mods(void) { weak_mods = 0; }
+
+/* Oneshot modifier */
+#ifndef NO_ACTION_ONESHOT
+void set_oneshot_mods(uint8_t mods)
+{
+    oneshot_mods = mods;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+    oneshot_time = timer_read();
+#endif
+}
+void clear_oneshot_mods(void)
+{
+    oneshot_mods = 0;
+#if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
+    oneshot_time = 0;
+#endif
+}
+#endif
+
+
+
+
+/*
+ * inspect keyboard state
+ */
+uint8_t has_anykey(void)
+{
+    uint8_t cnt = 0;
+    for (uint8_t i = 1; i < KEYBOARD_REPORT_SIZE; i++) {
+        if (keyboard_report->raw[i])
+            cnt++;
+    }
+    return cnt;
+}
+
+uint8_t has_anymod(void)
+{
+    return bitpop(real_mods);
+}
+
+uint8_t get_first_key(void)
+{
+#ifdef NKRO_ENABLE
+    if (keyboard_nkro) {
+        uint8_t i = 0;
+        for (; i < KEYBOARD_REPORT_BITS && !keyboard_report->nkro.bits[i]; i++)
+            ;
+        return i<<3 | biton(keyboard_report->nkro.bits[i]);
+    }
+#endif
+#ifdef USB_6KRO_ENABLE
+    uint8_t i = cb_head;
+    do {
+        if (keyboard_report->keys[i] != 0) {
+            break;
+        }
+        i = RO_INC(i);
+    } while (i != cb_tail);
+    return keyboard_report->keys[i];
+#else
+    return keyboard_report->keys[0];
+#endif
+}
+
+
+
+/* local functions */
+static inline void add_key_byte(uint8_t code)
+{
+#ifdef USB_6KRO_ENABLE
+    int8_t i = cb_head;
+    int8_t empty = -1;
+    if (cb_count) {
+        do {
+            if (keyboard_report->keys[i] == code) {
+                return;
+            }
+            if (empty == -1 && keyboard_report->keys[i] == 0) {
+                empty = i;
+            }
+            i = RO_INC(i);
+        } while (i != cb_tail);
+        if (i == cb_tail) {
+            if (cb_tail == cb_head) {
+                // buffer is full
+                if (empty == -1) {
+                    // pop head when has no empty space
+                    cb_head = RO_INC(cb_head);
+                    cb_count--;
+                }
+                else {
+                    // left shift when has empty space
+                    uint8_t offset = 1;
+                    i = RO_INC(empty);
+                    do {
+                        if (keyboard_report->keys[i] != 0) {
+                            keyboard_report->keys[empty] = keyboard_report->keys[i];
+                            keyboard_report->keys[i] = 0;
+                            empty = RO_INC(empty);
+                        }
+                        else {
+                            offset++;
+                        }
+                        i = RO_INC(i);
+                    } while (i != cb_tail);
+                    cb_tail = RO_SUB(cb_tail, offset);
+                }
+            }
+        }
+    }
+    // add to tail
+    keyboard_report->keys[cb_tail] = code;
+    cb_tail = RO_INC(cb_tail);
+    cb_count++;
+#else
+    int8_t i = 0;
+    int8_t empty = -1;
+    for (; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (keyboard_report->keys[i] == code) {
+            break;
+        }
+        if (empty == -1 && keyboard_report->keys[i] == 0) {
+            empty = i;
+        }
+    }
+    if (i == KEYBOARD_REPORT_KEYS) {
+        if (empty != -1) {
+            keyboard_report->keys[empty] = code;
+        }
+    }
+#endif
+}
+
+static inline void del_key_byte(uint8_t code)
+{
+#ifdef USB_6KRO_ENABLE
+    uint8_t i = cb_head;
+    if (cb_count) {
+        do {
+            if (keyboard_report->keys[i] == code) {
+                keyboard_report->keys[i] = 0;
+                cb_count--;
+                if (cb_count == 0) {
+                    // reset head and tail
+                    cb_tail = cb_head = 0;
+                }
+                if (i == RO_DEC(cb_tail)) {
+                    // left shift when next to tail
+                    do {
+                        cb_tail = RO_DEC(cb_tail);
+                        if (keyboard_report->keys[RO_DEC(cb_tail)] != 0) {
+                            break;
+                        }
+                    } while (cb_tail != cb_head);
+                }
+                break;
+            }
+            i = RO_INC(i);
+        } while (i != cb_tail);
+    }
+#else
+    for (uint8_t i = 0; i < KEYBOARD_REPORT_KEYS; i++) {
+        if (keyboard_report->keys[i] == code) {
+            keyboard_report->keys[i] = 0;
+        }
+    }
+#endif
+}
+
+#ifdef NKRO_ENABLE
+static inline void add_key_bit(uint8_t code)
+{
+    if ((code>>3) < KEYBOARD_REPORT_BITS) {
+        keyboard_report->nkro.bits[code>>3] |= 1<<(code&7);
+    } else {
+        dprintf("add_key_bit: can't add: %02X\n", code);
+    }
+}
+
+static inline void del_key_bit(uint8_t code)
+{
+    if ((code>>3) < KEYBOARD_REPORT_BITS) {
+        keyboard_report->nkro.bits[code>>3] &= ~(1<<(code&7));
+    } else {
+        dprintf("del_key_bit: can't del: %02X\n", code);
+    }
+}
+#endif
diff --git a/common/action_util.h b/common/action_util.h
new file mode 100644 (file)
index 0000000..a955638
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef ACTION_UTIL_H
+#define ACTION_UTIL_H
+
+#include <stdint.h>
+#include "report.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern report_keyboard_t *keyboard_report;
+
+void send_keyboard_report(void);
+
+/* key */
+void add_key(uint8_t key);
+void del_key(uint8_t key);
+void clear_keys(void);
+
+/* modifier */
+uint8_t get_mods(void);
+void add_mods(uint8_t mods);
+void del_mods(uint8_t mods);
+void set_mods(uint8_t mods);
+void clear_mods(void);
+
+/* weak modifier */
+uint8_t get_weak_mods(void);
+void add_weak_mods(uint8_t mods);
+void del_weak_mods(uint8_t mods);
+void set_weak_mods(uint8_t mods);
+void clear_weak_mods(void);
+
+/* oneshot modifier */
+void set_oneshot_mods(uint8_t mods);
+void clear_oneshot_mods(void);
+void oneshot_toggle(void);
+void oneshot_enable(void);
+void oneshot_disable(void);
+
+/* inspect */
+uint8_t has_anykey(void);
+uint8_t has_anymod(void);
+uint8_t get_first_key(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/avr/bootloader.c b/common/avr/bootloader.c
new file mode 100644 (file)
index 0000000..cda295b
--- /dev/null
@@ -0,0 +1,148 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <util/delay.h>
+#include "bootloader.h"
+
+#ifdef PROTOCOL_LUFA
+#include <LUFA/Drivers/USB/USB.h>
+#endif
+
+
+/* Boot Section Size in *BYTEs*
+ *   Teensy   halfKay    512
+ *   Teensy++ halfKay    1024
+ *   Atmel DFU loader    4096
+ *   LUFA bootloader     4096
+ *   USBaspLoader        2048
+ */
+#ifndef BOOTLOADER_SIZE
+#warning To use bootloader_jump() you need to define BOOTLOADER_SIZE in config.h.
+#define BOOTLOADER_SIZE     4096
+#endif
+
+#define FLASH_SIZE          (FLASHEND + 1L)
+#define BOOTLOADER_START    (FLASH_SIZE - BOOTLOADER_SIZE)
+
+
+/* 
+ * Entering the Bootloader via Software 
+ * http://www.fourwalledcubicle.com/files/LUFA/Doc/120730/html/_page__software_bootloader_start.html
+ */
+#define BOOTLOADER_RESET_KEY 0xB007B007
+uint32_t reset_key  __attribute__ ((section (".noinit")));
+
+/* initialize MCU status by watchdog reset */
+void bootloader_jump(void) {
+#ifdef PROTOCOL_LUFA
+    USB_Disable();
+    cli();
+    _delay_ms(2000);
+#endif
+
+#ifdef PROTOCOL_PJRC
+    cli();
+    UDCON = 1;
+    USBCON = (1<<FRZCLK);
+    UCSR1B = 0;
+    _delay_ms(5);
+#endif
+
+    // watchdog reset
+    reset_key = BOOTLOADER_RESET_KEY;
+    wdt_enable(WDTO_250MS);
+    for (;;);
+}
+
+
+/* this runs before main() */
+void bootloader_jump_after_watchdog_reset(void) __attribute__ ((used, naked, section (".init3")));
+void bootloader_jump_after_watchdog_reset(void)
+{
+    if ((MCUSR & (1<<WDRF)) && reset_key == BOOTLOADER_RESET_KEY) {
+        reset_key = 0;
+
+        // My custom USBasploader requires this to come up.
+        MCUSR = 0;
+
+        // Seems like Teensy halfkay loader requires clearing WDRF and disabling watchdog.
+        MCUSR &= ~(1<<WDRF);
+        wdt_disable();
+
+        // This is compled into 'icall', address should be in word unit, not byte.
+        ((void (*)(void))(BOOTLOADER_START/2))();
+    }
+}
+
+
+#if 0
+/* Jumping To The Bootloader
+ * http://www.pjrc.com/teensy/jump_to_bootloader.html
+ * 
+ * This method doen't work when using LUFA. idk why.
+ * - needs to initialize more regisers or interrupt setting?
+ */
+void bootloader_jump(void) {
+#ifdef PROTOCOL_LUFA
+    USB_Disable();
+    cli();
+    _delay_ms(2000);
+#endif
+
+#ifdef PROTOCOL_PJRC
+    cli();
+    UDCON = 1;
+    USBCON = (1<<FRZCLK);
+    UCSR1B = 0;
+    _delay_ms(5);
+#endif
+
+    /*
+     * Initialize
+     */
+#if defined(__AVR_AT90USB162__)
+    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0;
+    TIMSK0 = 0; TIMSK1 = 0; UCSR1B = 0;
+    DDRB = 0; DDRC = 0; DDRD = 0;
+    PORTB = 0; PORTC = 0; PORTD = 0;
+#elif defined(__AVR_ATmega32U4__)
+    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+    TIMSK0 = 0; TIMSK1 = 0; TIMSK3 = 0; TIMSK4 = 0; UCSR1B = 0; TWCR = 0;
+    DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0; TWCR = 0;
+    PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#elif defined(__AVR_AT90USB646__)
+    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+    DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+    PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#elif defined(__AVR_AT90USB1286__)
+    EIMSK = 0; PCICR = 0; SPCR = 0; ACSR = 0; EECR = 0; ADCSRA = 0;
+    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0; TIMSK3 = 0; UCSR1B = 0; TWCR = 0;
+    DDRA = 0; DDRB = 0; DDRC = 0; DDRD = 0; DDRE = 0; DDRF = 0;
+    PORTA = 0; PORTB = 0; PORTC = 0; PORTD = 0; PORTE = 0; PORTF = 0;
+#endif
+
+    /*
+     * USBaspLoader
+     */
+#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
+    // This makes custom USBasploader come up.
+    MCUSR = 0;
+
+    // initialize ports
+    PORTB = 0; PORTC= 0; PORTD = 0;
+    DDRB = 0; DDRC= 0; DDRD = 0;
+
+    // disable interrupts
+    EIMSK = 0; EECR = 0; SPCR = 0;
+    ACSR = 0; SPMCSR = 0; WDTCSR = 0; PCICR = 0;
+    TIMSK0 = 0; TIMSK1 = 0; TIMSK2 = 0;
+    ADCSRA = 0; TWCR = 0; UCSR0B = 0;
+#endif
+
+    // This is compled into 'icall', address should be in word unit, not byte.
+    ((void (*)(void))(BOOTLOADER_START/2))();
+}
+#endif
diff --git a/common/avr/eeconfig.c b/common/avr/eeconfig.c
new file mode 100644 (file)
index 0000000..5bd47dc
--- /dev/null
@@ -0,0 +1,45 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/eeprom.h>
+#include "eeconfig.h"
+
+void eeconfig_init(void)
+{
+    eeprom_write_word(EECONFIG_MAGIC,          EECONFIG_MAGIC_NUMBER);
+    eeprom_write_byte(EECONFIG_DEBUG,          0);
+    eeprom_write_byte(EECONFIG_DEFAULT_LAYER,  0);
+    eeprom_write_byte(EECONFIG_KEYMAP,         0);
+    eeprom_write_byte(EECONFIG_MOUSEKEY_ACCEL, 0);
+#ifdef BACKLIGHT_ENABLE
+    eeprom_write_byte(EECONFIG_BACKLIGHT,      0);
+#endif
+}
+
+void eeconfig_enable(void)
+{
+    eeprom_write_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER);
+}
+
+void eeconfig_disable(void)
+{
+    eeprom_write_word(EECONFIG_MAGIC, 0xFFFF);
+}
+
+bool eeconfig_is_enabled(void)
+{
+    return (eeprom_read_word(EECONFIG_MAGIC) == EECONFIG_MAGIC_NUMBER);
+}
+
+uint8_t eeconfig_read_debug(void)      { return eeprom_read_byte(EECONFIG_DEBUG); }
+void eeconfig_write_debug(uint8_t val) { eeprom_write_byte(EECONFIG_DEBUG, val); }
+
+uint8_t eeconfig_read_default_layer(void)      { return eeprom_read_byte(EECONFIG_DEFAULT_LAYER); }
+void eeconfig_write_default_layer(uint8_t val) { eeprom_write_byte(EECONFIG_DEFAULT_LAYER, val); }
+
+uint8_t eeconfig_read_keymap(void)      { return eeprom_read_byte(EECONFIG_KEYMAP); }
+void eeconfig_write_keymap(uint8_t val) { eeprom_write_byte(EECONFIG_KEYMAP, val); }
+
+#ifdef BACKLIGHT_ENABLE
+uint8_t eeconfig_read_backlight(void)      { return eeprom_read_byte(EECONFIG_BACKLIGHT); }
+void eeconfig_write_backlight(uint8_t val) { eeprom_write_byte(EECONFIG_BACKLIGHT, val); }
+#endif
diff --git a/common/avr/suspend.c b/common/avr/suspend.c
new file mode 100644 (file)
index 0000000..80243f0
--- /dev/null
@@ -0,0 +1,122 @@
+#include <stdbool.h>
+#include <avr/sleep.h>
+#include <avr/wdt.h>
+#include <avr/interrupt.h>
+#include "matrix.h"
+#include "action.h"
+#include "backlight.h"
+#include "suspend_avr.h"
+#include "suspend.h"
+#include "timer.h"
+#ifdef PROTOCOL_LUFA
+#include "lufa.h"
+#endif
+
+
+#define wdt_intr_enable(value)   \
+__asm__ __volatile__ (  \
+    "in __tmp_reg__,__SREG__" "\n\t"    \
+    "cli" "\n\t"    \
+    "wdr" "\n\t"    \
+    "sts %0,%1" "\n\t"  \
+    "out __SREG__,__tmp_reg__" "\n\t"   \
+    "sts %0,%2" "\n\t" \
+    : /* no outputs */  \
+    : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+    "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+    "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+        _BV(WDIE) | (value & 0x07)) ) \
+    : "r0"  \
+)
+
+
+void suspend_idle(uint8_t time)
+{
+    cli();
+    set_sleep_mode(SLEEP_MODE_IDLE);
+    sleep_enable();
+    sei();
+    sleep_cpu();
+    sleep_disable();
+}
+
+/* Power down MCU with watchdog timer
+ * wdto: watchdog timer timeout defined in <avr/wdt.h>
+ *          WDTO_15MS
+ *          WDTO_30MS
+ *          WDTO_60MS
+ *          WDTO_120MS
+ *          WDTO_250MS
+ *          WDTO_500MS
+ *          WDTO_1S
+ *          WDTO_2S
+ *          WDTO_4S
+ *          WDTO_8S
+ */
+static uint8_t wdt_timeout = 0;
+static void power_down(uint8_t wdto)
+{
+#ifdef PROTOCOL_LUFA
+    if (USB_DeviceState == DEVICE_STATE_Configured) return;
+#endif
+    wdt_timeout = wdto;
+
+    // Watchdog Interrupt Mode
+    wdt_intr_enable(wdto);
+
+    // TODO: more power saving
+    // See PicoPower application note
+    // - I/O port input with pullup
+    // - prescale clock
+    // - BOD disable
+    // - Power Reduction Register PRR
+    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
+    sleep_enable();
+    sei();
+    sleep_cpu();
+    sleep_disable();
+
+    // Disable watchdog after sleep
+    wdt_disable();
+}
+
+void suspend_power_down(void)
+{
+    power_down(WDTO_15MS);
+}
+
+bool suspend_wakeup_condition(void)
+{
+    matrix_power_up();
+    matrix_scan();
+    matrix_power_down();
+    for (uint8_t r = 0; r < MATRIX_ROWS; r++) {
+        if (matrix_get_row(r)) return true;
+    }
+    return false;
+}
+
+// run immediately after wakeup
+void suspend_wakeup_init(void)
+{
+    // clear keyboard state
+    clear_keyboard();
+#ifdef BACKLIGHT_ENABLE
+    backlight_init();
+#endif
+}
+
+#ifndef NO_SUSPEND_POWER_DOWN
+/* watchdog timeout */
+ISR(WDT_vect)
+{
+    // compensate timer for sleep
+    switch (wdt_timeout) {
+        case WDTO_15MS:
+            timer_count += 15 + 2;  // WDTO_15MS + 2(from observation)
+            break;
+        default:
+            ;
+    }
+}
+#endif
diff --git a/common/avr/suspend_avr.h b/common/avr/suspend_avr.h
new file mode 100644 (file)
index 0000000..357102d
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef SUSPEND_AVR_H
+#define SUSPEND_AVR_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <avr/sleep.h>
+#include <avr/wdt.h>
+#include <avr/interrupt.h>
+
+
+#define wdt_intr_enable(value)   \
+__asm__ __volatile__ (  \
+    "in __tmp_reg__,__SREG__" "\n\t"    \
+    "cli" "\n\t"    \
+    "wdr" "\n\t"    \
+    "sts %0,%1" "\n\t"  \
+    "out __SREG__,__tmp_reg__" "\n\t"   \
+    "sts %0,%2" "\n\t" \
+    : /* no outputs */  \
+    : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)), \
+    "r" (_BV(_WD_CHANGE_BIT) | _BV(WDE)), \
+    "r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) | \
+        _BV(WDIE) | (value & 0x07)) ) \
+    : "r0"  \
+)
+
+#endif
diff --git a/common/avr/timer.c b/common/avr/timer.c
new file mode 100644 (file)
index 0000000..292b41c
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <stdint.h>
+#include "timer_avr.h"
+#include "timer.h"
+
+
+// counter resolution 1ms
+// NOTE: union { uint32_t timer32; struct { uint16_t dummy; uint16_t timer16; }}
+volatile uint32_t timer_count = 0;
+
+void timer_init(void)
+{
+    // Timer0 CTC mode
+    TCCR0A = 0x02;
+
+#if TIMER_PRESCALER == 1
+    TCCR0B = 0x01;
+#elif TIMER_PRESCALER == 8
+    TCCR0B = 0x02;
+#elif TIMER_PRESCALER == 64
+    TCCR0B = 0x03;
+#elif TIMER_PRESCALER == 256
+    TCCR0B = 0x04;
+#elif TIMER_PRESCALER == 1024
+    TCCR0B = 0x05;
+#else
+#   error "Timer prescaler value is NOT vaild."
+#endif
+
+    OCR0A = TIMER_RAW_TOP;
+    TIMSK0 = (1<<OCIE0A);
+}
+
+inline
+void timer_clear(void)
+{
+    uint8_t sreg = SREG;
+    cli();
+    timer_count = 0;
+    SREG = sreg;
+}
+
+inline
+uint16_t timer_read(void)
+{
+    uint32_t t;
+
+    uint8_t sreg = SREG;
+    cli();
+    t = timer_count;
+    SREG = sreg;
+
+    return (t & 0xFFFF);
+}
+
+inline
+uint32_t timer_read32(void)
+{
+    uint32_t t;
+
+    uint8_t sreg = SREG;
+    cli();
+    t = timer_count;
+    SREG = sreg;
+
+    return t;
+}
+
+inline
+uint16_t timer_elapsed(uint16_t last)
+{
+    uint32_t t;
+
+    uint8_t sreg = SREG;
+    cli();
+    t = timer_count;
+    SREG = sreg;
+
+    return TIMER_DIFF_16((t & 0xFFFF), last);
+}
+
+inline
+uint32_t timer_elapsed32(uint32_t last)
+{
+    uint32_t t;
+
+    uint8_t sreg = SREG;
+    cli();
+    t = timer_count;
+    SREG = sreg;
+
+    return TIMER_DIFF_32(t, last);
+}
+
+// excecuted once per 1ms.(excess for just timer count?)
+ISR(TIMER0_COMPA_vect)
+{
+    timer_count++;
+}
diff --git a/common/avr/timer_avr.h b/common/avr/timer_avr.h
new file mode 100644 (file)
index 0000000..0e85eb1
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef TIMER_AVR_H
+#define TIMER_AVR_H 1
+
+#include <stdint.h>
+
+#ifndef TIMER_PRESCALER
+#   if F_CPU > 16000000
+#       define TIMER_PRESCALER      256
+#   elif F_CPU > 2000000
+#       define TIMER_PRESCALER      64
+#   elif F_CPU > 250000
+#       define TIMER_PRESCALER      8
+#   else
+#       define TIMER_PRESCALER      1
+#   endif
+#endif
+#define TIMER_RAW_FREQ      (F_CPU/TIMER_PRESCALER)
+#define TIMER_RAW           TCNT0
+#define TIMER_RAW_TOP       (TIMER_RAW_FREQ/1000)
+
+#if (TIMER_RAW_TOP > 255)
+#   error "Timer0 can't count 1ms at this clock freq. Use larger prescaler."
+#endif
+
+#endif
diff --git a/common/avr/xprintf.S b/common/avr/xprintf.S
new file mode 100644 (file)
index 0000000..0cec70c
--- /dev/null
@@ -0,0 +1,500 @@
+;---------------------------------------------------------------------------;\r
+; Extended itoa, puts, printf and atoi                     (C)ChaN, 2011\r
+;---------------------------------------------------------------------------;\r
+\r
+                               // Base size is 152 bytes\r
+#define        CR_CRLF         0       // Convert \n to \r\n (+10 bytes)\r
+#define USE_XPRINTF    1       // Enable xprintf function (+194 bytes)\r
+#define USE_XSPRINTF   0       // Add xsprintf function (+78 bytes)\r
+#define USE_XFPRINTF   0       // Add xfprintf function (+54 bytes)\r
+#define USE_XATOI      0       // Enable xatoi function (+182 bytes)\r
+\r
+\r
+#if FLASHEND > 0x1FFFF\r
+#error xitoa module does not support 256K devices\r
+#endif\r
+\r
+.nolist\r
+#include <avr/io.h>    // Include device specific definitions.\r
+.list\r
+\r
+#ifdef SPM_PAGESIZE    // Recent devices have "lpm Rd,Z+" and "movw".\r
+.macro _LPMI   reg\r
+       lpm     \reg, Z+\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       movw    \dl, \sl\r
+.endm\r
+#else                  // Earlier devices do not have "lpm Rd,Z+" nor "movw".\r
+.macro _LPMI   reg\r
+       lpm\r
+       mov     \reg, r0\r
+       adiw    ZL, 1\r
+.endm\r
+.macro _MOVW   dh,dl, sh,sl\r
+       mov     \dl, \sl\r
+       mov     \dh, \sh\r
+.endm\r
+#endif\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Stub function to forward to user output function\r
+;\r
+;Prototype: void xputc (char chr       // a character to be output\r
+;                      );\r
+;Size: 12/12 words\r
+\r
+.section .bss\r
+.global xfunc_out      ; xfunc_out must be initialized before using this module.\r
+xfunc_out:     .ds.w   1\r
+.section .text\r
+\r
+\r
+.func xputc\r
+.global xputc\r
+xputc:\r
+#if CR_CRLF\r
+       cpi     r24, 10         ;LF --> CRLF\r
+       brne    1f              ;\r
+       ldi     r24, 13         ;\r
+       rcall   1f              ;\r
+       ldi     r24, 10         ;/\r
+1:\r
+#endif\r
+       push    ZH\r
+       push    ZL\r
+       lds     ZL, xfunc_out+0 ;Pointer to the registered output function.\r
+       lds     ZH, xfunc_out+1 ;/\r
+       sbiw    ZL, 0           ;Skip if null\r
+       breq    2f              ;/\r
+       icall\r
+2:     pop     ZL\r
+       pop     ZH\r
+       ret\r
+.endfunc\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Direct ROM string output\r
+;\r
+;Prototype: void xputs (const char *str_p // rom string to be output\r
+;                      );\r
+\r
+.func xputs\r
+.global xputs\r
+xputs:\r
+       _MOVW   ZH,ZL, r25,r24  ; Z = pointer to rom string\r
+1:     _LPMI   r24\r
+       cpi     r24, 0\r
+       breq    2f\r
+       rcall   xputc\r
+       rjmp    1b\r
+2:     ret\r
+.endfunc\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Extended direct numeral string output (32bit version)\r
+;\r
+;Prototype: void xitoa (long value,    // value to be output\r
+;                       char radix,    // radix\r
+;                       char width);   // minimum width\r
+;\r
+\r
+.func xitoa\r
+.global xitoa\r
+xitoa:\r
+                               ;r25:r22 = value, r20 = base, r18 = digits\r
+       clr     r31             ;r31 = stack level\r
+       ldi     r30, ' '        ;r30 = sign\r
+       ldi     r19, ' '        ;r19 = filler\r
+       sbrs    r20, 7          ;When base indicates signd format and the value\r
+       rjmp    0f              ;is minus, add a '-'.\r
+       neg     r20             ;\r
+       sbrs    r25, 7          ;\r
+       rjmp    0f              ;\r
+       ldi     r30, '-'        ;\r
+       com     r22             ;\r
+       com     r23             ;\r
+       com     r24             ;\r
+       com     r25             ;\r
+       adc     r22, r1         ;\r
+       adc     r23, r1         ;\r
+       adc     r24, r1         ;\r
+       adc     r25, r1         ;/\r
+0:     sbrs    r18, 7          ;When digits indicates zero filled,\r
+       rjmp    1f              ;filler is '0'.\r
+       neg     r18             ;\r
+       ldi     r19, '0'        ;/\r
+                               ;----- string conversion loop\r
+1:     ldi     r21, 32         ;r26 = r25:r22 % r20\r
+       clr     r26             ;r25:r22 /= r20\r
+2:     lsl     r22             ;\r
+       rol     r23             ;\r
+       rol     r24             ;\r
+       rol     r25             ;\r
+       rol     r26             ;\r
+       cp      r26, r20        ;\r
+       brcs    3f              ;\r
+       sub     r26, r20        ;\r
+       inc     r22             ;\r
+3:     dec     r21             ;\r
+       brne    2b              ;/\r
+       cpi     r26, 10         ;r26 is a numeral digit '0'-'F'\r
+       brcs    4f              ;\r
+       subi    r26, -7         ;\r
+4:     subi    r26, -'0'       ;/\r
+       push    r26             ;Stack it\r
+       inc     r31             ;/\r
+       cp      r22, r1         ;Repeat until r25:r22 gets zero\r
+       cpc     r23, r1         ;\r
+       cpc     r24, r1         ;\r
+       cpc     r25, r1         ;\r
+       brne    1b              ;/\r
+\r
+       cpi     r30, '-'        ;Minus sign if needed\r
+       brne    5f              ;\r
+       push    r30             ;\r
+       inc     r31             ;/\r
+5:     cp      r31, r18        ;Filler\r
+       brcc    6f              ;\r
+       push    r19             ;\r
+       inc     r31             ;\r
+       rjmp    5b              ;/\r
+\r
+6:     pop     r24             ;Flush stacked digits and exit\r
+       rcall   xputc           ;\r
+       dec     r31             ;\r
+       brne    6b              ;/\r
+\r
+       ret\r
+.endfunc\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------;\r
+; Formatted string output (16/32bit version)\r
+;\r
+;Prototype:\r
+; void __xprintf (const char *format_p, ...);\r
+; void __xsprintf(char*, const char *format_p, ...);\r
+; void __xfprintf(void(*func)(char), const char *format_p, ...);\r
+;\r
+\r
+#if USE_XPRINTF\r
+\r
+.func xvprintf\r
+xvprintf:\r
+       ld      ZL, Y+          ;Z = pointer to format string\r
+       ld      ZH, Y+          ;/\r
+\r
+0:     _LPMI   r24             ;Get a format char\r
+       cpi     r24, 0          ;End of format string?\r
+       breq    90f             ;/\r
+       cpi     r24, '%'        ;Is format?\r
+       breq    20f             ;/\r
+1:     rcall   xputc           ;Put a normal character\r
+       rjmp    0b              ;/\r
+90:    ret\r
+\r
+20:    ldi     r18, 0          ;r18: digits\r
+       clt                     ;T: filler\r
+       _LPMI   r21             ;Get flags\r
+       cpi     r21, '%'        ;Is a %?\r
+       breq    1b              ;/\r
+       cpi     r21, '0'        ;Zero filled?\r
+       brne    23f             ;\r
+       set                     ;/\r
+22:    _LPMI   r21             ;Get width\r
+23:    cpi     r21, '9'+1      ;\r
+       brcc    24f             ;\r
+       subi    r21, '0'        ;\r
+       brcs    90b             ;\r
+       lsl     r18             ;\r
+       mov     r0, r18         ;\r
+       lsl     r18             ;\r
+       lsl     r18             ;\r
+       add     r18, r0         ;\r
+       add     r18, r21        ;\r
+       rjmp    22b             ;/\r
+\r
+24:    brtc    25f             ;get value (low word)\r
+       neg     r18             ;\r
+25:    ld      r24, Y+         ;\r
+       ld      r25, Y+         ;/\r
+       cpi     r21, 'c'        ;Is type character?\r
+       breq    1b              ;/\r
+       cpi     r21, 's'        ;Is type RAM string?\r
+       breq    50f             ;/\r
+       cpi     r21, 'S'        ;Is type ROM string?\r
+       breq    60f             ;/\r
+       _MOVW   r23,r22,r25,r24 ;r25:r22 = value\r
+       clr     r24             ;\r
+       clr     r25             ;\r
+       clt                     ;/\r
+       cpi     r21, 'l'        ;Is long int?\r
+       brne    26f             ;\r
+       ld      r24, Y+         ;get value (high word)\r
+       ld      r25, Y+         ;\r
+       set                     ;\r
+       _LPMI   r21             ;/\r
+26:    cpi     r21, 'd'        ;Is type signed decimal?\r
+       brne    27f             ;/\r
+       ldi     r20, -10        ;\r
+       brts    40f             ;\r
+       sbrs    r23, 7          ;\r
+       rjmp    40f             ;\r
+       ldi     r24, -1         ;\r
+       ldi     r25, -1         ;\r
+       rjmp    40f             ;/\r
+27:    cpi     r21, 'u'        ;Is type unsigned decimal?\r
+       ldi     r20, 10         ;\r
+       breq    40f             ;/\r
+       cpi     r21, 'X'        ;Is type hexdecimal?\r
+       ldi     r20, 16         ;\r
+       breq    40f             ;/\r
+       cpi     r21, 'b'        ;Is type binary?\r
+       ldi     r20, 2          ;\r
+       breq    40f             ;/\r
+       ret                     ;abort\r
+40:    push    ZH              ;Output the value\r
+       push    ZL              ;\r
+       rcall   xitoa           ;\r
+42:    pop     ZL              ;\r
+       pop     ZH              ;\r
+       rjmp    0b              ;/\r
+\r
+50:    push    ZH              ;Put a string on the RAM\r
+       push    ZL\r
+       _MOVW   ZH,ZL, r25,r24\r
+51:    ld      r24, Z+\r
+       cpi     r24, 0\r
+       breq    42b\r
+       rcall   xputc\r
+       rjmp    51b\r
+\r
+60:    push    ZH              ;Put a string on the ROM\r
+       push    ZL\r
+       rcall   xputs\r
+       rjmp    42b\r
+.endfunc\r
+\r
+\r
+.func __xprintf\r
+.global __xprintf\r
+__xprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       rcall   xvprintf\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+\r
+\r
+#if USE_XSPRINTF\r
+\r
+.func __xsprintf\r
+putram:\r
+       _MOVW   ZH,ZL, r15,r14\r
+       st      Z+, r24\r
+       _MOVW   r15,r14, ZH,ZL\r
+       ret\r
+.global __xsprintf\r
+__xsprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       lds     ZL, xfunc_out+0 ;Save registered output function\r
+       lds     ZH, xfunc_out+1 ;\r
+       push    ZL              ;\r
+       push    ZH              ;/\r
+       ldi     ZL, lo8(pm(putram));Set local output function\r
+       ldi     ZH, hi8(pm(putram));\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       push    r15             ;Initialize pointer to string buffer\r
+       push    r14             ;\r
+       ld      r14, Y+         ;\r
+       ld      r15, Y+         ;/\r
+       rcall   xvprintf\r
+       _MOVW   ZH,ZL, r15,r14  ;Terminate string\r
+       st      Z, r1           ;\r
+       pop     r14             ;\r
+       pop     r15             ;/\r
+       pop     ZH              ;Restore registered output function\r
+       pop     ZL              ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+\r
+#if USE_XFPRINTF\r
+.func __xfprintf\r
+.global __xfprintf\r
+__xfprintf:\r
+       push    YH\r
+       push    YL\r
+       in      YL, _SFR_IO_ADDR(SPL)\r
+#ifdef SPH\r
+       in      YH, _SFR_IO_ADDR(SPH)\r
+#else\r
+       clr     YH\r
+#endif\r
+       adiw    YL, 5           ;Y = pointer to arguments\r
+       lds     ZL, xfunc_out+0 ;Save registered output function\r
+       lds     ZH, xfunc_out+1 ;\r
+       push    ZL              ;\r
+       push    ZH              ;/\r
+       ld      ZL, Y+          ;Set output function\r
+       ld      ZH, Y+          ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       rcall   xvprintf\r
+       pop     ZH              ;Restore registered output function\r
+       pop     ZL              ;\r
+       sts     xfunc_out+0, ZL ;\r
+       sts     xfunc_out+1, ZH ;/\r
+       pop     YL\r
+       pop     YH\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+#endif\r
+\r
+\r
+\r
+;---------------------------------------------------------------------------\r
+; Extended numeral string input\r
+;\r
+;Prototype:\r
+; char xatoi (           /* 1: Successful, 0: Failed */\r
+;      const char **str, /* pointer to pointer to source string */\r
+;      long *res         /* result */\r
+; );\r
+;\r
+\r
+\r
+#if USE_XATOI\r
+.func xatoi\r
+.global xatoi\r
+xatoi:\r
+       _MOVW   r1, r0, r23, r22\r
+       _MOVW   XH, XL, r25, r24\r
+       ld      ZL, X+\r
+       ld      ZH, X+\r
+       clr     r18             ;r21:r18 = 0;\r
+       clr     r19             ;\r
+       clr     r20             ;\r
+       clr     r21             ;/\r
+       clt                     ;T = 0;\r
+\r
+       ldi     r25, 10         ;r25 = 10;\r
+       rjmp    41f             ;/\r
+40:    adiw    ZL, 1           ;Z++;\r
+41:    ld      r22, Z          ;r22 = *Z;\r
+       cpi     r22, ' '        ;if(r22 == ' ') continue\r
+       breq    40b             ;/\r
+       brcs    70f             ;if(r22 < ' ') error;\r
+       cpi     r22, '-'        ;if(r22 == '-') {\r
+       brne    42f             ; T = 1;\r
+       set                     ; continue;\r
+       rjmp    40b             ;}\r
+42:    cpi     r22, '9'+1      ;if(r22 > '9') error;\r
+       brcc    70f             ;/\r
+       cpi     r22, '0'        ;if(r22 < '0') error;\r
+       brcs    70f             ;/\r
+       brne    51f             ;if(r22 > '0') cv_start;\r
+       ldi     r25, 8          ;r25 = 8;\r
+       adiw    ZL, 1           ;r22 = *(++Z);\r
+       ld      r22, Z          ;/\r
+       cpi     r22, ' '+1      ;if(r22 <= ' ') exit;\r
+       brcs    80f             ;/\r
+       cpi     r22, 'b'        ;if(r22 == 'b') {\r
+       brne    43f             ; r25 = 2;\r
+       ldi     r25, 2          ; cv_start;\r
+       rjmp    50f             ;}\r
+43:    cpi     r22, 'x'        ;if(r22 != 'x') error;\r
+       brne    51f             ;/\r
+       ldi     r25, 16         ;r25 = 16;\r
+\r
+50:    adiw    ZL, 1           ;Z++;\r
+       ld      r22, Z          ;r22 = *Z;\r
+51:    cpi     r22, ' '+1      ;if(r22 <= ' ') break;\r
+       brcs    80f             ;/\r
+       cpi     r22, 'a'        ;if(r22 >= 'a') r22 =- 0x20;\r
+       brcs    52f             ;\r
+       subi    r22, 0x20       ;/\r
+52:    subi    r22, '0'        ;if((r22 -= '0') < 0) error;\r
+       brcs    70f             ;/\r
+       cpi     r22, 10         ;if(r22 >= 10) {\r
+       brcs    53f             ; r22 -= 7;\r
+       subi    r22, 7          ; if(r22 < 10) \r
+       cpi     r22, 10         ;\r
+       brcs    70f             ;}\r
+53:    cp      r22, r25        ;if(r22 >= r25) error;\r
+       brcc    70f             ;/\r
+60:    ldi     r24, 33         ;r21:r18 *= r25;\r
+       sub     r23, r23        ;\r
+61:    brcc    62f             ;\r
+       add     r23, r25        ;\r
+62:    lsr     r23             ;\r
+       ror     r21             ;\r
+       ror     r20             ;\r
+       ror     r19             ;\r
+       ror     r18             ;\r
+       dec     r24             ;\r
+       brne    61b             ;/\r
+       add     r18, r22        ;r21:r18 += r22;\r
+       adc     r19, r24        ;\r
+       adc     r20, r24        ;\r
+       adc     r21, r24        ;/\r
+       rjmp    50b             ;repeat\r
+\r
+70:    ldi     r24, 0\r
+       rjmp    81f\r
+80:    ldi     r24, 1\r
+81:    brtc    82f\r
+       clr     r22\r
+       com     r18\r
+       com     r19\r
+       com     r20\r
+       com     r21\r
+       adc     r18, r22\r
+       adc     r19, r22\r
+       adc     r20, r22\r
+       adc     r21, r22\r
+82:    st      -X, ZH\r
+       st      -X, ZL\r
+       _MOVW   XH, XL, r1, r0\r
+       st      X+, r18\r
+       st      X+, r19\r
+       st      X+, r20\r
+       st      X+, r21\r
+       clr     r1\r
+       ret\r
+.endfunc\r
+#endif\r
+\r
+\r
diff --git a/common/avr/xprintf.h b/common/avr/xprintf.h
new file mode 100644 (file)
index 0000000..59c6f25
--- /dev/null
@@ -0,0 +1,111 @@
+/*---------------------------------------------------------------------------\r
+   Extended itoa, puts and printf                    (C)ChaN, 2011\r
+-----------------------------------------------------------------------------*/\r
+\r
+#ifndef XPRINTF_H\r
+#define XPRINTF_H\r
+\r
+#include <inttypes.h>\r
+#include <avr/pgmspace.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+extern void (*xfunc_out)(uint8_t);\r
+#define xdev_out(func) xfunc_out = (void(*)(uint8_t))(func)\r
+\r
+/* This is a pointer to user defined output function. It must be initialized\r
+   before using this modle.\r
+*/\r
+\r
+void xputc(char chr);\r
+\r
+/* This is a stub function to forward outputs to user defined output function.\r
+   All outputs from this module are output via this function.\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+void xputs(const char *string_p);\r
+\r
+/*  The string placed in the ROM is forwarded to xputc() directly.\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+void xitoa(long value, char radix, char width);\r
+\r
+/* Extended itoa().\r
+\r
+      value  radix  width   output\r
+        100     10      6   "   100"\r
+        100     10     -6   "000100"\r
+        100     10      0   "100"\r
+ 4294967295     10      0   "4294967295"\r
+ 4294967295    -10      0   "-1"\r
+     655360     16     -8   "000A0000"\r
+       1024     16      0   "400"\r
+       0x55      2     -8   "01010101"\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+#define xprintf(format, ...)            __xprintf(PSTR(format), ##__VA_ARGS__)\r
+#define xsprintf(str, format, ...)      __xsprintf(str, PSTR(format), ##__VA_ARGS__)\r
+#define xfprintf(func, format, ...)     __xfprintf(func, PSTR(format), ##__VA_ARGS__)\r
+\r
+void __xprintf(const char *format_p, ...);     /* Send formatted string to the registered device */\r
+void __xsprintf(char*, const char *format_p, ...);     /* Put formatted string to the memory */\r
+void __xfprintf(void(*func)(uint8_t), const char *format_p, ...); /* Send formatted string to the specified device */\r
+\r
+/* Format string is placed in the ROM. The format flags is similar to printf().\r
+\r
+   %[flag][width][size]type\r
+\r
+   flag\r
+     A '0' means filled with '0' when output is shorter than width.\r
+     ' ' is used in default. This is effective only numeral type.\r
+   width\r
+     Minimum width in decimal number. This is effective only numeral type.\r
+     Default width is zero.\r
+   size\r
+     A 'l' means the argument is long(32bit). Default is short(16bit).\r
+     This is effective only numeral type.\r
+   type\r
+     'c' : Character, argument is the value\r
+     's' : String placed on the RAM, argument is the pointer\r
+     'S' : String placed on the ROM, argument is the pointer\r
+     'd' : Signed decimal, argument is the value\r
+     'u' : Unsigned decimal, argument is the value\r
+     'X' : Hexdecimal, argument is the value\r
+     'b' : Binary, argument is the value\r
+     '%' : '%'\r
+\r
+*/\r
+\r
+\r
+/*-----------------------------------------------------------------------------*/\r
+char xatoi(char **str, long *ret);\r
+\r
+/* Get value of the numeral string. \r
+\r
+  str\r
+    Pointer to pointer to source string\r
+\r
+    "0b11001010" binary\r
+    "0377" octal\r
+    "0xff800" hexdecimal\r
+    "1250000" decimal\r
+    "-25000" decimal\r
+\r
+  ret\r
+    Pointer to return value\r
+*/\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
+\r
+#endif\r
+\r
diff --git a/common/backlight.c b/common/backlight.c
new file mode 100644 (file)
index 0000000..558ad9b
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+Copyright 2013 Mathias Andersson <wraul@dbox.se>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "backlight.h"
+#include "eeconfig.h"
+#include "debug.h"
+
+backlight_config_t backlight_config;
+
+void backlight_init(void)
+{
+    /* check signature */
+    if (!eeconfig_is_enabled()) {
+        eeconfig_init();
+    }
+    backlight_config.raw = eeconfig_read_backlight();
+    backlight_set(backlight_config.enable ? backlight_config.level : 0);
+}
+
+void backlight_increase(void)
+{
+    if(backlight_config.level < BACKLIGHT_LEVELS)
+    {
+        backlight_config.level++;
+        backlight_config.enable = 1;
+        eeconfig_write_backlight(backlight_config.raw);
+    }
+    dprintf("backlight increase: %u\n", backlight_config.level);
+    backlight_set(backlight_config.level);
+}
+
+void backlight_decrease(void)
+{
+    if(backlight_config.level > 0)
+    {
+        backlight_config.level--;
+        backlight_config.enable = !!backlight_config.level;
+        eeconfig_write_backlight(backlight_config.raw);
+    }
+    dprintf("backlight decrease: %u\n", backlight_config.level);
+    backlight_set(backlight_config.level);
+}
+
+void backlight_toggle(void)
+{
+    backlight_config.enable ^= 1;
+    eeconfig_write_backlight(backlight_config.raw);
+    dprintf("backlight toggle: %u\n", backlight_config.enable);
+    backlight_set(backlight_config.enable ? backlight_config.level : 0);
+}
+
+void backlight_step(void)
+{
+    backlight_config.level++;
+    if(backlight_config.level > BACKLIGHT_LEVELS)
+    {
+        backlight_config.level = 0;
+    }
+    backlight_config.enable = !!backlight_config.level;
+    eeconfig_write_backlight(backlight_config.raw);
+    dprintf("backlight step: %u\n", backlight_config.level);
+    backlight_set(backlight_config.level);
+}
+
+void backlight_level(uint8_t level)
+{
+    backlight_config.level ^= level;
+    backlight_config.enable = !!backlight_config.level;
+    eeconfig_write_backlight(backlight_config.raw);
+    backlight_set(backlight_config.level);
+}
diff --git a/common/backlight.h b/common/backlight.h
new file mode 100644 (file)
index 0000000..525ec8b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+Copyright 2013 Mathias Andersson <wraul@dbox.se>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BACKLIGHT_H
+#define BACKLIGHT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef union {
+    uint8_t raw;
+    struct {
+        bool    enable :1;
+        uint8_t level  :7;
+    };
+} backlight_config_t;
+
+void backlight_init(void);
+void backlight_increase(void);
+void backlight_decrease(void);
+void backlight_toggle(void);
+void backlight_step(void);
+void backlight_set(uint8_t level);
+void backlight_level(uint8_t level);
+
+#endif
diff --git a/common/bootloader.h b/common/bootloader.h
new file mode 100644 (file)
index 0000000..4477503
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef BOOTLOADER_H
+#define BOOTLOADER_H
+
+
+/* give code for your bootloader to come up if needed */
+void bootloader_jump(void);
+
+#endif
diff --git a/common/bootmagic.c b/common/bootmagic.c
new file mode 100644 (file)
index 0000000..b002a58
--- /dev/null
@@ -0,0 +1,128 @@
+#include <stdint.h>
+#include <stdbool.h>
+#include <util/delay.h>
+#include "matrix.h"
+#include "bootloader.h"
+#include "debug.h"
+#include "keymap.h"
+#include "host.h"
+#include "action_layer.h"
+#include "eeconfig.h"
+#include "bootmagic.h"
+
+
+void bootmagic(void)
+{
+    /* check signature */
+    if (!eeconfig_is_enabled()) {
+        eeconfig_init();
+    }
+
+    /* do scans in case of bounce */
+    print("boogmagic scan: ... ");
+    uint8_t scan = 100;
+    while (scan--) { matrix_scan(); _delay_ms(10); }
+    print("done.\n");
+
+    /* bootmagic skip */
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SKIP)) {
+        return;
+    }
+
+    /* eeconfig clear */
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_EEPROM_CLEAR)) {
+        eeconfig_init();
+    }
+
+    /* bootloader */
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_BOOTLOADER)) {
+        bootloader_jump();
+    }
+
+    /* debug enable */
+    debug_config.raw = eeconfig_read_debug();
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_ENABLE)) {
+        if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MATRIX)) {
+            debug_config.matrix = !debug_config.matrix;
+        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_KEYBOARD)) {
+            debug_config.keyboard = !debug_config.keyboard;
+        } else if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEBUG_MOUSE)) {
+            debug_config.mouse = !debug_config.mouse;
+        } else {
+            debug_config.enable = !debug_config.enable;
+        }
+    }
+    eeconfig_write_debug(debug_config.raw);
+
+    /* keymap config */
+    keymap_config.raw = eeconfig_read_keymap();
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK)) {
+        keymap_config.swap_control_capslock = !keymap_config.swap_control_capslock;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL)) {
+        keymap_config.capslock_to_control = !keymap_config.capslock_to_control;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_LALT_LGUI)) {
+        keymap_config.swap_lalt_lgui = !keymap_config.swap_lalt_lgui;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_RALT_RGUI)) {
+        keymap_config.swap_ralt_rgui = !keymap_config.swap_ralt_rgui;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_NO_GUI)) {
+        keymap_config.no_gui = !keymap_config.no_gui;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_GRAVE_ESC)) {
+        keymap_config.swap_grave_esc = !keymap_config.swap_grave_esc;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE)) {
+        keymap_config.swap_backslash_backspace = !keymap_config.swap_backslash_backspace;
+    }
+    if (bootmagic_scan_keycode(BOOTMAGIC_HOST_NKRO)) {
+        keymap_config.nkro = !keymap_config.nkro;
+    }
+    eeconfig_write_keymap(keymap_config.raw);
+
+#ifdef NKRO_ENABLE
+    keyboard_nkro = keymap_config.nkro;
+#endif
+
+    /* default layer */
+    uint8_t default_layer = 0;
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_0)) { default_layer |= (1<<0); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_1)) { default_layer |= (1<<1); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_2)) { default_layer |= (1<<2); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_3)) { default_layer |= (1<<3); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_4)) { default_layer |= (1<<4); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_5)) { default_layer |= (1<<5); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_6)) { default_layer |= (1<<6); }
+    if (bootmagic_scan_keycode(BOOTMAGIC_KEY_DEFAULT_LAYER_7)) { default_layer |= (1<<7); }
+    if (default_layer) {
+        eeconfig_write_default_layer(default_layer);
+        default_layer_set((uint32_t)default_layer);
+    } else {
+        default_layer = eeconfig_read_default_layer();
+        default_layer_set((uint32_t)default_layer);
+    }
+}
+
+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 (uint8_t c = 0; c < MATRIX_COLS; c++) {
+            if (matrix_row & ((matrix_row_t)1<<c)) {
+                if (keycode == keymap_key_to_keycode(0, (keypos_t){ .row = r, .col = c })) {
+                    return true;
+                }
+            }
+        }
+    }
+    return false;
+}
+
+bool bootmagic_scan_keycode(uint8_t keycode)
+{
+    if (!scan_keycode(BOOTMAGIC_KEY_SALT)) return false;
+
+    return scan_keycode(keycode);
+}
diff --git a/common/bootmagic.h b/common/bootmagic.h
new file mode 100644 (file)
index 0000000..8f6618f
--- /dev/null
@@ -0,0 +1,100 @@
+#ifndef BOOTMAGIC_H
+#define BOOTMAGIC_H
+
+
+/* bootmagic salt key */
+#ifndef BOOTMAGIC_KEY_SALT
+#define BOOTMAGIC_KEY_SALT              KC_SPACE
+#endif
+
+/* skip bootmagic and eeconfig */
+#ifndef BOOTMAGIC_KEY_SKIP
+#define BOOTMAGIC_KEY_SKIP              KC_ESC
+#endif
+
+/* eeprom clear */
+#ifndef BOOTMAGIC_KEY_EEPROM_CLEAR
+#define BOOTMAGIC_KEY_EEPROM_CLEAR      KC_BSPACE
+#endif
+
+/* kick up bootloader */
+#ifndef BOOTMAGIC_KEY_BOOTLOADER
+#define BOOTMAGIC_KEY_BOOTLOADER        KC_B
+#endif
+
+/* debug enable */
+#ifndef BOOTMAGIC_KEY_DEBUG_ENABLE
+#define BOOTMAGIC_KEY_DEBUG_ENABLE      KC_D
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_MATRIX
+#define BOOTMAGIC_KEY_DEBUG_MATRIX      KC_X
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_KEYBOARD
+#define BOOTMAGIC_KEY_DEBUG_KEYBOARD    KC_K
+#endif
+#ifndef BOOTMAGIC_KEY_DEBUG_MOUSE
+#define BOOTMAGIC_KEY_DEBUG_MOUSE       KC_M
+#endif
+
+/*
+ * keymap config
+ */
+#ifndef BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK
+#define BOOTMAGIC_KEY_SWAP_CONTROL_CAPSLOCK     KC_LCTRL
+#endif
+#ifndef BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL
+#define BOOTMAGIC_KEY_CAPSLOCK_TO_CONTROL       KC_CAPSLOCK
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_LALT_LGUI
+#define BOOTMAGIC_KEY_SWAP_LALT_LGUI            KC_LALT
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_RALT_RGUI
+#define BOOTMAGIC_KEY_SWAP_RALT_RGUI            KC_RALT
+#endif
+#ifndef BOOTMAGIC_KEY_NO_GUI
+#define BOOTMAGIC_KEY_NO_GUI                    KC_LGUI
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_GRAVE_ESC
+#define BOOTMAGIC_KEY_SWAP_GRAVE_ESC            KC_GRAVE
+#endif
+#ifndef BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE
+#define BOOTMAGIC_KEY_SWAP_BACKSLASH_BACKSPACE  KC_BSLASH
+#endif
+#ifndef BOOTMAGIC_HOST_NKRO
+#define BOOTMAGIC_HOST_NKRO              KC_N
+#endif
+
+
+/*
+ * change default layer
+ */
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_0
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_0   KC_0
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_1
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_1   KC_1
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_2
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_2   KC_2
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_3
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_3   KC_3
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_4
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_4   KC_4
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_5
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_5   KC_5
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_6
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_6   KC_6
+#endif
+#ifndef BOOTMAGIC_KEY_DEFAULT_LAYER_7
+#define BOOTMAGIC_KEY_DEFAULT_LAYER_7   KC_7
+#endif
+
+
+void bootmagic(void);
+bool bootmagic_scan_keycode(uint8_t keycode);
+
+#endif
diff --git a/common/command.c b/common/command.c
new file mode 100644 (file)
index 0000000..fbaa9f2
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include <stdbool.h>
+#include <util/delay.h>
+#include "keycode.h"
+#include "host.h"
+#include "keymap.h"
+#include "print.h"
+#include "debug.h"
+#include "util.h"
+#include "timer.h"
+#include "keyboard.h"
+#include "bootloader.h"
+#include "action_layer.h"
+#include "action_util.h"
+#include "eeconfig.h"
+#include "sleep_led.h"
+#include "led.h"
+#include "command.h"
+#include "backlight.h"
+
+#ifdef MOUSEKEY_ENABLE
+#include "mousekey.h"
+#endif
+
+#ifdef PROTOCOL_PJRC
+#   include "usb_keyboard.h"
+#   ifdef EXTRAKEY_ENABLE
+#       include "usb_extra.h"
+#   endif
+#endif
+
+#ifdef PROTOCOL_VUSB
+#   include "usbdrv.h"
+#endif
+
+
+static bool command_common(uint8_t code);
+static void command_common_help(void);
+static bool command_console(uint8_t code);
+static void command_console_help(void);
+#ifdef MOUSEKEY_ENABLE
+static bool mousekey_console(uint8_t code);
+static void mousekey_console_help(void);
+#endif
+
+static uint8_t numkey2num(uint8_t code);
+static void switch_default_layer(uint8_t layer);
+
+
+command_state_t command_state = ONESHOT;
+
+
+bool command_proc(uint8_t code)
+{
+    switch (command_state) {
+        case ONESHOT:
+            if (!IS_COMMAND())
+                return false;
+            return (command_extra(code) || command_common(code));
+            break;
+        case CONSOLE:
+            if (IS_COMMAND())
+                return (command_extra(code) || command_common(code));
+            else
+                return (command_console_extra(code) || command_console(code));
+            break;
+#ifdef MOUSEKEY_ENABLE
+        case MOUSEKEY:
+            mousekey_console(code);
+            break;
+#endif
+        default:
+            command_state = ONESHOT;
+            return false;
+    }
+    return true;
+}
+
+/* TODO: Refactoring is needed. */
+/* This allows to define extra commands. return false when not processed. */
+bool command_extra(uint8_t code) __attribute__ ((weak));
+bool command_extra(uint8_t code)
+{
+    return false;
+}
+
+bool command_console_extra(uint8_t code) __attribute__ ((weak));
+bool command_console_extra(uint8_t code)
+{
+    return false;
+}
+
+
+/***********************************************************
+ * Command common
+ ***********************************************************/
+static void command_common_help(void)
+{
+    print("\n\n----- Command Help -----\n");
+    print("c:  enter console mode\n");
+    print("d:  toggle debug enable\n");
+    print("x:  toggle matrix debug\n");
+    print("k:  toggle keyboard debug\n");
+    print("m:  toggle mouse debug\n");
+#ifdef SLEEP_LED_ENABLE
+    print("z:  toggle sleep LED test\n");
+#endif
+    print("v:  print device version & info\n");
+    print("t:  print timer count\n");
+    print("s:  print status\n");
+    print("e:  print eeprom config\n");
+#ifdef NKRO_ENABLE
+    print("n:  toggle NKRO\n");
+#endif
+    print("0/F10:      switch to Layer0 \n");
+    print("1/F1:       switch to Layer1 \n");
+    print("2/F2:       switch to Layer2 \n");
+    print("3/F3:       switch to Layer3 \n");
+    print("4/F4:       switch to Layer4 \n");
+    print("PScr:       power down/remote wake-up\n");
+    print("Caps:       Lock Keyboard(Child Proof)\n");
+    print("Paus:       jump to bootloader\n");
+}
+
+#ifdef BOOTMAGIC_ENABLE
+static void print_eeconfig(void)
+{
+    print("default_layer: "); print_dec(eeconfig_read_default_layer()); print("\n");
+
+    debug_config_t dc;
+    dc.raw = eeconfig_read_debug();
+    print("debug_config.raw: "); print_hex8(dc.raw); print("\n");
+    print(".enable: "); print_dec(dc.enable); print("\n");
+    print(".matrix: "); print_dec(dc.matrix); print("\n");
+    print(".keyboard: "); print_dec(dc.keyboard); print("\n");
+    print(".mouse: "); print_dec(dc.mouse); print("\n");
+
+    keymap_config_t kc;
+    kc.raw = eeconfig_read_keymap();
+    print("keymap_config.raw: "); print_hex8(kc.raw); print("\n");
+    print(".swap_control_capslock: "); print_dec(kc.swap_control_capslock); print("\n");
+    print(".capslock_to_control: "); print_dec(kc.capslock_to_control); print("\n");
+    print(".swap_lalt_lgui: "); print_dec(kc.swap_lalt_lgui); print("\n");
+    print(".swap_ralt_rgui: "); print_dec(kc.swap_ralt_rgui); print("\n");
+    print(".no_gui: "); print_dec(kc.no_gui); print("\n");
+    print(".swap_grave_esc: "); print_dec(kc.swap_grave_esc); print("\n");
+    print(".swap_backslash_backspace: "); print_dec(kc.swap_backslash_backspace); print("\n");
+    print(".nkro: "); print_dec(kc.nkro); print("\n");
+
+#ifdef BACKLIGHT_ENABLE
+    backlight_config_t bc;
+    bc.raw = eeconfig_read_backlight();
+    print("backlight_config.raw: "); print_hex8(bc.raw); print("\n");
+    print(".enable: "); print_dec(bc.enable); print("\n");
+    print(".level: "); print_dec(bc.level); print("\n");
+#endif
+}
+#endif
+
+static bool command_common(uint8_t code)
+{
+    static host_driver_t *host_driver = 0;
+    switch (code) {
+#ifdef SLEEP_LED_ENABLE
+        case KC_Z:
+            // test breathing sleep LED
+            print("Sleep LED test\n");
+            sleep_led_toggle();
+            led_set(host_keyboard_leds());
+            break;
+#endif
+#ifdef BOOTMAGIC_ENABLE
+        case KC_E:
+            print("eeconfig:\n");
+            print_eeconfig();
+            break;
+#endif
+        case KC_CAPSLOCK:
+            if (host_get_driver()) {
+                host_driver = host_get_driver();
+                clear_keyboard();
+                host_set_driver(0);
+                print("Locked.\n");
+            } else {
+                host_set_driver(host_driver);
+                print("Unlocked.\n");
+            }
+            break;
+        case KC_H:
+        case KC_SLASH: /* ? */
+            command_common_help();
+            break;
+        case KC_C:
+            debug_matrix   = false;
+            debug_keyboard = false;
+            debug_mouse    = false;
+            debug_enable   = false;
+            command_console_help();
+            print("\nEnter Console Mode\n");
+            print("C> ");
+            command_state = CONSOLE;
+            break;
+        case KC_PAUSE:
+            clear_keyboard();
+            print("\n\nJump to bootloader... ");
+            _delay_ms(1000);
+            bootloader_jump(); // not return
+            print("not supported.\n");
+            break;
+        case KC_D:
+            if (debug_enable) {
+                print("\nDEBUG: disabled.\n");
+                debug_matrix   = false;
+                debug_keyboard = false;
+                debug_mouse    = false;
+                debug_enable   = false;
+            } else {
+                print("\nDEBUG: enabled.\n");
+                debug_enable   = true;
+            }
+            break;
+        case KC_X: // debug matrix toggle
+            debug_matrix = !debug_matrix;
+            if (debug_matrix) {
+                print("\nDEBUG: matrix enabled.\n");
+                debug_enable = true;
+            } else {
+                print("\nDEBUG: matrix disabled.\n");
+            }
+            break;
+        case KC_K: // debug keyboard toggle
+            debug_keyboard = !debug_keyboard;
+            if (debug_keyboard) {
+                print("\nDEBUG: keyboard enabled.\n");
+                debug_enable = true;
+            } else {
+                print("\nDEBUG: keyboard disabled.\n");
+            }
+            break;
+        case KC_M: // debug mouse toggle
+            debug_mouse = !debug_mouse;
+            if (debug_mouse) {
+                print("\nDEBUG: mouse enabled.\n");
+                debug_enable = true;
+            } else {
+                print("\nDEBUG: mouse disabled.\n");
+            }
+            break;
+        case KC_V: // print version & information
+            print("\n\n----- Version -----\n");
+            print("DESC: " STR(DESCRIPTION) "\n");
+            print("VID: " STR(VENDOR_ID) "(" STR(MANUFACTURER) ") "
+                  "PID: " STR(PRODUCT_ID) "(" STR(PRODUCT) ") "
+                  "VER: " STR(DEVICE_VER) "\n");
+            print("BUILD: " STR(VERSION) " (" __TIME__ " " __DATE__ ")\n");
+            /* build options */
+            print("OPTIONS:"
+#ifdef PROTOCOL_PJRC
+            " PJRC"
+#endif
+#ifdef PROTOCOL_LUFA
+            " LUFA"
+#endif
+#ifdef PROTOCOL_VUSB
+            " VUSB"
+#endif
+#ifdef BOOTMAGIC_ENABLE
+            " BOOTMAGIC"
+#endif
+#ifdef MOUSEKEY_ENABLE
+            " MOUSEKEY"
+#endif
+#ifdef EXTRAKEY_ENABLE
+            " EXTRAKEY"
+#endif
+#ifdef CONSOLE_ENABLE
+            " CONSOLE"
+#endif
+#ifdef COMMAND_ENABLE
+            " COMMAND"
+#endif
+#ifdef NKRO_ENABLE
+            " NKRO"
+#endif
+#ifdef KEYMAP_SECTION_ENABLE
+            " KEYMAP_SECTION"
+#endif
+            " " STR(BOOTLOADER_SIZE) "\n");
+
+            print("GCC: " STR(__GNUC__) "." STR(__GNUC_MINOR__) "." STR(__GNUC_PATCHLEVEL__)
+                  " AVR-LIBC: " __AVR_LIBC_VERSION_STRING__
+                  " AVR_ARCH: avr" STR(__AVR_ARCH__) "\n");
+            break;
+        case KC_T: // print timer
+            print_val_hex32(timer_count);
+            break;
+        case KC_S:
+            print("\n\n----- Status -----\n");
+            print_val_hex8(host_keyboard_leds());
+            print_val_hex8(keyboard_protocol);
+            print_val_hex8(keyboard_idle);
+#ifdef PROTOCOL_PJRC
+            print_val_hex8(UDCON);
+            print_val_hex8(UDIEN);
+            print_val_hex8(UDINT);
+            print_val_hex8(usb_keyboard_leds);
+            print_val_hex8(usb_keyboard_idle_count);
+#endif
+
+#ifdef PROTOCOL_PJRC
+#   if USB_COUNT_SOF
+            print_val_hex8(usbSofCount);
+#   endif
+#endif
+            break;
+#ifdef NKRO_ENABLE
+        case KC_N:
+            clear_keyboard(); //Prevents stuck keys.
+            keyboard_nkro = !keyboard_nkro;
+            if (keyboard_nkro)
+                print("NKRO: enabled\n");
+            else
+                print("NKRO: disabled\n");
+            break;
+#endif
+#ifdef EXTRAKEY_ENABLE
+        case KC_PSCREEN:
+            // TODO: Power key should take this feature? otherwise any key during suspend.
+#ifdef PROTOCOL_PJRC
+            if (suspend && remote_wakeup) {
+                usb_remote_wakeup();
+            } else {
+                host_system_send(SYSTEM_POWER_DOWN);
+                host_system_send(0);
+                _delay_ms(500);
+            }
+#else
+            host_system_send(SYSTEM_POWER_DOWN);
+            _delay_ms(100);
+            host_system_send(0);
+            _delay_ms(500);
+#endif
+            break;
+#endif
+        case KC_ESC:
+        case KC_GRV:
+        case KC_0:
+            switch_default_layer(0);
+            break;
+        case KC_1 ... KC_9:
+            switch_default_layer((code - KC_1) + 1);
+            break;
+        case KC_F1 ... KC_F12:
+            switch_default_layer((code - KC_F1) + 1);
+            break;
+        default:
+            print("?");
+            return false;
+    }
+    return true;
+}
+
+
+/***********************************************************
+ * Command console
+ ***********************************************************/
+static void command_console_help(void)
+{
+    print("\n\n----- Console Help -----\n");
+    print("ESC/q:      quit\n");
+#ifdef MOUSEKEY_ENABLE
+    print("m:  mousekey\n");
+#endif
+}
+
+static bool command_console(uint8_t code)
+{
+    switch (code) {
+        case KC_H:
+        case KC_SLASH: /* ? */
+            command_console_help();
+            break;
+        case KC_Q:
+        case KC_ESC:
+            print("\nQuit Console Mode\n");
+            command_state = ONESHOT;
+            return false;
+#ifdef MOUSEKEY_ENABLE
+        case KC_M:
+            mousekey_console_help();
+            print("\nEnter Mousekey Console\n");
+            print("M0>");
+            command_state = MOUSEKEY;
+            return true;
+#endif
+        default:
+            print("?");
+            return false;
+    }
+    print("C> ");
+    return true;
+}
+
+
+#ifdef MOUSEKEY_ENABLE
+/***********************************************************
+ * Mousekey console
+ ***********************************************************/
+static uint8_t mousekey_param = 0;
+
+static void mousekey_param_print(void)
+{
+    print("\n\n----- Mousekey Parameters -----\n");
+    print("1: mk_delay(*10ms): "); pdec(mk_delay); print("\n");
+    print("2: mk_interval(ms): "); pdec(mk_interval); print("\n");
+    print("3: mk_max_speed: "); pdec(mk_max_speed); print("\n");
+    print("4: mk_time_to_max: "); pdec(mk_time_to_max); print("\n");
+    print("5: mk_wheel_max_speed: "); pdec(mk_wheel_max_speed); print("\n");
+    print("6: mk_wheel_time_to_max: "); pdec(mk_wheel_time_to_max); print("\n");
+}
+
+#define PRINT_SET_VAL(v)  print(#v " = "); print_dec(v); print("\n");
+static void mousekey_param_inc(uint8_t param, uint8_t inc)
+{
+    switch (param) {
+        case 1:
+            if (mk_delay + inc < UINT8_MAX)
+                mk_delay += inc;
+            else
+                mk_delay = UINT8_MAX;
+            PRINT_SET_VAL(mk_delay);
+            break;
+        case 2:
+            if (mk_interval + inc < UINT8_MAX)
+                mk_interval += inc;
+            else
+                mk_interval = UINT8_MAX;
+            PRINT_SET_VAL(mk_interval);
+            break;
+        case 3:
+            if (mk_max_speed + inc < UINT8_MAX)
+                mk_max_speed += inc;
+            else
+                mk_max_speed = UINT8_MAX;
+            PRINT_SET_VAL(mk_max_speed);
+            break;
+        case 4:
+            if (mk_time_to_max + inc < UINT8_MAX)
+                mk_time_to_max += inc;
+            else
+                mk_time_to_max = UINT8_MAX;
+            PRINT_SET_VAL(mk_time_to_max);
+            break;
+        case 5:
+            if (mk_wheel_max_speed + inc < UINT8_MAX)
+                mk_wheel_max_speed += inc;
+            else
+                mk_wheel_max_speed = UINT8_MAX;
+            PRINT_SET_VAL(mk_wheel_max_speed);
+            break;
+        case 6:
+            if (mk_wheel_time_to_max + inc < UINT8_MAX)
+                mk_wheel_time_to_max += inc;
+            else
+                mk_wheel_time_to_max = UINT8_MAX;
+            PRINT_SET_VAL(mk_wheel_time_to_max);
+            break;
+    }
+}
+
+static void mousekey_param_dec(uint8_t param, uint8_t dec)
+{
+    switch (param) {
+        case 1:
+            if (mk_delay > dec)
+                mk_delay -= dec;
+            else
+                mk_delay = 0;
+            PRINT_SET_VAL(mk_delay);
+            break;
+        case 2:
+            if (mk_interval > dec)
+                mk_interval -= dec;
+            else
+                mk_interval = 0;
+            PRINT_SET_VAL(mk_interval);
+            break;
+        case 3:
+            if (mk_max_speed > dec)
+                mk_max_speed -= dec;
+            else
+                mk_max_speed = 0;
+            PRINT_SET_VAL(mk_max_speed);
+            break;
+        case 4:
+            if (mk_time_to_max > dec)
+                mk_time_to_max -= dec;
+            else
+                mk_time_to_max = 0;
+            PRINT_SET_VAL(mk_time_to_max);
+            break;
+        case 5:
+            if (mk_wheel_max_speed > dec)
+                mk_wheel_max_speed -= dec;
+            else
+                mk_wheel_max_speed = 0;
+            PRINT_SET_VAL(mk_wheel_max_speed);
+            break;
+        case 6:
+            if (mk_wheel_time_to_max > dec)
+                mk_wheel_time_to_max -= dec;
+            else
+                mk_wheel_time_to_max = 0;
+            PRINT_SET_VAL(mk_wheel_time_to_max);
+            break;
+    }
+}
+
+static void mousekey_console_help(void)
+{
+    print("\n\n----- Mousekey Parameters Help -----\n");
+    print("ESC/q:      quit\n");
+    print("1:  select mk_delay(*10ms)\n");
+    print("2:  select mk_interval(ms)\n");
+    print("3:  select mk_max_speed\n");
+    print("4:  select mk_time_to_max\n");
+    print("5:  select mk_wheel_max_speed\n");
+    print("6:  select mk_wheel_time_to_max\n");
+    print("p:  print parameters\n");
+    print("d:  set default values\n");
+    print("up: increase parameters(+1)\n");
+    print("down:       decrease parameters(-1)\n");
+    print("pgup:       increase parameters(+10)\n");
+    print("pgdown:     decrease parameters(-10)\n");
+    print("\nspeed = delta * max_speed * (repeat / time_to_max)\n");
+    print("where delta: cursor="); pdec(MOUSEKEY_MOVE_DELTA);
+    print(", wheel="); pdec(MOUSEKEY_WHEEL_DELTA); print("\n");
+    print("See http://en.wikipedia.org/wiki/Mouse_keys\n");
+}
+
+static bool mousekey_console(uint8_t code)
+{
+    switch (code) {
+        case KC_H:
+        case KC_SLASH: /* ? */
+            mousekey_console_help();
+            break;
+        case KC_Q:
+        case KC_ESC:
+            mousekey_param = 0;
+            print("\nQuit Mousekey Console\n");
+            print("C> ");
+            command_state = CONSOLE;
+            return false;
+        case KC_P:
+            mousekey_param_print();
+            break;
+        case KC_1:
+        case KC_2:
+        case KC_3:
+        case KC_4:
+        case KC_5:
+        case KC_6:
+        case KC_7:
+        case KC_8:
+        case KC_9:
+        case KC_0:
+            mousekey_param = numkey2num(code);
+            print("selected parameter: "); pdec(mousekey_param); print("\n");
+            break;
+        case KC_UP:
+            mousekey_param_inc(mousekey_param, 1);
+            break;
+        case KC_DOWN:
+            mousekey_param_dec(mousekey_param, 1);
+            break;
+        case KC_PGUP:
+            mousekey_param_inc(mousekey_param, 10);
+            break;
+        case KC_PGDN:
+            mousekey_param_dec(mousekey_param, 10);
+            break;
+        case KC_D:
+            mk_delay = MOUSEKEY_DELAY/10;
+            mk_interval = MOUSEKEY_INTERVAL;
+            mk_max_speed = MOUSEKEY_MAX_SPEED;
+            mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+            mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+            mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
+            print("set default values.\n");
+            break;
+        default:
+            print("?");
+            return false;
+    }
+    print("M"); pdec(mousekey_param); print("> ");
+    return true;
+}
+#endif
+
+
+/***********************************************************
+ * Utilities
+ ***********************************************************/
+static uint8_t numkey2num(uint8_t code)
+{
+    switch (code) {
+        case KC_1: return 1;
+        case KC_2: return 2;
+        case KC_3: return 3;
+        case KC_4: return 4;
+        case KC_5: return 5;
+        case KC_6: return 6;
+        case KC_7: return 7;
+        case KC_8: return 8;
+        case KC_9: return 9;
+        case KC_0: return 0;
+    }
+    return 0;
+}
+
+static void switch_default_layer(uint8_t layer)
+{
+    print("switch_default_layer: "); print_dec(biton32(default_layer_state));
+    print(" to "); print_dec(layer); print("\n");
+    default_layer_set(1UL<<layer);
+    clear_keyboard();
+}
diff --git a/common/command.h b/common/command.h
new file mode 100644 (file)
index 0000000..b57a6c1
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef COMMAND_H
+#define COMMAND
+
+/* TODO: Refactoring */
+typedef enum { ONESHOT, CONSOLE, MOUSEKEY } command_state_t;
+extern command_state_t command_state;
+
+/* This allows to extend commands. Return false when command is not processed. */
+bool command_extra(uint8_t code);
+bool command_console_extra(uint8_t code);
+
+#ifdef COMMAND_ENABLE
+bool command_proc(uint8_t code);
+#else
+#define command_proc(code)      false
+#endif
+
+#endif
diff --git a/common/debug.c b/common/debug.c
new file mode 100644 (file)
index 0000000..18613fc
--- /dev/null
@@ -0,0 +1,24 @@
+#include <stdbool.h>
+#include "debug.h"
+
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+
+debug_config_t debug_config = {
+/* GCC Bug 10676 - Using unnamed fields in initializers
+ * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10676 */
+#if GCC_VERSION >= 40600
+    .enable = false,
+    .matrix = false,
+    .keyboard = false,
+    .mouse = false,
+    .reserved = 0
+#else
+    {
+        false,  // .enable
+        false,  // .matrix
+        false,  // .keyboard
+        false,  // .mouse
+        0       // .reserved
+    }
+#endif
+};
diff --git a/common/debug.h b/common/debug.h
new file mode 100644 (file)
index 0000000..3cbe209
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef DEBUG_H
+#define DEBUG_H 1
+
+#include <stdbool.h>
+#include "print.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Debug output control
+ */
+typedef union {
+    struct {
+        bool enable:1;
+        bool matrix:1;
+        bool keyboard:1;
+        bool mouse:1;
+        uint8_t reserved:4;
+    };
+    uint8_t raw;
+} debug_config_t;
+
+extern debug_config_t debug_config;
+
+#ifdef __cplusplus
+}
+#endif
+
+/* for backward compatibility */
+#define debug_enable    (debug_config.enable)
+#define debug_matrix    (debug_config.matrix)
+#define debug_keyboard  (debug_config.keyboard)
+#define debug_mouse     (debug_config.mouse)
+
+
+/*
+ * Debug print utils
+ */
+#ifndef NO_DEBUG
+
+#define dprint(s)                   do { if (debug_enable) print(s); } while (0)
+#define dprintln(s)                 do { if (debug_enable) println(s); } while (0)
+#define dprintf(fmt, ...)           do { if (debug_enable) xprintf(fmt, ##__VA_ARGS__); } while (0)
+#define dmsg(s)                     dprintf("%s at %s: %S\n", __FILE__, __LINE__, PSTR(s))
+
+/* Deprecated. DO NOT USE these anymore, use dprintf instead. */
+#define debug(s)                    do { if (debug_enable) print(s); } while (0)
+#define debugln(s)                  do { if (debug_enable) println(s); } while (0)
+#define debug_msg(s)                do { \
+    if (debug_enable) { \
+        print(__FILE__); print(" at "); print_dec(__LINE__); print(" in "); print(": "); print(s); \
+    } \
+} while (0)
+#define debug_dec(data)             do { if (debug_enable) print_dec(data); } while (0)
+#define debug_decs(data)            do { if (debug_enable) print_decs(data); } while (0)
+#define debug_hex4(data)            do { if (debug_enable) print_hex4(data); } while (0)
+#define debug_hex8(data)            do { if (debug_enable) print_hex8(data); } while (0)
+#define debug_hex16(data)           do { if (debug_enable) print_hex16(data); } while (0)
+#define debug_hex32(data)           do { if (debug_enable) print_hex32(data); } while (0)
+#define debug_bin8(data)            do { if (debug_enable) print_bin8(data); } while (0)
+#define debug_bin16(data)           do { if (debug_enable) print_bin16(data); } while (0)
+#define debug_bin32(data)           do { if (debug_enable) print_bin32(data); } while (0)
+#define debug_bin_reverse8(data)    do { if (debug_enable) print_bin_reverse8(data); } while (0)
+#define debug_bin_reverse16(data)   do { if (debug_enable) print_bin_reverse16(data); } while (0)
+#define debug_bin_reverse32(data)   do { if (debug_enable) print_bin_reverse32(data); } while (0)
+#define debug_hex(data)             debug_hex8(data)
+#define debug_bin(data)             debug_bin8(data)
+#define debug_bin_reverse(data)     debug_bin8(data)
+
+#else /* NO_DEBUG */
+
+#define dprint(s)
+#define dprintln(s)
+#define dprintf(fmt, ...)
+#define dmsg(s)
+#define debug(s)
+#define debugln(s)
+#define debug_msg(s)
+#define debug_dec(data)
+#define debug_decs(data)
+#define debug_hex4(data)
+#define debug_hex8(data)
+#define debug_hex16(data)
+#define debug_hex32(data)
+#define debug_bin8(data)
+#define debug_bin16(data)
+#define debug_bin32(data)
+#define debug_bin_reverse8(data)
+#define debug_bin_reverse16(data)
+#define debug_bin_reverse32(data)
+#define debug_hex(data)
+#define debug_bin(data)
+#define debug_bin_reverse(data)
+
+#endif /* NO_DEBUG */
+
+#endif
diff --git a/common/eeconfig.h b/common/eeconfig.h
new file mode 100644 (file)
index 0000000..3cd1a17
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef EECONFIG_H
+#define EECONFIG_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+#define EECONFIG_MAGIC_NUMBER                       (uint16_t)0xFEED
+
+/* eeprom parameteter address */
+#define EECONFIG_MAGIC                              (uint16_t *)0
+#define EECONFIG_DEBUG                              (uint8_t *)2
+#define EECONFIG_DEFAULT_LAYER                      (uint8_t *)3
+#define EECONFIG_KEYMAP                             (uint8_t *)4
+#define EECONFIG_MOUSEKEY_ACCEL                     (uint8_t *)5
+#define EECONFIG_BACKLIGHT                          (uint8_t *)6
+
+
+/* debug bit */
+#define EECONFIG_DEBUG_ENABLE                       (1<<0)
+#define EECONFIG_DEBUG_MATRIX                       (1<<1)
+#define EECONFIG_DEBUG_KEYBOARD                     (1<<2)
+#define EECONFIG_DEBUG_MOUSE                        (1<<3)
+
+/* keyconf bit */
+#define EECONFIG_KEYMAP_SWAP_CONTROL_CAPSLOCK       (1<<0)
+#define EECONFIG_KEYMAP_CAPSLOCK_TO_CONTROL         (1<<1)
+#define EECONFIG_KEYMAP_SWAP_LALT_LGUI              (1<<2)
+#define EECONFIG_KEYMAP_SWAP_RALT_RGUI              (1<<3)
+#define EECONFIG_KEYMAP_NO_GUI                      (1<<4)
+#define EECONFIG_KEYMAP_SWAP_GRAVE_ESC              (1<<5)
+#define EECONFIG_KEYMAP_SWAP_BACKSLASH_BACKSPACE    (1<<6)
+#define EECONFIG_KEYMAP_NKRO                        (1<<7)
+
+
+bool eeconfig_is_enabled(void);
+
+void eeconfig_init(void);
+
+void eeconfig_enable(void);
+
+void eeconfig_disable(void);
+
+uint8_t eeconfig_read_debug(void);
+void eeconfig_write_debug(uint8_t val);
+
+uint8_t eeconfig_read_default_layer(void);
+void eeconfig_write_default_layer(uint8_t val);
+
+uint8_t eeconfig_read_keymap(void);
+void eeconfig_write_keymap(uint8_t val);
+
+#ifdef BACKLIGHT_ENABLE
+uint8_t eeconfig_read_backlight(void);
+void eeconfig_write_backlight(uint8_t val);
+#endif
+
+#endif
diff --git a/common/host.c b/common/host.c
new file mode 100644 (file)
index 0000000..e9b7916
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+//#include <avr/interrupt.h>
+#include "keycode.h"
+#include "host.h"
+#include "util.h"
+#include "debug.h"
+
+
+#ifdef NKRO_ENABLE
+bool keyboard_nkro = true;
+#endif
+
+static host_driver_t *driver;
+static uint16_t last_system_report = 0;
+static uint16_t last_consumer_report = 0;
+
+
+void host_set_driver(host_driver_t *d)
+{
+    driver = d;
+}
+
+host_driver_t *host_get_driver(void)
+{
+    return driver;
+}
+
+uint8_t host_keyboard_leds(void)
+{
+    if (!driver) return 0;
+    return (*driver->keyboard_leds)();
+}
+/* send report */
+void host_keyboard_send(report_keyboard_t *report)
+{
+    if (!driver) return;
+    (*driver->send_keyboard)(report);
+
+    if (debug_keyboard) {
+        dprint("keyboard_report: ");
+        for (uint8_t i = 0; i < KEYBOARD_REPORT_SIZE; i++) {
+            dprintf("%02X ", report->raw[i]);
+        }
+        dprint("\n");
+    }
+}
+
+void host_mouse_send(report_mouse_t *report)
+{
+    if (!driver) return;
+    (*driver->send_mouse)(report);
+}
+
+void host_system_send(uint16_t report)
+{
+    if (report == last_system_report) return;
+    last_system_report = report;
+
+    if (!driver) return;
+    (*driver->send_system)(report);
+}
+
+void host_consumer_send(uint16_t report)
+{
+    if (report == last_consumer_report) return;
+    last_consumer_report = report;
+
+    if (!driver) return;
+    (*driver->send_consumer)(report);
+}
+
+uint16_t host_last_sysytem_report(void)
+{
+    return last_system_report;
+}
+
+uint16_t host_last_consumer_report(void)
+{
+    return last_consumer_report;
+}
diff --git a/common/host.h b/common/host.h
new file mode 100644 (file)
index 0000000..918af69
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_H
+#define HOST_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "report.h"
+#include "host_driver.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef NKRO_ENABLE
+extern bool keyboard_nkro;
+#endif
+
+extern uint8_t keyboard_idle;
+extern uint8_t keyboard_protocol;
+
+
+/* host driver */
+void host_set_driver(host_driver_t *driver);
+host_driver_t *host_get_driver(void);
+
+/* host driver interface */
+uint8_t host_keyboard_leds(void);
+void host_keyboard_send(report_keyboard_t *report);
+void host_mouse_send(report_mouse_t *report);
+void host_system_send(uint16_t data);
+void host_consumer_send(uint16_t data);
+
+uint16_t host_last_sysytem_report(void);
+uint16_t host_last_consumer_report(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/host_driver.h b/common/host_driver.h
new file mode 100644 (file)
index 0000000..edb9e5d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef HOST_DRIVER_H
+#define HOST_DRIVER_H
+
+#include <stdint.h>
+#include "report.h"
+
+
+typedef struct {
+    uint8_t (*keyboard_leds)(void);
+    void (*send_keyboard)(report_keyboard_t *);
+    void (*send_mouse)(report_mouse_t *);
+    void (*send_system)(uint16_t);
+    void (*send_consumer)(uint16_t);
+} host_driver_t;
+
+#endif
diff --git a/common/keyboard.c b/common/keyboard.c
new file mode 100644 (file)
index 0000000..1e3fb51
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include <stdint.h>
+#include "keyboard.h"
+#include "matrix.h"
+#include "keymap.h"
+#include "host.h"
+#include "led.h"
+#include "keycode.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "command.h"
+#include "util.h"
+#include "sendchar.h"
+#include "bootmagic.h"
+#include "eeconfig.h"
+#include "backlight.h"
+#ifdef MOUSEKEY_ENABLE
+#   include "mousekey.h"
+#endif
+#ifdef PS2_MOUSE_ENABLE
+#   include "ps2_mouse.h"
+#endif
+#ifdef SERIAL_MOUSE_ENABLE
+#include "serial_mouse.h"
+#endif
+
+
+#ifdef MATRIX_HAS_GHOST
+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
+
+
+void keyboard_init(void)
+{
+    timer_init();
+    matrix_init();
+#ifdef PS2_MOUSE_ENABLE
+    ps2_mouse_init();
+#endif
+#ifdef SERIAL_MOUSE_ENABLE
+    serial_mouse_init();
+#endif
+
+
+#ifdef BOOTMAGIC_ENABLE
+    bootmagic();
+#endif
+
+#ifdef BACKLIGHT_ENABLE
+    backlight_init();
+#endif
+}
+
+/*
+ * 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];
+    static uint8_t led_status = 0;
+    matrix_row_t matrix_row = 0;
+    matrix_row_t matrix_change = 0;
+
+    matrix_scan();
+    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) {
+            if (debug_matrix) matrix_print();
+#ifdef MATRIX_HAS_GHOST
+            if (has_ghost_in_row(r)) {
+                matrix_prev[r] = matrix_row;
+                continue;
+            }
+#endif
+            for (uint8_t c = 0; c < MATRIX_COLS; c++) {
+                if (matrix_change & ((matrix_row_t)1<<c)) {
+                    action_exec((keyevent_t){
+                        .key = (keypos_t){ .row = r, .col = c },
+                        .pressed = (matrix_row & ((matrix_row_t)1<<c)),
+                        .time = (timer_read() | 1) /* time should not be 0 */
+                    });
+                    // record a processed key
+                    matrix_prev[r] ^= ((matrix_row_t)1<<c);
+                    // process a key per task call
+                    goto MATRIX_LOOP_END;
+                }
+            }
+        }
+    }
+    // call with pseudo tick event when no real key event.
+    action_exec(TICK);
+
+MATRIX_LOOP_END:
+
+#ifdef MOUSEKEY_ENABLE
+    // mousekey repeat & acceleration
+    mousekey_task();
+#endif
+
+#ifdef PS2_MOUSE_ENABLE
+    ps2_mouse_task();
+#endif
+
+#ifdef SERIAL_MOUSE_ENABLE
+        serial_mouse_task();
+#endif
+
+    // update LED
+    if (led_status != host_keyboard_leds()) {
+        led_status = host_keyboard_leds();
+        keyboard_set_leds(led_status);
+    }
+}
+
+void keyboard_set_leds(uint8_t leds)
+{
+    if (debug_keyboard) { debug("keyboard_set_led: "); debug_hex8(leds); debug("\n"); }
+    led_set(leds);
+}
diff --git a/common/keyboard.h b/common/keyboard.h
new file mode 100644 (file)
index 0000000..6442716
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+Copyright 2011,2012,2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYBOARD_H
+#define KEYBOARD_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* key matrix position */
+typedef struct {
+    uint8_t col;
+    uint8_t row;
+} keypos_t;
+
+/* key event */
+typedef struct {
+    keypos_t key;
+    bool     pressed;
+    uint16_t time;
+} keyevent_t;
+
+/* equivalent test of keypos_t */
+#define KEYEQ(keya, keyb)       ((keya).row == (keyb).row && (keya).col == (keyb).col)
+
+/* Rules for No Event:
+ * 1) (time == 0) to handle (keyevent_t){} as empty event
+ * 2) Matrix(255, 255) to make TICK event available
+ */
+static inline bool IS_NOEVENT(keyevent_t event) { return event.time == 0 || (event.key.row == 255 && event.key.col == 255); }
+static inline bool IS_PRESSED(keyevent_t event) { return (!IS_NOEVENT(event) && event.pressed); }
+static inline bool IS_RELEASED(keyevent_t event) { return (!IS_NOEVENT(event) && !event.pressed); }
+
+/* Tick event */
+#define TICK                    (keyevent_t){           \
+    .key = (keypos_t){ .row = 255, .col = 255 },           \
+    .pressed = false,                                   \
+    .time = (timer_read() | 1)                          \
+}
+
+
+void keyboard_init(void);
+void keyboard_task(void);
+void keyboard_set_leds(uint8_t leds);
+
+__attribute__ ((weak)) void matrix_power_up(void) {}
+__attribute__ ((weak)) void matrix_power_down(void) {}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/keycode.h b/common/keycode.h
new file mode 100644 (file)
index 0000000..ac4ef00
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Keycodes based on HID Usage Keyboard/Keypad Page(0x07) plus special codes
+ * http://www.usb.org/developers/devclass_docs/Hut1_12.pdf
+ */
+#ifndef KEYCODE_H
+#define KEYCODE_H
+
+
+#define IS_ERROR(code)           (KC_ROLL_OVER <= (code) && (code) <= KC_UNDEFINED)
+#define IS_ANY(code)             (KC_A         <= (code) && (code) <= 0xFF)
+#define IS_KEY(code)             (KC_A         <= (code) && (code) <= KC_EXSEL)
+#define IS_MOD(code)             (KC_LCTRL     <= (code) && (code) <= KC_RGUI)
+
+
+#define IS_SPECIAL(code)         ((0xA5 <= (code) && (code) <= 0xDF) || (0xE8 <= (code) && (code) <= 0xFF))
+#define IS_SYSTEM(code)          (KC_PWR       <= (code) && (code) <= KC_WAKE)
+#define IS_CONSUMER(code)        (KC_MUTE      <= (code) && (code) <= KC_WFAV)
+#define IS_FN(code)              (KC_FN0       <= (code) && (code) <= KC_FN31)
+#define IS_MOUSEKEY(code)        (KC_MS_UP     <= (code) && (code) <= KC_MS_ACCEL2)
+#define IS_MOUSEKEY_MOVE(code)   (KC_MS_UP     <= (code) && (code) <= KC_MS_RIGHT)
+#define IS_MOUSEKEY_BUTTON(code) (KC_MS_BTN1   <= (code) && (code) <= KC_MS_BTN5)
+#define IS_MOUSEKEY_WHEEL(code)  (KC_MS_WH_UP  <= (code) && (code) <= KC_MS_WH_RIGHT)
+#define IS_MOUSEKEY_ACCEL(code)  (KC_MS_ACCEL0 <= (code) && (code) <= KC_MS_ACCEL2)
+
+#define MOD_BIT(code)   (1<<MOD_INDEX(code))
+#define MOD_INDEX(code) ((code) & 0x07)
+#define FN_BIT(code)    (1<<FN_INDEX(code))
+#define FN_INDEX(code)  ((code) - KC_FN0)
+#define FN_MIN          KC_FN0
+#define FN_MAX          KC_FN31
+
+
+/*
+ * Short names for ease of definition of keymap
+ */
+#define KC_LCTL KC_LCTRL
+#define KC_RCTL KC_RCTRL
+#define KC_LSFT KC_LSHIFT
+#define KC_RSFT KC_RSHIFT
+#define KC_ESC  KC_ESCAPE
+#define KC_BSPC KC_BSPACE
+#define KC_ENT  KC_ENTER
+#define KC_DEL  KC_DELETE
+#define KC_INS  KC_INSERT
+#define KC_CAPS KC_CAPSLOCK
+#define KC_CLCK KC_CAPSLOCK
+#define KC_RGHT KC_RIGHT
+#define KC_PGDN KC_PGDOWN
+#define KC_PSCR KC_PSCREEN
+#define KC_SLCK KC_SCROLLLOCK
+#define KC_PAUS KC_PAUSE
+#define KC_BRK  KC_PAUSE
+#define KC_NLCK KC_NUMLOCK
+#define KC_SPC  KC_SPACE
+#define KC_MINS KC_MINUS
+#define KC_EQL  KC_EQUAL
+#define KC_GRV  KC_GRAVE
+#define KC_RBRC KC_RBRACKET
+#define KC_LBRC KC_LBRACKET
+#define KC_COMM KC_COMMA
+#define KC_BSLS KC_BSLASH
+#define KC_SLSH KC_SLASH
+#define KC_SCLN KC_SCOLON
+#define KC_QUOT KC_QUOTE
+#define KC_APP  KC_APPLICATION
+#define KC_NUHS KC_NONUS_HASH
+#define KC_NUBS KC_NONUS_BSLASH
+#define KC_LCAP KC_LOCKING_CAPS
+#define KC_LNUM KC_LOCKING_NUM
+#define KC_LSCR KC_LOCKING_SCROLL
+#define KC_ERAS KC_ALT_ERASE,
+#define KC_CLR  KC_CLEAR
+/* Japanese specific */
+#define KC_ZKHK KC_GRAVE
+#define KC_RO   KC_INT1
+#define KC_KANA KC_INT2
+#define KC_JYEN KC_INT3
+#define KC_HENK KC_INT4
+#define KC_MHEN KC_INT5
+/* Keypad */
+#define KC_P1   KC_KP_1
+#define KC_P2   KC_KP_2
+#define KC_P3   KC_KP_3
+#define KC_P4   KC_KP_4
+#define KC_P5   KC_KP_5
+#define KC_P6   KC_KP_6
+#define KC_P7   KC_KP_7
+#define KC_P8   KC_KP_8
+#define KC_P9   KC_KP_9
+#define KC_P0   KC_KP_0
+#define KC_PDOT KC_KP_DOT
+#define KC_PCMM KC_KP_COMMA
+#define KC_PSLS KC_KP_SLASH
+#define KC_PAST KC_KP_ASTERISK
+#define KC_PMNS KC_KP_MINUS
+#define KC_PPLS KC_KP_PLUS
+#define KC_PEQL KC_KP_EQUAL
+#define KC_PENT KC_KP_ENTER
+/* Mousekey */
+#define KC_MS_U KC_MS_UP
+#define KC_MS_D KC_MS_DOWN
+#define KC_MS_L KC_MS_LEFT
+#define KC_MS_R KC_MS_RIGHT
+#define KC_BTN1 KC_MS_BTN1
+#define KC_BTN2 KC_MS_BTN2
+#define KC_BTN3 KC_MS_BTN3
+#define KC_BTN4 KC_MS_BTN4
+#define KC_BTN5 KC_MS_BTN5
+#define KC_WH_U KC_MS_WH_UP
+#define KC_WH_D KC_MS_WH_DOWN
+#define KC_WH_L KC_MS_WH_LEFT
+#define KC_WH_R KC_MS_WH_RIGHT
+#define KC_ACL0 KC_MS_ACCEL0
+#define KC_ACL1 KC_MS_ACCEL1
+#define KC_ACL2 KC_MS_ACCEL2
+/* Sytem Control */
+#define KC_PWR  KC_SYSTEM_POWER
+#define KC_SLEP KC_SYSTEM_SLEEP
+#define KC_WAKE KC_SYSTEM_WAKE
+/* Consumer Page */
+#define KC_MUTE KC_AUDIO_MUTE
+#define KC_VOLU KC_AUDIO_VOL_UP
+#define KC_VOLD KC_AUDIO_VOL_DOWN
+#define KC_MNXT KC_MEDIA_NEXT_TRACK
+#define KC_MPRV KC_MEDIA_PREV_TRACK
+#define KC_MFFD KC_MEDIA_FAST_FORWARD
+#define KC_MRWD KC_MEDIA_REWIND
+#define KC_MSTP KC_MEDIA_STOP
+#define KC_MPLY KC_MEDIA_PLAY_PAUSE
+#define KC_MSEL KC_MEDIA_SELECT
+#define KC_EJCT KC_MEDIA_EJECT
+#define KC_MAIL KC_MAIL
+#define KC_CALC KC_CALCULATOR
+#define KC_MYCM KC_MY_COMPUTER
+#define KC_WSCH KC_WWW_SEARCH
+#define KC_WHOM KC_WWW_HOME
+#define KC_WBAK KC_WWW_BACK
+#define KC_WFWD KC_WWW_FORWARD
+#define KC_WSTP KC_WWW_STOP
+#define KC_WREF KC_WWW_REFRESH
+#define KC_WFAV KC_WWW_FAVORITES
+/* Transparent */
+#define KC_TRANSPARENT  1
+#define KC_TRNS KC_TRANSPARENT
+
+
+
+/* USB HID Keyboard/Keypad Usage(0x07) */
+enum hid_keyboard_keypad_usage {
+    KC_NO               = 0x00,
+    KC_ROLL_OVER,
+    KC_POST_FAIL,
+    KC_UNDEFINED,
+    KC_A,
+    KC_B,
+    KC_C,
+    KC_D,
+    KC_E,
+    KC_F,
+    KC_G,
+    KC_H,
+    KC_I,
+    KC_J,
+    KC_K,
+    KC_L,
+    KC_M,               /* 0x10 */
+    KC_N,
+    KC_O,
+    KC_P,
+    KC_Q,
+    KC_R,
+    KC_S,
+    KC_T,
+    KC_U,
+    KC_V,
+    KC_W,
+    KC_X,
+    KC_Y,
+    KC_Z,
+    KC_1,
+    KC_2,
+    KC_3,               /* 0x20 */
+    KC_4,
+    KC_5,
+    KC_6,
+    KC_7,
+    KC_8,
+    KC_9,
+    KC_0,
+    KC_ENTER,
+    KC_ESCAPE,
+    KC_BSPACE,
+    KC_TAB,
+    KC_SPACE,
+    KC_MINUS,
+    KC_EQUAL,
+    KC_LBRACKET,
+    KC_RBRACKET,        /* 0x30 */
+    KC_BSLASH,          /* \ (and |) */
+    KC_NONUS_HASH,      /* Non-US # and ~ */
+    KC_SCOLON,          /* ; (and :) */
+    KC_QUOTE,           /* ' and " */
+    KC_GRAVE,           /* Grave accent and tilde */
+    KC_COMMA,           /* , and < */
+    KC_DOT,             /* . and > */
+    KC_SLASH,           /* / and ? */
+    KC_CAPSLOCK,
+    KC_F1,
+    KC_F2,
+    KC_F3,
+    KC_F4,
+    KC_F5,
+    KC_F6,
+    KC_F7,              /* 0x40 */
+    KC_F8,
+    KC_F9,
+    KC_F10,
+    KC_F11,
+    KC_F12,
+    KC_PSCREEN,
+    KC_SCROLLLOCK,
+    KC_PAUSE,
+    KC_INSERT,
+    KC_HOME,
+    KC_PGUP,
+    KC_DELETE,
+    KC_END,
+    KC_PGDOWN,
+    KC_RIGHT,
+    KC_LEFT,            /* 0x50 */
+    KC_DOWN,
+    KC_UP,
+    KC_NUMLOCK,
+    KC_KP_SLASH,
+    KC_KP_ASTERISK,
+    KC_KP_MINUS,
+    KC_KP_PLUS,
+    KC_KP_ENTER,
+    KC_KP_1,
+    KC_KP_2,
+    KC_KP_3,
+    KC_KP_4,
+    KC_KP_5,
+    KC_KP_6,
+    KC_KP_7,
+    KC_KP_8,            /* 0x60 */
+    KC_KP_9,
+    KC_KP_0,
+    KC_KP_DOT,
+    KC_NONUS_BSLASH,    /* Non-US \ and | */
+    KC_APPLICATION,
+    KC_POWER,
+    KC_KP_EQUAL,
+    KC_F13,
+    KC_F14,
+    KC_F15,
+    KC_F16,
+    KC_F17,
+    KC_F18,
+    KC_F19,
+    KC_F20,
+    KC_F21,             /* 0x70 */
+    KC_F22,
+    KC_F23,
+    KC_F24,
+    KC_EXECUTE,
+    KC_HELP,
+    KC_MENU,
+    KC_SELECT,
+    KC_STOP,
+    KC_AGAIN,
+    KC_UNDO,
+    KC_CUT,
+    KC_COPY,
+    KC_PASTE,
+    KC_FIND,
+    KC__MUTE,
+    KC__VOLUP,          /* 0x80 */
+    KC__VOLDOWN,
+    KC_LOCKING_CAPS,    /* locking Caps Lock */
+    KC_LOCKING_NUM,     /* locking Num Lock */
+    KC_LOCKING_SCROLL,  /* locking Scroll Lock */
+    KC_KP_COMMA,
+    KC_KP_EQUAL_AS400,  /* equal sign on AS/400 */
+    KC_INT1,
+    KC_INT2,
+    KC_INT3,
+    KC_INT4,
+    KC_INT5,
+    KC_INT6,
+    KC_INT7,
+    KC_INT8,
+    KC_INT9,
+    KC_LANG1,           /* 0x90 */
+    KC_LANG2,
+    KC_LANG3,
+    KC_LANG4,
+    KC_LANG5,
+    KC_LANG6,
+    KC_LANG7,
+    KC_LANG8,
+    KC_LANG9,
+    KC_ALT_ERASE,
+    KC_SYSREQ,
+    KC_CANCEL,
+    KC_CLEAR,
+    KC_PRIOR,
+    KC_RETURN,
+    KC_SEPARATOR,
+    KC_OUT,             /* 0xA0 */
+    KC_OPER,
+    KC_CLEAR_AGAIN,
+    KC_CRSEL,
+    KC_EXSEL,           /* 0xA4 */
+
+    /* NOTE: 0xA5-DF are used for internal special purpose */
+
+#if 0
+    /* NOTE: Following codes(0xB0-DD) are not used. Leave them for reference. */
+    KC_KP_00            = 0xB0,
+    KC_KP_000,
+    KC_THOUSANDS_SEPARATOR,
+    KC_DECIMAL_SEPARATOR,
+    KC_CURRENCY_UNIT,
+    KC_CURRENCY_SUB_UNIT,
+    KC_KP_LPAREN,
+    KC_KP_RPAREN,
+    KC_KP_LCBRACKET,    /* { */
+    KC_KP_RCBRACKET,    /* } */
+    KC_KP_TAB,
+    KC_KP_BSPACE,
+    KC_KP_A,
+    KC_KP_B,
+    KC_KP_C,
+    KC_KP_D,
+    KC_KP_E,            /* 0xC0 */
+    KC_KP_F,
+    KC_KP_XOR,
+    KC_KP_HAT,
+    KC_KP_PERC,
+    KC_KP_LT,
+    KC_KP_GT,
+    KC_KP_AND,
+    KC_KP_LAZYAND,
+    KC_KP_OR,
+    KC_KP_LAZYOR,
+    KC_KP_COLON,
+    KC_KP_HASH,
+    KC_KP_SPACE,
+    KC_KP_ATMARK,
+    KC_KP_EXCLAMATION,
+    KC_KP_MEM_STORE,    /* 0xD0 */
+    KC_KP_MEM_RECALL,
+    KC_KP_MEM_CLEAR,
+    KC_KP_MEM_ADD,
+    KC_KP_MEM_SUB,
+    KC_KP_MEM_MUL,
+    KC_KP_MEM_DIV,
+    KC_KP_PLUS_MINUS,
+    KC_KP_CLEAR,
+    KC_KP_CLEAR_ENTRY,
+    KC_KP_BINARY,
+    KC_KP_OCTAL,
+    KC_KP_DECIMAL,
+    KC_KP_HEXADECIMAL,  /* 0xDD */
+#endif
+
+    /* Modifiers */
+    KC_LCTRL            = 0xE0,
+    KC_LSHIFT,
+    KC_LALT,
+    KC_LGUI,
+    KC_RCTRL,
+    KC_RSHIFT,
+    KC_RALT,
+    KC_RGUI,
+
+    /* NOTE: 0xE8-FF are used for internal special purpose */
+};
+
+/* Special keycodes */
+/* NOTE: 0xA5-DF and 0xE8-FF are used for internal special purpose */
+enum internal_special_keycodes {
+    /* System Control */
+    KC_SYSTEM_POWER     = 0xA5,
+    KC_SYSTEM_SLEEP,
+    KC_SYSTEM_WAKE,
+
+    /* Media Control */
+    KC_AUDIO_MUTE,
+    KC_AUDIO_VOL_UP,
+    KC_AUDIO_VOL_DOWN,
+    KC_MEDIA_NEXT_TRACK,
+    KC_MEDIA_PREV_TRACK,
+    KC_MEDIA_STOP,
+    KC_MEDIA_PLAY_PAUSE,
+    KC_MEDIA_SELECT,
+    KC_MEDIA_EJECT,
+    KC_MAIL,
+    KC_CALCULATOR,
+    KC_MY_COMPUTER,
+    KC_WWW_SEARCH,
+    KC_WWW_HOME,
+    KC_WWW_BACK,
+    KC_WWW_FORWARD,
+    KC_WWW_STOP,
+    KC_WWW_REFRESH,
+    KC_WWW_FAVORITES,
+    KC_MEDIA_FAST_FORWARD,
+    KC_MEDIA_REWIND,    /* 0xBC */
+
+    /* Fn key */
+    KC_FN0              = 0xC0,
+    KC_FN1,
+    KC_FN2,
+    KC_FN3,
+    KC_FN4,
+    KC_FN5,
+    KC_FN6,
+    KC_FN7,
+    KC_FN8,
+    KC_FN9,
+    KC_FN10,
+    KC_FN11,
+    KC_FN12,
+    KC_FN13,
+    KC_FN14,
+    KC_FN15,
+
+    KC_FN16             = 0xD0,
+    KC_FN17,
+    KC_FN18,
+    KC_FN19,
+    KC_FN20,
+    KC_FN21,
+    KC_FN22,
+    KC_FN23,
+    KC_FN24,
+    KC_FN25,
+    KC_FN26,
+    KC_FN27,
+    KC_FN28,
+    KC_FN29,
+    KC_FN30,
+    KC_FN31,            /* 0xDF */
+
+    /**************************************/
+    /* 0xE0-E7 for Modifiers. DO NOT USE. */
+    /**************************************/
+
+    /* Mousekey */
+    KC_MS_UP            = 0xF0,
+    KC_MS_DOWN,
+    KC_MS_LEFT,
+    KC_MS_RIGHT,
+    KC_MS_BTN1,
+    KC_MS_BTN2,
+    KC_MS_BTN3,
+    KC_MS_BTN4,
+    KC_MS_BTN5,         /* 0xF8 */
+    /* Mousekey wheel */
+    KC_MS_WH_UP,
+    KC_MS_WH_DOWN,
+    KC_MS_WH_LEFT,
+    KC_MS_WH_RIGHT,     /* 0xFC */
+    /* Mousekey accel */
+    KC_MS_ACCEL0,
+    KC_MS_ACCEL1,
+    KC_MS_ACCEL2        /* 0xFF */
+};
+
+#endif /* KEYCODE_H */
diff --git a/common/keymap.c b/common/keymap.c
new file mode 100644 (file)
index 0000000..4c0b61b
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "keymap.h"
+#include "report.h"
+#include "keycode.h"
+#include "action_layer.h"
+#include "action.h"
+#include "action_macro.h"
+#include "debug.h"
+
+
+static action_t keycode_to_action(uint8_t keycode);
+
+
+/* converts key to action */
+action_t action_for_key(uint8_t layer, keypos_t key)
+{
+    uint8_t keycode = keymap_key_to_keycode(layer, key);
+    switch (keycode) {
+        case KC_FN0 ... KC_FN31:
+            return keymap_fn_to_action(keycode);
+#ifdef BOOTMAGIC_ENABLE
+        case KC_CAPSLOCK:
+        case KC_LOCKING_CAPS:
+            if (keymap_config.swap_control_capslock || keymap_config.capslock_to_control) {
+                return keycode_to_action(KC_LCTL);
+            }
+            return keycode_to_action(keycode);
+        case KC_LCTL:
+            if (keymap_config.swap_control_capslock) {
+                return keycode_to_action(KC_CAPSLOCK);
+            }
+            return keycode_to_action(KC_LCTL);
+        case KC_LALT:
+            if (keymap_config.swap_lalt_lgui) {
+                if (keymap_config.no_gui) {
+                    return keycode_to_action(ACTION_NO);
+                }
+                return keycode_to_action(KC_LGUI);
+            }
+            return keycode_to_action(KC_LALT);
+        case KC_LGUI:
+            if (keymap_config.swap_lalt_lgui) {
+                return keycode_to_action(KC_LALT);
+            }
+            if (keymap_config.no_gui) {
+                return keycode_to_action(ACTION_NO);
+            }
+            return keycode_to_action(KC_LGUI);
+        case KC_RALT:
+            if (keymap_config.swap_ralt_rgui) {
+                if (keymap_config.no_gui) {
+                    return keycode_to_action(ACTION_NO);
+                }
+                return keycode_to_action(KC_RGUI);
+            }
+            return keycode_to_action(KC_RALT);
+        case KC_RGUI:
+            if (keymap_config.swap_ralt_rgui) {
+                return keycode_to_action(KC_RALT);
+            }
+            if (keymap_config.no_gui) {
+                return keycode_to_action(ACTION_NO);
+            }
+            return keycode_to_action(KC_RGUI);
+        case KC_GRAVE:
+            if (keymap_config.swap_grave_esc) {
+                return keycode_to_action(KC_ESC);
+            }
+            return keycode_to_action(KC_GRAVE);
+        case KC_ESC:
+            if (keymap_config.swap_grave_esc) {
+                return keycode_to_action(KC_GRAVE);
+            }
+            return keycode_to_action(KC_ESC);
+        case KC_BSLASH:
+            if (keymap_config.swap_backslash_backspace) {
+                return keycode_to_action(KC_BSPACE);
+            }
+            return keycode_to_action(KC_BSLASH);
+        case KC_BSPACE:
+            if (keymap_config.swap_backslash_backspace) {
+                return keycode_to_action(KC_BSLASH);
+            }
+            return keycode_to_action(KC_BSPACE);
+#endif
+        default:
+            return keycode_to_action(keycode);
+    }
+}
+
+
+/* Macro */
+__attribute__ ((weak))
+const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+    return MACRO_NONE;
+}
+
+/* Function */
+__attribute__ ((weak))
+void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
+{
+}
+
+
+
+/* translates keycode to action */
+static action_t keycode_to_action(uint8_t keycode)
+{
+    action_t action;
+    switch (keycode) {
+        case KC_A ... KC_EXSEL:
+        case KC_LCTRL ... KC_RGUI:
+            action.code = ACTION_KEY(keycode);
+            break;
+        case KC_SYSTEM_POWER ... KC_SYSTEM_WAKE:
+            action.code = ACTION_USAGE_SYSTEM(KEYCODE2SYSTEM(keycode));
+            break;
+        case KC_AUDIO_MUTE ... KC_WWW_FAVORITES:
+            action.code = ACTION_USAGE_CONSUMER(KEYCODE2CONSUMER(keycode));
+            break;
+        case KC_MS_UP ... KC_MS_ACCEL2:
+            action.code = ACTION_MOUSEKEY(keycode);
+            break;
+        case KC_TRNS:
+            action.code = ACTION_TRANSPARENT;
+            break;
+        default:
+            action.code = ACTION_NO;
+            break;
+    }
+    return action;
+}
+
+
+
+#ifdef USE_LEGACY_KEYMAP
+/*
+ * Legacy keymap support
+ *      Consider using new keymap API instead.
+ */
+__attribute__ ((weak))
+uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key)
+{
+    return keymap_get_keycode(layer, key.row, key.col);
+}
+
+
+/* Legacy keymap support */
+__attribute__ ((weak))
+action_t keymap_fn_to_action(uint8_t keycode)
+{
+    action_t action = { .code = ACTION_NO };
+    switch (keycode) {
+        case KC_FN0 ... KC_FN31:
+            {
+                uint8_t layer = keymap_fn_layer(FN_INDEX(keycode));
+                uint8_t key = keymap_fn_keycode(FN_INDEX(keycode));
+                if (key) {
+                    action.code = ACTION_LAYER_TAP_KEY(layer, key);
+                } else {
+                    action.code = ACTION_LAYER_MOMENTARY(layer);
+                }
+            }
+            return action;
+        default:
+            return action;
+    }
+}
+#endif
diff --git a/common/keymap.h b/common/keymap.h
new file mode 100644 (file)
index 0000000..e1a6f99
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef KEYMAP_H
+#define KEYMAP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "action.h"
+
+
+#ifdef BOOTMAGIC_ENABLE
+/* NOTE: Not portable. Bit field order depends on implementation */
+typedef union {
+    uint8_t raw;
+    struct {
+        bool swap_control_capslock:1;
+        bool capslock_to_control:1;
+        bool swap_lalt_lgui:1;
+        bool swap_ralt_rgui:1;
+        bool no_gui:1;
+        bool swap_grave_esc:1;
+        bool swap_backslash_backspace:1;
+        bool nkro:1;
+    };
+} keymap_config_t;
+keymap_config_t keymap_config;
+#endif
+
+
+/* translates key to keycode */
+uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key);
+
+/* translates Fn keycode to action */
+action_t keymap_fn_to_action(uint8_t keycode);
+
+
+
+#ifdef USE_LEGACY_KEYMAP
+/* 
+ * Legacy keymap
+ *      Consider using new keymap API above instead.
+ */
+/* keycode of key */
+__attribute__ ((deprecated))
+uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col);
+
+/* layer to move during press Fn key */
+__attribute__ ((deprecated))
+uint8_t keymap_fn_layer(uint8_t fn_bits);
+
+/* keycode to send when release Fn key without using */
+__attribute__ ((deprecated))
+uint8_t keymap_fn_keycode(uint8_t fn_bits);
+#endif
+
+#endif
diff --git a/common/led.h b/common/led.h
new file mode 100644 (file)
index 0000000..402a247
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef LED_H
+#define LED_H
+#include "stdint.h"
+
+
+/* keyboard LEDs */
+#define USB_LED_NUM_LOCK                0
+#define USB_LED_CAPS_LOCK               1
+#define USB_LED_SCROLL_LOCK             2
+#define USB_LED_COMPOSE                 3
+#define USB_LED_KANA                    4
+
+
+void led_set(uint8_t usb_led);
+
+#endif
diff --git a/common/matrix.h b/common/matrix.h
new file mode 100644 (file)
index 0000000..107ee72
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+
+#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 "MATRIX_COLS: invalid value"
+#endif
+
+#define MATRIX_IS_ON(row, col)  (matrix_get_row(row) && (1<<col))
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* number of matrix rows */
+uint8_t matrix_rows(void);
+/* number of matrix columns */
+uint8_t matrix_cols(void);
+/* intialize matrix for scaning. should be called once. */
+void matrix_init(void);
+/* scan all key states on matrix */
+uint8_t matrix_scan(void);
+/* whether modified from previous scan. used after matrix_scan. */
+bool matrix_is_modified(void) __attribute__ ((deprecated));
+/* whether a swtich is on */
+bool matrix_is_on(uint8_t row, uint8_t col);
+/* matrix state on row */
+matrix_row_t matrix_get_row(uint8_t row);
+/* print matrix for debug */
+void matrix_print(void);
+
+
+/* power control */
+void matrix_power_up(void);
+void matrix_power_down(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/mbed/bootloader.c b/common/mbed/bootloader.c
new file mode 100644 (file)
index 0000000..b51e839
--- /dev/null
@@ -0,0 +1,4 @@
+#include "bootloader.h"
+
+
+void bootloader_jump(void) {}
diff --git a/common/mbed/suspend.c b/common/mbed/suspend.c
new file mode 100644 (file)
index 0000000..3265157
--- /dev/null
@@ -0,0 +1,6 @@
+#include <stdbool.h>
+
+
+void suspend_power_down(void) {}
+bool suspend_wakeup_condition(void) { return true; }
+void suspend_wakeup_init(void) {}
diff --git a/common/mbed/timer.c b/common/mbed/timer.c
new file mode 100644 (file)
index 0000000..c357ceb
--- /dev/null
@@ -0,0 +1,41 @@
+#include "cmsis.h"
+#include "timer.h"
+
+/* Mill second tick count */
+volatile uint32_t timer_count = 0;
+
+/* Timer interrupt handler */
+void SysTick_Handler(void)  {
+    timer_count++;
+}
+
+void timer_init(void)
+{
+    timer_count = 0;
+    SysTick_Config(SystemCoreClock / 1000); /* 1ms tick */
+}
+
+void timer_clear(void)
+{
+    timer_count = 0;
+}
+
+uint16_t timer_read(void)
+{
+    return (uint16_t)(timer_count & 0xFFFF);
+}
+
+uint32_t timer_read32(void)
+{
+    return timer_count;
+}
+
+uint16_t timer_elapsed(uint16_t last)
+{
+    return TIMER_DIFF_16(timer_read(), last);
+}
+
+uint32_t timer_elapsed32(uint32_t last)
+{
+    return TIMER_DIFF_32(timer_read32(), last);
+}
diff --git a/common/mbed/xprintf.cpp b/common/mbed/xprintf.cpp
new file mode 100644 (file)
index 0000000..3647ece
--- /dev/null
@@ -0,0 +1,51 @@
+#include <cstdarg>
+//#include <stdarg.h>
+#include "mbed.h"
+#include "mbed/xprintf.h"
+
+
+#define STRING_STACK_LIMIT    120
+
+//TODO
+int xprintf(const char* format, ...) { return 0; }
+
+#if 0
+/* mbed Serial */
+Serial ser(UART_TX, UART_RX);
+
+/* TODO: Need small implementation for embedded */
+int xprintf(const char* format, ...)
+{
+    /* copy from mbed/common/RawSerial.cpp */
+    std::va_list arg;
+    va_start(arg, format);
+    int len = vsnprintf(NULL, 0, format, arg);
+    if (len < STRING_STACK_LIMIT) {
+        char temp[STRING_STACK_LIMIT];
+        vsprintf(temp, format, arg);
+        ser.puts(temp);
+    } else {
+        char *temp = new char[len + 1];
+        vsprintf(temp, format, arg);
+        ser.puts(temp);
+        delete[] temp;
+    }
+    va_end(arg);
+    return len;
+
+/* Fail: __builtin_va_arg_pack?
+ * https://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/Constructing-Calls.html#Constructing-Calls
+    void *arg = __builtin_apply_args();
+    void *ret = __builtin_apply((void*)(&(ser.printf)), arg, 100);
+    __builtin_return(ret)
+*/
+/* Fail: varargs can not be passed to printf
+    //int r = ser.printf("test %i\r\n", 123);
+    va_list arg;
+    va_start(arg, format);
+    int r = ser.printf(format, arg);
+    va_end(arg);
+    return r;
+*/
+}
+#endif
diff --git a/common/mbed/xprintf.h b/common/mbed/xprintf.h
new file mode 100644 (file)
index 0000000..26bc529
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef XPRINTF_H
+#define XPRINTF_H
+
+//#define xprintf(format, ...)            __xprintf(format, ##__VA_ARGS__)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int xprintf(const char *format, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/common/mousekey.c b/common/mousekey.c
new file mode 100644 (file)
index 0000000..2346947
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdint.h>
+#include "keycode.h"
+#include "host.h"
+#include "timer.h"
+#include "print.h"
+#include "debug.h"
+#include "mousekey.h"
+
+
+
+static report_mouse_t mouse_report = {};
+static uint8_t mousekey_repeat =  0;
+static uint8_t mousekey_accel = 0;
+
+static void mousekey_debug(void);
+
+
+/*
+ * Mouse keys  acceleration algorithm
+ *  http://en.wikipedia.org/wiki/Mouse_keys
+ *
+ *  speed = delta * max_speed * (repeat / time_to_max)**((1000+curve)/1000)
+ */
+/* milliseconds between the initial key press and first repeated motion event (0-2550) */
+uint8_t mk_delay = MOUSEKEY_DELAY/10;
+/* milliseconds between repeated motion events (0-255) */
+uint8_t mk_interval = MOUSEKEY_INTERVAL;
+/* steady speed (in action_delta units) applied each event (0-255) */
+uint8_t mk_max_speed = MOUSEKEY_MAX_SPEED;
+/* number of events (count) accelerating to steady speed (0-255) */
+uint8_t mk_time_to_max = MOUSEKEY_TIME_TO_MAX;
+/* ramp used to reach maximum pointer speed (NOT SUPPORTED) */
+//int8_t mk_curve = 0;
+/* wheel params */
+uint8_t mk_wheel_max_speed = MOUSEKEY_WHEEL_MAX_SPEED;
+uint8_t mk_wheel_time_to_max = MOUSEKEY_WHEEL_TIME_TO_MAX;
+
+
+static uint16_t last_timer = 0;
+
+
+static uint8_t move_unit(void)
+{
+    uint16_t unit;
+    if (mousekey_accel & (1<<0)) {
+        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/4;
+    } else if (mousekey_accel & (1<<1)) {
+        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed)/2;
+    } else if (mousekey_accel & (1<<2)) {
+        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed);
+    } else if (mousekey_repeat == 0) {
+        unit = MOUSEKEY_MOVE_DELTA;
+    } else if (mousekey_repeat >= mk_time_to_max) {
+        unit = MOUSEKEY_MOVE_DELTA * mk_max_speed;
+    } else {
+        unit = (MOUSEKEY_MOVE_DELTA * mk_max_speed * mousekey_repeat) / mk_time_to_max;
+    }
+    return (unit > MOUSEKEY_MOVE_MAX ? MOUSEKEY_MOVE_MAX : (unit == 0 ? 1 : unit));
+}
+
+static uint8_t wheel_unit(void)
+{
+    uint16_t unit;
+    if (mousekey_accel & (1<<0)) {
+        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/4;
+    } else if (mousekey_accel & (1<<1)) {
+        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed)/2;
+    } else if (mousekey_accel & (1<<2)) {
+        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed);
+    } else if (mousekey_repeat == 0) {
+        unit = MOUSEKEY_WHEEL_DELTA;
+    } else if (mousekey_repeat >= mk_wheel_time_to_max) {
+        unit = MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed;
+    } else {
+        unit = (MOUSEKEY_WHEEL_DELTA * mk_wheel_max_speed * mousekey_repeat) / mk_wheel_time_to_max;
+    }
+    return (unit > MOUSEKEY_WHEEL_MAX ? MOUSEKEY_WHEEL_MAX : (unit == 0 ? 1 : unit));
+}
+
+void mousekey_task(void)
+{
+    if (timer_elapsed(last_timer) < (mousekey_repeat ? mk_interval : mk_delay*10))
+        return;
+
+    if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+        return;
+
+    if (mousekey_repeat != UINT8_MAX)
+        mousekey_repeat++;
+
+
+    if (mouse_report.x > 0) mouse_report.x = move_unit();
+    if (mouse_report.x < 0) mouse_report.x = move_unit() * -1;
+    if (mouse_report.y > 0) mouse_report.y = move_unit();
+    if (mouse_report.y < 0) mouse_report.y = move_unit() * -1;
+
+    /* diagonal move [1/sqrt(2) = 0.7] */
+    if (mouse_report.x && mouse_report.y) {
+        mouse_report.x *= 0.7;
+        mouse_report.y *= 0.7;
+    }
+
+    if (mouse_report.v > 0) mouse_report.v = wheel_unit();
+    if (mouse_report.v < 0) mouse_report.v = wheel_unit() * -1;
+    if (mouse_report.h > 0) mouse_report.h = wheel_unit();
+    if (mouse_report.h < 0) mouse_report.h = wheel_unit() * -1;
+
+    mousekey_send();
+}
+
+void mousekey_on(uint8_t code)
+{
+    if      (code == KC_MS_UP)       mouse_report.y = move_unit() * -1;
+    else if (code == KC_MS_DOWN)     mouse_report.y = move_unit();
+    else if (code == KC_MS_LEFT)     mouse_report.x = move_unit() * -1;
+    else if (code == KC_MS_RIGHT)    mouse_report.x = move_unit();
+    else if (code == KC_MS_WH_UP)    mouse_report.v = wheel_unit();
+    else if (code == KC_MS_WH_DOWN)  mouse_report.v = wheel_unit() * -1;
+    else if (code == KC_MS_WH_LEFT)  mouse_report.h = wheel_unit() * -1;
+    else if (code == KC_MS_WH_RIGHT) mouse_report.h = wheel_unit();
+    else if (code == KC_MS_BTN1)     mouse_report.buttons |= MOUSE_BTN1;
+    else if (code == KC_MS_BTN2)     mouse_report.buttons |= MOUSE_BTN2;
+    else if (code == KC_MS_BTN3)     mouse_report.buttons |= MOUSE_BTN3;
+    else if (code == KC_MS_BTN4)     mouse_report.buttons |= MOUSE_BTN4;
+    else if (code == KC_MS_BTN5)     mouse_report.buttons |= MOUSE_BTN5;
+    else if (code == KC_MS_ACCEL0)   mousekey_accel |= (1<<0);
+    else if (code == KC_MS_ACCEL1)   mousekey_accel |= (1<<1);
+    else if (code == KC_MS_ACCEL2)   mousekey_accel |= (1<<2);
+}
+
+void mousekey_off(uint8_t code)
+{
+    if      (code == KC_MS_UP       && mouse_report.y < 0) mouse_report.y = 0;
+    else if (code == KC_MS_DOWN     && mouse_report.y > 0) mouse_report.y = 0;
+    else if (code == KC_MS_LEFT     && mouse_report.x < 0) mouse_report.x = 0;
+    else if (code == KC_MS_RIGHT    && mouse_report.x > 0) mouse_report.x = 0;
+    else if (code == KC_MS_WH_UP    && mouse_report.v > 0) mouse_report.v = 0;
+    else if (code == KC_MS_WH_DOWN  && mouse_report.v < 0) mouse_report.v = 0;
+    else if (code == KC_MS_WH_LEFT  && mouse_report.h < 0) mouse_report.h = 0;
+    else if (code == KC_MS_WH_RIGHT && mouse_report.h > 0) mouse_report.h = 0;
+    else if (code == KC_MS_BTN1) mouse_report.buttons &= ~MOUSE_BTN1;
+    else if (code == KC_MS_BTN2) mouse_report.buttons &= ~MOUSE_BTN2;
+    else if (code == KC_MS_BTN3) mouse_report.buttons &= ~MOUSE_BTN3;
+    else if (code == KC_MS_BTN4) mouse_report.buttons &= ~MOUSE_BTN4;
+    else if (code == KC_MS_BTN5) mouse_report.buttons &= ~MOUSE_BTN5;
+    else if (code == KC_MS_ACCEL0) mousekey_accel &= ~(1<<0);
+    else if (code == KC_MS_ACCEL1) mousekey_accel &= ~(1<<1);
+    else if (code == KC_MS_ACCEL2) mousekey_accel &= ~(1<<2);
+
+    if (mouse_report.x == 0 && mouse_report.y == 0 && mouse_report.v == 0 && mouse_report.h == 0)
+        mousekey_repeat = 0;
+}
+
+void mousekey_send(void)
+{
+    mousekey_debug();
+    host_mouse_send(&mouse_report);
+    last_timer = timer_read();
+}
+
+void mousekey_clear(void)
+{
+    mouse_report = (report_mouse_t){};
+    mousekey_repeat = 0;
+    mousekey_accel = 0;
+}
+
+static void mousekey_debug(void)
+{
+    if (!debug_mouse) return;
+    print("mousekey [btn|x y v h](rep/acl): [");
+    phex(mouse_report.buttons); print("|");
+    print_decs(mouse_report.x); print(" ");
+    print_decs(mouse_report.y); print(" ");
+    print_decs(mouse_report.v); print(" ");
+    print_decs(mouse_report.h); print("](");
+    print_dec(mousekey_repeat); print("/");
+    print_dec(mousekey_accel); print(")\n");
+}
diff --git a/common/mousekey.h b/common/mousekey.h
new file mode 100644 (file)
index 0000000..6eede06
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef MOUSEKEY_H
+#define  MOUSEKEY_H
+
+#include <stdbool.h>
+#include "host.h"
+
+
+/* max value on report descriptor */
+#define MOUSEKEY_MOVE_MAX       127
+#define MOUSEKEY_WHEEL_MAX      127
+
+#ifndef MOUSEKEY_MOVE_DELTA
+#define MOUSEKEY_MOVE_DELTA     5
+#endif
+#ifndef MOUSEKEY_WHEEL_DELTA
+#define MOUSEKEY_WHEEL_DELTA    1
+#endif
+#ifndef MOUSEKEY_DELAY
+#define MOUSEKEY_DELAY 300
+#endif
+#ifndef MOUSEKEY_INTERVAL
+#define MOUSEKEY_INTERVAL 50
+#endif
+#ifndef MOUSEKEY_MAX_SPEED
+#define MOUSEKEY_MAX_SPEED 10
+#endif
+#ifndef MOUSEKEY_TIME_TO_MAX
+#define MOUSEKEY_TIME_TO_MAX 20
+#endif
+#ifndef MOUSEKEY_WHEEL_MAX_SPEED
+#define MOUSEKEY_WHEEL_MAX_SPEED 8
+#endif
+#ifndef MOUSEKEY_WHEEL_TIME_TO_MAX
+#define MOUSEKEY_WHEEL_TIME_TO_MAX 40
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint8_t mk_delay;
+extern uint8_t mk_interval;
+extern uint8_t mk_max_speed;
+extern uint8_t mk_time_to_max;
+extern uint8_t mk_wheel_max_speed;
+extern uint8_t mk_wheel_time_to_max;
+
+
+void mousekey_task(void);
+void mousekey_on(uint8_t code);
+void mousekey_off(uint8_t code);
+void mousekey_clear(void);
+void mousekey_send(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/nodebug.h b/common/nodebug.h
new file mode 100644 (file)
index 0000000..93309ad
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+Copyright 2013 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef NODEBUG_H
+#define NODEBUG_H 1
+
+#define NO_DEBUG
+#include "debug.h"
+#undef NO_DEBUG
+
+#endif
diff --git a/common/print.c b/common/print.c
new file mode 100644 (file)
index 0000000..ca94e1e
--- /dev/null
@@ -0,0 +1,48 @@
+/* Copyright 2012,2013 Jun Wako <wakojun@gmail.com> */
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 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:
+ * 
+ * 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.
+ */
+
+#include <stdint.h>
+#include "print.h"
+
+
+#ifndef NO_PRINT
+
+#if defined(__AVR__)
+
+#define sendchar(c)    xputc(c)
+
+
+void print_set_sendchar(int8_t (*sendchar_func)(uint8_t))
+{
+    xdev_out(sendchar_func);
+}
+
+#elif defined(__arm__)
+
+// TODO
+//void print_set_sendchar(int8_t (*sendchar_func)(uint8_t)) { }
+
+#endif
+
+#endif
diff --git a/common/print.h b/common/print.h
new file mode 100644 (file)
index 0000000..c0e9e14
--- /dev/null
@@ -0,0 +1,137 @@
+/* Copyright 2012 Jun Wako <wakojun@gmail.com> */
+/* Very basic print functions, intended to be used with usb_debug_only.c
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2008 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:
+ * 
+ * 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.
+ */
+
+#ifndef PRINT_H__
+#define PRINT_H__ 1
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "util.h"
+
+
+
+
+#ifndef NO_PRINT
+
+
+#if defined(__AVR__)
+
+#include "avr/xprintf.h"
+#define print(s)    xputs(PSTR(s))
+#define println(s)  xputs(PSTR(s "\r\n"))
+
+#ifdef __cplusplus
+extern "C"
+#endif
+/* function pointer of sendchar to be used by print utility */
+void print_set_sendchar(int8_t (*print_sendchar_func)(uint8_t));
+
+#elif defined(__arm__)
+
+#include "mbed/xprintf.h"
+
+#define print(s)    xprintf(s)
+#define println(s)  xprintf(s "\r\n")
+
+/* TODO: to select output destinations: UART/USBSerial */
+#define print_set_sendchar(func)
+
+#endif /* __AVR__ */
+
+
+/* decimal */
+#define print_dec(i)                xprintf("%u", i)
+#define print_decs(i)               xprintf("%d", i)
+/* hex */
+#define print_hex4(i)               xprintf("%X", i)
+#define print_hex8(i)               xprintf("%02X", i)
+#define print_hex16(i)              xprintf("%04X", i)
+#define print_hex32(i)              xprintf("%08lX", i)
+/* binary */
+#define print_bin4(i)               xprintf("%04b", i)
+#define print_bin8(i)               xprintf("%08b", i)
+#define print_bin16(i)              xprintf("%016b", i)
+#define print_bin32(i)              xprintf("%032lb", i)
+#define print_bin_reverse8(i)       xprintf("%08b", bitrev(i))
+#define print_bin_reverse16(i)      xprintf("%016b", bitrev16(i))
+#define print_bin_reverse32(i)      xprintf("%032lb", bitrev32(i))
+/* print value utility */
+#define print_val_dec(v)            xprintf(#v ": %u\n", v)
+#define print_val_decs(v)           xprintf(#v ": %d\n", v)
+#define print_val_hex8(v)           xprintf(#v ": %X\n", v)
+#define print_val_hex16(v)          xprintf(#v ": %02X\n", v)
+#define print_val_hex32(v)          xprintf(#v ": %04lX\n", v)
+#define print_val_bin8(v)           xprintf(#v ": %08b\n", v)
+#define print_val_bin16(v)          xprintf(#v ": %016b\n", v)
+#define print_val_bin32(v)          xprintf(#v ": %032lb\n", v)
+#define print_val_bin_reverse8(v)   xprintf(#v ": %08b\n", bitrev(v))
+#define print_val_bin_reverse16(v)  xprintf(#v ": %016b\n", bitrev16(v))
+#define print_val_bin_reverse32(v)  xprintf(#v ": %032lb\n", bitrev32(v))
+
+#else   /* NO_PRINT */
+
+#define xprintf
+#define print
+#define println
+#define print_set_sendchar(func)
+#define print_dec(data)
+#define print_decs(data)
+#define print_hex4(data)
+#define print_hex8(data)
+#define print_hex16(data)
+#define print_hex32(data)
+#define print_bin4(data)
+#define print_bin8(data)
+#define print_bin16(data)
+#define print_bin32(data)
+#define print_bin_reverse8(data)
+#define print_bin_reverse16(data)
+#define print_bin_reverse32(data)
+#define print_val_dec(v)
+#define print_val_decs(v)
+#define print_val_hex8(v)
+#define print_val_hex16(v)
+#define print_val_hex32(v)
+#define print_val_bin8(v)
+#define print_val_bin16(v)
+#define print_val_bin32(v)
+#define print_val_bin_reverse8(v)
+#define print_val_bin_reverse16(v)
+#define print_val_bin_reverse32(v)
+
+#endif  /* NO_PRINT */
+
+
+/* Backward compatiblitly for old name */
+#define pdec(data)              print_dec(data)
+#define pdec16(data)            print_dec(data)
+#define phex(data)              print_hex8(data)
+#define phex16(data)            print_hex16(data)
+#define pbin(data)              print_bin8(data)
+#define pbin16(data)            print_bin16(data)
+#define pbin_reverse(data)      print_bin_reverse8(data)
+#define pbin_reverse16(data)    print_bin_reverse16(data)
+
+
+#endif
diff --git a/common/progmem.h b/common/progmem.h
new file mode 100644 (file)
index 0000000..199b1be
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef PROGMEM_H
+#define PROGMEM_H 1
+
+#if defined(__AVR__)
+#   include <avr/pgmspace.h>
+#elif defined(__arm__)
+#   define PROGMEM
+#   define pgm_read_byte(p)     *(p)
+#   define pgm_read_word(p)     *(p)
+#endif
+
+#endif
diff --git a/common/report.h b/common/report.h
new file mode 100644 (file)
index 0000000..f6c0a31
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+Copyright 2011,2012 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef REPORT_H
+#define REPORT_H
+
+#include <stdint.h>
+#include "keycode.h"
+
+
+/* report id */
+#define REPORT_ID_MOUSE     1
+#define REPORT_ID_SYSTEM    2
+#define REPORT_ID_CONSUMER  3
+
+/* mouse buttons */
+#define MOUSE_BTN1 (1<<0)
+#define MOUSE_BTN2 (1<<1)
+#define MOUSE_BTN3 (1<<2)
+#define MOUSE_BTN4 (1<<3)
+#define MOUSE_BTN5 (1<<4)
+
+/* Consumer Page(0x0C)
+ * following are supported by Windows: http://msdn.microsoft.com/en-us/windows/hardware/gg463372.aspx
+ */
+#define AUDIO_MUTE              0x00E2
+#define AUDIO_VOL_UP            0x00E9
+#define AUDIO_VOL_DOWN          0x00EA
+#define TRANSPORT_NEXT_TRACK    0x00B5
+#define TRANSPORT_PREV_TRACK    0x00B6
+#define TRANSPORT_STOP          0x00B7
+#define TRANSPORT_STOP_EJECT    0x00CC
+#define TRANSPORT_PLAY_PAUSE    0x00CD
+/* application launch */
+#define AL_CC_CONFIG            0x0183
+#define AL_EMAIL                0x018A
+#define AL_CALCULATOR           0x0192
+#define AL_LOCAL_BROWSER        0x0194
+/* application control */
+#define AC_SEARCH               0x0221
+#define AC_HOME                 0x0223
+#define AC_BACK                 0x0224
+#define AC_FORWARD              0x0225
+#define AC_STOP                 0x0226
+#define AC_REFRESH              0x0227
+#define AC_BOOKMARKS            0x022A
+/* supplement for Bluegiga iWRAP HID(not supported by Windows?) */
+#define AL_LOCK                 0x019E
+#define TRANSPORT_RECORD        0x00B2
+#define TRANSPORT_FAST_FORWARD  0x00B3
+#define TRANSPORT_REWIND        0x00B4
+#define TRANSPORT_EJECT         0x00B8
+#define AC_MINIMIZE             0x0206
+
+/* Generic Desktop Page(0x01) - system power control */
+#define SYSTEM_POWER_DOWN       0x0081
+#define SYSTEM_SLEEP            0x0082
+#define SYSTEM_WAKE_UP          0x0083
+
+
+/* key report size(NKRO or boot mode) */
+#if defined(PROTOCOL_PJRC) && defined(NKRO_ENABLE)
+#   include "usb.h"
+#   define KEYBOARD_REPORT_SIZE KBD2_SIZE
+#   define KEYBOARD_REPORT_KEYS (KBD2_SIZE - 2)
+#   define KEYBOARD_REPORT_BITS (KBD2_SIZE - 1)
+
+#elif defined(PROTOCOL_LUFA) && defined(NKRO_ENABLE)
+#   include "protocol/lufa/descriptor.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
+#   define KEYBOARD_REPORT_KEYS 6
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * keyboard report is 8-byte array retains state of 8 modifiers and 6 keys.
+ *
+ * byte |0       |1       |2       |3       |4       |5       |6       |7
+ * -----+--------+--------+--------+--------+--------+--------+--------+--------
+ * desc |mods    |reserved|keys[0] |keys[1] |keys[2] |keys[3] |keys[4] |keys[5]
+ *
+ * It is exended to 16 bytes to retain 120keys+8mods when NKRO mode.
+ *
+ * byte |0       |1       |2       |3       |4       |5       |6       |7        ... |15
+ * -----+--------+--------+--------+--------+--------+--------+--------+--------     +--------
+ * desc |mods    |bits[0] |bits[1] |bits[2] |bits[3] |bits[4] |bits[5] |bits[6]  ... |bit[14]
+ *
+ * mods retains state of 8 modifiers.
+ *
+ *  bit |0       |1       |2       |3       |4       |5       |6       |7
+ * -----+--------+--------+--------+--------+--------+--------+--------+--------
+ * desc |Lcontrol|Lshift  |Lalt    |Lgui    |Rcontrol|Rshift  |Ralt    |Rgui
+ *
+ */
+typedef union {
+    uint8_t raw[KEYBOARD_REPORT_SIZE];
+    struct {
+        uint8_t mods;
+        uint8_t reserved;
+        uint8_t keys[KEYBOARD_REPORT_KEYS];
+    };
+#ifdef NKRO_ENABLE
+    struct {
+        uint8_t mods;
+        uint8_t bits[KEYBOARD_REPORT_BITS];
+    } nkro;
+#endif
+} __attribute__ ((packed)) report_keyboard_t;
+/*
+typedef struct {
+    uint8_t mods;
+    uint8_t reserved;
+    uint8_t keys[REPORT_KEYS];
+} __attribute__ ((packed)) report_keyboard_t;
+*/
+
+typedef struct {
+    uint8_t buttons;
+    int8_t x;
+    int8_t y;
+    int8_t v;
+    int8_t h;
+} __attribute__ ((packed)) report_mouse_t;
+
+
+/* keycode to system usage */
+#define KEYCODE2SYSTEM(key) \
+    (key == KC_SYSTEM_POWER ? SYSTEM_POWER_DOWN : \
+    (key == KC_SYSTEM_SLEEP ? SYSTEM_SLEEP : \
+    (key == KC_SYSTEM_WAKE  ? SYSTEM_WAKE_UP : 0)))
+
+/* keycode to consumer usage */
+#define KEYCODE2CONSUMER(key) \
+    (key == KC_AUDIO_MUTE       ?  AUDIO_MUTE : \
+    (key == KC_AUDIO_VOL_UP     ?  AUDIO_VOL_UP : \
+    (key == KC_AUDIO_VOL_DOWN   ?  AUDIO_VOL_DOWN : \
+    (key == KC_MEDIA_NEXT_TRACK ?  TRANSPORT_NEXT_TRACK : \
+    (key == KC_MEDIA_PREV_TRACK ?  TRANSPORT_PREV_TRACK : \
+    (key == KC_MEDIA_FAST_FORWARD ?  TRANSPORT_FAST_FORWARD : \
+    (key == KC_MEDIA_REWIND     ?  TRANSPORT_REWIND : \
+    (key == KC_MEDIA_STOP       ?  TRANSPORT_STOP : \
+    (key == KC_MEDIA_EJECT      ?  TRANSPORT_STOP_EJECT : \
+    (key == KC_MEDIA_PLAY_PAUSE ?  TRANSPORT_PLAY_PAUSE : \
+    (key == KC_MEDIA_SELECT     ?  AL_CC_CONFIG : \
+    (key == KC_MAIL             ?  AL_EMAIL : \
+    (key == KC_CALCULATOR       ?  AL_CALCULATOR : \
+    (key == KC_MY_COMPUTER      ?  AL_LOCAL_BROWSER : \
+    (key == KC_WWW_SEARCH       ?  AC_SEARCH : \
+    (key == KC_WWW_HOME         ?  AC_HOME : \
+    (key == KC_WWW_BACK         ?  AC_BACK : \
+    (key == KC_WWW_FORWARD      ?  AC_FORWARD : \
+    (key == KC_WWW_STOP         ?  AC_STOP : \
+    (key == KC_WWW_REFRESH      ?  AC_REFRESH : \
+    (key == KC_WWW_FAVORITES    ?  AC_BOOKMARKS : 0)))))))))))))))))))))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/sendchar.h b/common/sendchar.h
new file mode 100644 (file)
index 0000000..7a64d00
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+Copyright 2011 Jun Wako <wakojun@gmail.com>
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef SENDCHAR_H
+#define SENDCHAR_H
+
+#include <stdint.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* transmit a character.  return 0 on success, -1 on error. */
+int8_t sendchar(uint8_t c);