changeset 306:f158dfa0fa85

Merge pull request #25 from smasher816/master Set DFU bootloader name
author Jacob Alexander <haata@kiibohd.com>
date Sun, 08 Mar 2015 17:33:29 -0700
parents ac842066568a (diff) 4617ef5e06f1 (current diff)
children ecd2ae35d25c 4f47971c45c2 05a09eda53fb
files
diffstat 21 files changed, 543 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/Debug/cli/cli.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Debug/cli/cli.c	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 by Jacob Alexander
+/* Copyright (C) 2014-2015 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -422,7 +422,7 @@
 	print( NL );
 	print( " \033[1mRevision:\033[0m      " CLI_Revision       NL );
 	print( " \033[1mBranch:\033[0m        " CLI_Branch         NL );
-	print( " \033[1mTree Status:\033[0m   " CLI_ModifiedStatus NL );
+	print( " \033[1mTree Status:\033[0m   " CLI_ModifiedStatus CLI_ModifiedFiles NL );
 	print( " \033[1mRepo Origin:\033[0m   " CLI_RepoOrigin     NL );
 	print( " \033[1mCommit Date:\033[0m   " CLI_CommitDate     NL );
 	print( " \033[1mCommit Author:\033[0m " CLI_CommitAuthor   NL );
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/CMake/FindDFUSuffix.cmake	Sun Mar 08 17:33:29 2015 -0700
@@ -0,0 +1,40 @@
+# The module defines the following variables:
+#   DFU_SUFFIX_EXECUTABLE - path to ctags command line client
+#   DFU_SUFFIX_FOUND - true if the command line client was found
+#   DFU_SUFFIX_VERSION_STRING - the version of dfu-suffix found (since CMake 2.8.8)
+# Example usage:
+#   find_package( DFUSuffix )
+#   if( DFU_SUFFIX_FOUND )
+#     message("ctags found: ${DFU_SUFFIX_EXECUTABLE}")
+#   endif()
+
+find_program ( DFU_SUFFIX_EXECUTABLE
+	NAMES dfu-suffix
+	DOC "dfu-suffix executable"
+)
+mark_as_advanced ( DFU_SUFFIX_EXECUTABLE )
+
+if ( DFU_SUFFIX_EXECUTABLE )
+	execute_process ( COMMAND ${DFU_SUFFIX_EXECUTABLE} --version
+		OUTPUT_VARIABLE dfu_suffix_version
+		ERROR_QUIET
+		OUTPUT_STRIP_TRAILING_WHITESPACE
+	)
+
+	if ( dfu_suffix_version MATCHES "^dfu-suffix \\(dfu-util\\)" )
+		string ( REPLACE "\n" "" DFU_SUFFIX_VERSION_STRING ${dfu_suffix_version} )
+		string ( REPLACE "dfu-suffix (dfu-util) " "" DFU_SUFFIX_VERSION_STRING ${DFU_SUFFIX_VERSION_STRING} )
+		string ( REGEX REPLACE "Copyright .*$" "" DFU_SUFFIX_VERSION_STRING ${DFU_SUFFIX_VERSION_STRING} )
+	endif ()
+	unset ( dfu_suffix_version )
+endif ()
+
+# Handle the QUIETLY and REQUIRED arguments and set DFU_SUFFIX_FOUND to TRUE if
+# all listed variables are TRUE
+
+include ( FindPackageHandleStandardArgs )
+find_package_handle_standard_args ( DFU_SUFFIX
+	REQUIRED_VARS DFU_SUFFIX_EXECUTABLE
+	VERSION_VAR DFU_SUFFIX_VERSION_STRING
+)
+
--- a/Lib/CMake/build.cmake	Sun Mar 08 17:25:13 2015 -0700
+++ b/Lib/CMake/build.cmake	Sun Mar 08 17:33:29 2015 -0700
@@ -1,6 +1,6 @@
 ###| CMAKE Kiibohd Controller Source Configurator |###
 #
-# Written by Jacob Alexander in 2011-2014 for the Kiibohd Controller
+# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller
 #
 # Released into the Public Domain
 #
@@ -46,12 +46,25 @@
 
 
 #| Convert the .ELF into a .bin to load onto the McHCK
+#| Then sign using dfu-suffix (requries dfu-util)
 if ( DEFINED DFU )
+	# dfu-suffix is required to sign the dfu binary
+	find_package ( DFUSuffix )
+
 	set( TARGET_BIN ${TARGET}.dfu.bin )
-	add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
-		COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
-		COMMENT "Creating dfu binary file:      ${TARGET_BIN}"
-	)
+	if ( DFU_SUFFIX_FOUND )
+		add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
+			COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
+			COMMAND ${DFU_SUFFIX_EXECUTABLE} --add ${TARGET_BIN} --vid ${BOOT_VENDOR_ID} --pid ${BOOT_PRODUCT_ID} 1> /dev/null
+			COMMENT "Create and sign dfu bin file:  ${TARGET_BIN}"
+		)
+	else ()
+		message ( WARNING "DFU Binary has not been signed, requires dfu-suffix..." )
+		add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
+			COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
+			COMMENT "Creating dfu binary file:      ${TARGET_BIN}"
+		)
+	endif ()
 endif ()
 
 
--- a/Lib/CMake/kll.cmake	Sun Mar 08 17:25:13 2015 -0700
+++ b/Lib/CMake/kll.cmake	Sun Mar 08 17:33:29 2015 -0700
@@ -1,6 +1,6 @@
 ###| CMAKE Kiibohd Controller KLL Configurator |###
 #
-# Written by Jacob Alexander in 2014 for the Kiibohd Controller
+# Written by Jacob Alexander in 2014-2015 for the Kiibohd Controller
 #
 # Released into the Public Domain
 #
@@ -46,14 +46,10 @@
 
 #| KLL_DEPENDS is used to build a dependency tree for kll.py, this way when files are changed, kll.py gets re-run
 
-#| Search for capabilities.kll in each module directory
-foreach ( DIR ${ScanModulePath} ${MacroModulePath} ${OutputModulePath} ${DebugModulePath} )
-	# capabilities.kll exists, add to BaseMap
-	set ( filename "${PROJECT_SOURCE_DIR}/${DIR}/capabilities.kll" )
-	if ( EXISTS ${filename} )
-		set ( BaseMap_Args ${BaseMap_Args} ${filename} )
-		set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} )
-	endif ()
+#| Add each of the detected capabilities.kll
+foreach ( filename ${ScanModule_KLL} ${MacroModule_KLL} ${OutputModule_KLL} ${DebugModule_KLL} )
+	set ( BaseMap_Args ${BaseMap_Args} ${filename} )
+	set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} )
 endforeach ()
 
 #| If set BaseMap cannot be found, use default map
@@ -118,21 +114,25 @@
 #
 
 #| KLL Options
-set ( kll_backend   -b kiibohd )
-set ( kll_template  -t ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdKeymap.h )
-set ( kll_outputname generatedKeymap.h )
-set ( kll_output    -o ${kll_outputname} )
-set ( kll_define_output   --defines-output kll_defs.h )
-set ( kll_define_template --defines-template ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdDefs.h )
+set ( kll_backend   --backend kiibohd )
+set ( kll_template  --templates ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdKeymap.h ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdDefs.h )
+set ( kll_outputname generatedKeymap.h kll_defs.h )
+set ( kll_output    --outputs ${kll_outputname} )
 
 #| KLL Cmd
-set ( kll_cmd ${PROJECT_SOURCE_DIR}/kll/kll.py ${BaseMap_Args} ${DefaultMap_Args} ${PartialMap_Args} ${kll_backend} ${kll_template} ${kll_output} ${kll_define_template} ${kll_define_output} )
+set ( kll_cmd ${PROJECT_SOURCE_DIR}/kll/kll.py ${BaseMap_Args} ${DefaultMap_Args} ${PartialMap_Args} ${kll_backend} ${kll_template} ${kll_output} )
 add_custom_command ( OUTPUT ${kll_outputname}
 	COMMAND ${kll_cmd}
 	DEPENDS ${KLL_DEPENDS}
 	COMMENT "Generating KLL Layout"
 )
 
+#| KLL Regen Convenience Target
+add_custom_target ( kll_regen
+	COMMAND ${kll_cmd}
+	COMMENT "Re-generating KLL Layout"
+)
+
 #| Append generated file to required sources so it becomes a dependency in the main build
 set ( SRCS ${SRCS} ${kll_outputname} )
 
--- a/Lib/CMake/modules.cmake	Sun Mar 08 17:25:13 2015 -0700
+++ b/Lib/CMake/modules.cmake	Sun Mar 08 17:33:29 2015 -0700
@@ -1,6 +1,6 @@
 ###| CMAKE Kiibohd Controller Source Configurator |###
 #
-# Written by Jacob Alexander in 2011-2014 for the Kiibohd Controller
+# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller
 #
 # Released into the Public Domain
 #
@@ -104,10 +104,8 @@
 	PathPrepend ( Module_SRCS ${ModulePath} ${Module_SRCS} )
 
 	# Check the current scope to see if a sub-module added some source files
-	set ( Module_SRCS ${${ModuleType}_SRCS} ${Module_SRCS} )
-
 	# Append each of the sources to each type of module srcs list
-	set ( ${ModuleType}_SRCS ${Module_SRCS} )
+	set ( ${ModuleType}_SRCS ${${ModuleType}_SRCS} ${Module_SRCS} )
 
 	# Add .h files
 	add_definitions ( -I${ModuleFullPath} )
@@ -124,8 +122,17 @@
 		endif ()
 	endforeach ()
 
-	# Finally, add the sources to the parent scope (i.e. return)
+	# Check for any capabilities.kll files in the Module
+	set ( kll_capabilities_file "${ModuleFullPath}/capabilities.kll" )
+	if ( EXISTS ${kll_capabilities_file} )
+		# Add the kll file and any submodule kll files to the running list
+		set ( ${ModuleType}Module_KLL ${${ModuleType}Module_KLL} ${kll_capabilities_file} )
+	endif ()
+
+
+	# Finally, add the sources and kll files to the parent scope (i.e. return)
 	set ( ${ModuleType}_SRCS ${${ModuleType}_SRCS} PARENT_SCOPE )
+	set ( ${ModuleType}Module_KLL ${${ModuleType}Module_KLL} PARENT_SCOPE )
 endfunction ()
 
 
@@ -150,7 +157,7 @@
 #
 
 #| Manufacturer name
-set( MANUFACTURER "Kiibohd" )
+set ( MANUFACTURER "Kiibohd" )
 
 
 #| Serial Number
@@ -158,19 +165,29 @@
 
 #| Modified
 #| Takes a bit of work to extract the "M " using CMake, and not using it if there are no modifications
-execute_process( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain
+execute_process ( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	OUTPUT_VARIABLE Git_Modified_INFO
 	ERROR_QUIET
 	OUTPUT_STRIP_TRAILING_WHITESPACE
 )
-string( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH )
-set( Git_Modified_Status "Clean" )
+string ( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH )
+set ( Git_Modified_Status "Clean" )
 if ( ${Git_Modified_LENGTH} GREATER 2 )
-	string( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO )
-	set( Git_Modified_Status "Dirty" )
+	string ( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO )
+	set ( Git_Modified_Status "Dirty" )
 endif ()
 
+#| List of modified files
+execute_process ( COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
+	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+	OUTPUT_VARIABLE Git_Modified_Files
+	ERROR_QUIET
+	OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+string ( REGEX REPLACE "\n" "\\\\r\\\\n\\\\t" Git_Modified_Files "${Git_Modified_Files}" )
+set ( Git_Modified_Files "\\r\\n\\t${Git_Modified_Files}" )
+
 #| Branch
 execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
@@ -180,7 +197,7 @@
 )
 
 #| Date
-execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
+execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	OUTPUT_VARIABLE Git_Date_INFO
 	ERROR_QUIET
@@ -188,7 +205,7 @@
 )
 
 #| Commit Author and Email
-execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>"
+execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>"
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	OUTPUT_VARIABLE Git_Commit_Author
 	ERROR_QUIET
@@ -196,7 +213,7 @@
 )
 
 #| Commit Revision
-execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%H
+execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%H
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	OUTPUT_VARIABLE Git_Commit_Revision
 	ERROR_QUIET
@@ -204,7 +221,7 @@
 )
 
 #| Origin URL
-execute_process( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
+execute_process ( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
 	WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	OUTPUT_VARIABLE Git_Origin_URL
 	ERROR_QUIET
@@ -212,25 +229,25 @@
 )
 
 #| Build Date
-execute_process( COMMAND "date" "+%Y-%m-%d %T %z"
+execute_process ( COMMAND "date" "+%Y-%m-%d %T %z"
 	OUTPUT_VARIABLE Build_Date
 	ERROR_QUIET
 	OUTPUT_STRIP_TRAILING_WHITESPACE
 )
 
 #| Last Commit Date
-set( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" )
+set ( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" )
 
 #| Uses CMake variables to include as defines
 #| Primarily for USB configuration
-configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Lib/_buildvars.h buildvars.h )
+configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/Lib/_buildvars.h buildvars.h )
 
 
 
 ###
 # Source Defines
 #
-set( SRCS
+set ( SRCS
 	${MAIN_SRCS}
 	${COMPILER_SRCS}
 	${Scan_SRCS}
@@ -240,7 +257,7 @@
 )
 
 #| Directories to include by default
-include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
+include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
 
 
 
@@ -248,20 +265,20 @@
 # ctag Generation
 #
 
-if( CTAGS_EXECUTABLE )
+if ( CTAGS_EXECUTABLE )
 	# Populate list of directories for ctags to parse
 	# NOTE: Doesn't support dots in the folder names...
-	foreach( filename ${SRCS} )
-		string( REGEX REPLACE "/[a-zA-Z0-9_-]+.c$" "" pathglob ${filename} )
-		file( GLOB filenames "${pathglob}/*.c" )
-		set( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
-		file( GLOB filenames "${pathglob}/*.h" )
-		set( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
-	endforeach()
+	foreach ( filename ${SRCS} )
+		string ( REGEX REPLACE "/[a-zA-Z0-9_-]+.c$" "" pathglob ${filename} )
+		file ( GLOB filenames "${pathglob}/*.c" )
+		set ( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
+		file ( GLOB filenames "${pathglob}/*.h" )
+		set ( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
+	endforeach ()
 
 	# Generate the ctags
-	execute_process( COMMAND ctags ${CTAG_PATHS}
+	execute_process ( COMMAND ctags ${CTAG_PATHS}
 		WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
 	)
-endif()
+endif ()
 
--- a/Lib/_buildvars.h	Sun Mar 08 17:25:13 2015 -0700
+++ b/Lib/_buildvars.h	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2013-2014 by Jacob Alexander
+/* Copyright (C) 2013-2015 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -38,6 +38,7 @@
 #define CLI_Revision            "@Git_Commit_Revision@"
 #define CLI_Branch              "@Git_Branch_INFO@"
 #define CLI_ModifiedStatus      "@Git_Modified_Status@"
+#define CLI_ModifiedFiles       "@Git_Modified_Files@"
 #define CLI_RepoOrigin          "@Git_Origin_URL@"
 #define CLI_CommitDate          "@Git_Date_INFO@"
 #define CLI_CommitAuthor        @Git_Commit_Author@
--- a/LoadFile/load.dfu	Sun Mar 08 17:25:13 2015 -0700
+++ b/LoadFile/load.dfu	Sun Mar 08 17:33:29 2015 -0700
@@ -49,7 +49,7 @@
 if [[ "$SERIAL_PORT" != "" ]] && [[ -e "$SERIAL_PORT" ]]; then
 	echo "NOTE: This may fail if the uC is in a bad state or does not support remote flashing"
 	printf "reload\r" > $SERIAL_PORT
-	sleep 1
+	sleep 2
 fi
 
 # Load via dfu-util
--- a/Macro/PartialMap/macro.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Macro/PartialMap/macro.c	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 by Jacob Alexander
+/* Copyright (C) 2014-2015 by Jacob Alexander
  *
  * This file is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -121,9 +121,11 @@
 uint16_t macroStepCounter = 0;
 
 
-// Key Trigger List Buffer
+// Key Trigger List Buffer and Layer Cache
+// The layer cache is set on press only, hold and release events refer to the value set on press
 TriggerGuide macroTriggerListBuffer[ MaxScanCode ];
 uint8_t macroTriggerListBufferSize = 0;
+var_uint_t macroTriggerListLayerCache[ MaxScanCode ];
 
 // Pending Trigger Macro Index List
 //  * Any trigger macros that need processing from a previous macro processing loop
@@ -311,8 +313,24 @@
 
 // Looks up the trigger list for the given scan code (from the active layer)
 // NOTE: Calling function must handle the NULL pointer case
-nat_ptr_t *Macro_layerLookup( uint8_t scanCode, uint8_t latch_expire )
+nat_ptr_t *Macro_layerLookup( TriggerGuide *guide, uint8_t latch_expire )
 {
+	uint8_t scanCode = guide->scanCode;
+
+	// TODO Analog
+	// If a normal key, and not pressed, do a layer cache lookup
+	if ( guide->type == 0x00 && guide->state != 0x01 )
+	{
+		// Cached layer
+		var_uint_t cachedLayer = macroTriggerListLayerCache[ scanCode ];
+
+		// Lookup map, then layer
+		nat_ptr_t **map = (nat_ptr_t**)LayerIndex[ cachedLayer ].triggerMap;
+		const Layer *layer = &LayerIndex[ cachedLayer ];
+
+		return map[ scanCode - layer->first ];
+	}
+
 	// If no trigger macro is defined at the given layer, fallthrough to the next layer
 	for ( uint16_t layerIndex = 0; layerIndex < macroLayerIndexStackSize; layerIndex++ )
 	{
@@ -342,6 +360,9 @@
 			  && scanCode >= layer->first
 			  && *map[ scanCode - layer->first ] != 0 )
 			{
+				// Set the layer cache
+				macroTriggerListLayerCache[ scanCode ] = macroLayerIndexStack[ layerIndex ];
+
 				return map[ scanCode - layer->first ];
 			}
 		}
@@ -359,6 +380,9 @@
 	  && scanCode >= layer->first
 	  && *map[ scanCode - layer->first ] != 0 )
 	{
+		// Set the layer cache to default map
+		macroTriggerListLayerCache[ scanCode ] = 0;
+
 		return map[ scanCode - layer->first ];
 	}
 
@@ -836,7 +860,7 @@
 		uint8_t latch_expire = macroTriggerListBuffer[ key ].state == 0x03;
 
 		// Lookup Trigger List
-		nat_ptr_t *triggerList = Macro_layerLookup( macroTriggerListBuffer[ key ].scanCode, latch_expire );
+		nat_ptr_t *triggerList = Macro_layerLookup( &macroTriggerListBuffer[ key ], latch_expire );
 
 		// Number of Triggers in list
 		nat_ptr_t triggerListSize = triggerList[0];
--- a/Macro/PartialMap/usb_hid.h	Sun Mar 08 17:25:13 2015 -0700
+++ b/Macro/PartialMap/usb_hid.h	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2011-2014 by Jacob Alexander
+/* Copyright (C) 2011-2015 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -113,7 +113,7 @@
 #define KEY_UP             0x52
 #define KEY_NUM_LOCK       0x53
 #define KEYPAD_SLASH       0x54
-#define KEYPAD_ASTERIX     0x55
+#define KEYPAD_ASTERISK    0x55
 #define KEYPAD_MINUS       0x56
 #define KEYPAD_PLUS        0x57
 #define KEYPAD_ENTER       0x58
--- a/Output/pjrcUSB/arm/usb_dev.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/pjrcUSB/arm/usb_dev.c	Sun Mar 08 17:33:29 2015 -0700
@@ -300,7 +300,7 @@
 		data = reply_buffer;
 		break;
 	case 0x0082: // GET_STATUS (endpoint)
-		if (setup.wIndex > NUM_ENDPOINTS)
+		if ( setup.wIndex > NUM_ENDPOINTS )
 		{
 			// TODO: do we need to handle IN vs OUT here?
 			endpoint0_stall();
@@ -313,17 +313,31 @@
 		data = reply_buffer;
 		datalen = 2;
 		break;
-	case 0x0102: // CLEAR_FEATURE (endpoint)
+	case 0x0100: // CLEAR_FEATURE (device)
+	case 0x0101: // CLEAR_FEATURE (interface)
+		// TODO: Currently ignoring, perhaps useful? -HaaTa
+		endpoint0_stall();
+		return;
+	case 0x0102: // CLEAR_FEATURE (interface)
 		i = setup.wIndex & 0x7F;
 		if ( i > NUM_ENDPOINTS || setup.wValue != 0 )
 		{
-			// TODO: do we need to handle IN vs OUT here?
 			endpoint0_stall();
 			return;
 		}
-		(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02;
+		//(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02;
 		// TODO: do we need to clear the data toggle here?
-		break;
+		//break;
+
+		// FIXME: Clearing causes keyboard to freeze, likely an invalid clear
+		// XXX: Ignoring seems to work, though this may not be the ideal behaviour -HaaTa
+		endpoint0_stall();
+		return;
+	case 0x0300: // SET_FEATURE (device)
+	case 0x0301: // SET_FEATURE (interface)
+		// TODO: Currently ignoring, perhaps useful? -HaaTa
+		endpoint0_stall();
+		return;
 	case 0x0302: // SET_FEATURE (endpoint)
 		i = setup.wIndex & 0x7F;
 		if ( i > NUM_ENDPOINTS || setup.wValue != 0 )
--- a/Output/pjrcUSB/arm/usb_keyboard.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/pjrcUSB/arm/usb_keyboard.c	Sun Mar 08 17:33:29 2015 -0700
@@ -1,7 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
- * Modifications by Jacob Alexander 2013-2014
+ * Modifications by Jacob Alexander 2013-2015
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -120,6 +120,23 @@
 	{
 	// Send boot keyboard interrupt packet(s)
 	case 0:
+		// USB Boot Mode debug output
+		if ( Output_DebugMode )
+		{
+			dbug_msg("Boot USB: ");
+			printHex_op( USBKeys_Modifiers, 2 );
+			print(" ");
+			printHex( 0 );
+			print(" ");
+			printHex_op( USBKeys_Keys[0], 2 );
+			printHex_op( USBKeys_Keys[1], 2 );
+			printHex_op( USBKeys_Keys[2], 2 );
+			printHex_op( USBKeys_Keys[3], 2 );
+			printHex_op( USBKeys_Keys[4], 2 );
+			printHex_op( USBKeys_Keys[5], 2 );
+			print( NL );
+		}
+
 		// Boot Mode
 		*tx_buf++ = USBKeys_Modifiers;
 		*tx_buf++ = 0;
@@ -133,9 +150,21 @@
 
 	// Send NKRO keyboard interrupts packet(s)
 	case 1:
+		if ( Output_DebugMode )
+		{
+			dbug_msg("NKRO USB: ");
+		}
+
 		// Check system control keys
 		if ( USBKeys_Changed & USBKeyChangeState_System )
 		{
+			if ( Output_DebugMode )
+			{
+				print("SysCtrl[");
+				printHex_op( USBKeys_SysCtrl, 2 );
+				print( "] " NL );
+			}
+
 			*tx_buf++ = 0x02; // ID
 			*tx_buf   = USBKeys_SysCtrl;
 			tx_packet->len = 2;
@@ -148,6 +177,13 @@
 		// Check consumer control keys
 		if ( USBKeys_Changed & USBKeyChangeState_Consumer )
 		{
+			if ( Output_DebugMode )
+			{
+				print("ConsCtrl[");
+				printHex_op( USBKeys_ConsCtrl, 2 );
+				print( "] " NL );
+			}
+
 			*tx_buf++ = 0x03; // ID
 			*tx_buf++ = (uint8_t)(USBKeys_ConsCtrl & 0x00FF);
 			*tx_buf   = (uint8_t)(USBKeys_ConsCtrl >> 8);
@@ -161,6 +197,24 @@
 		// Standard HID Keyboard
 		if ( USBKeys_Changed )
 		{
+			// USB NKRO Debug output
+			if ( Output_DebugMode )
+			{
+				printHex_op( USBKeys_Modifiers, 2 );
+				print(" ");
+				for ( uint8_t c = 0; c < 6; c++ )
+					printHex_op( USBKeys_Keys[ c ], 2 );
+				print(" ");
+				for ( uint8_t c = 6; c < 20; c++ )
+					printHex_op( USBKeys_Keys[ c ], 2 );
+				print(" ");
+				printHex_op( USBKeys_Keys[20], 2 );
+				print(" ");
+				for ( uint8_t c = 21; c < 27; c++ )
+					printHex_op( USBKeys_Keys[ c ], 2 );
+				print( NL );
+			}
+
 			tx_packet->len = 0;
 
 			// Modifiers
--- a/Output/pjrcUSB/output_com.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/pjrcUSB/output_com.c	Sun Mar 08 17:33:29 2015 -0700
@@ -61,6 +61,7 @@
 // ----- Function Declarations -----
 
 void cliFunc_kbdProtocol( char* args );
+void cliFunc_outputDebug( char* args );
 void cliFunc_readLEDs   ( char* args );
 void cliFunc_sendKeys   ( char* args );
 void cliFunc_setKeys    ( char* args );
@@ -72,6 +73,7 @@
 
 // Output Module command dictionary
 CLIDict_Entry( kbdProtocol, "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode" );
+CLIDict_Entry( outputDebug, "Toggle Output Debug mode." );
 CLIDict_Entry( readLEDs,    "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." );
 CLIDict_Entry( sendKeys,    "Send the prepared list of USB codes and modifier byte." );
 CLIDict_Entry( setKeys,     "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." );
@@ -79,6 +81,7 @@
 
 CLIDict_Def( outputCLIDict, "USB Module Commands" ) = {
 	CLIDict_Item( kbdProtocol ),
+	CLIDict_Item( outputDebug ),
 	CLIDict_Item( readLEDs ),
 	CLIDict_Item( sendKeys ),
 	CLIDict_Item( setKeys ),
@@ -129,6 +132,11 @@
 // 0 is often used to show that a USB cable is not plugged in (but has power)
          uint8_t  Output_Available = 0;
 
+// Debug control variable for Output modules
+// 0 - Debug disabled (default)
+// 1 - Debug enabled
+         uint8_t  Output_DebugMode = 0;
+
 
 
 // ----- Capabilities -----
@@ -211,7 +219,10 @@
 
 	// Only send keypresses if press or hold state
 	if ( stateType == 0x00 && state == 0x03 ) // Release state
+	{
+		USBKeys_ConsCtrl = 0;
 		return;
+	}
 
 	// Set consumer control code
 	USBKeys_ConsCtrl = *(uint16_t*)(&args[0]);
@@ -242,7 +253,10 @@
 
 	// Only send keypresses if press or hold state
 	if ( stateType == 0x00 && state == 0x03 ) // Release state
+	{
+		USBKeys_SysCtrl = 0;
 		return;
+	}
 
 	// Set system control code
 	USBKeys_SysCtrl = args[0];
@@ -584,6 +598,24 @@
 }
 
 
+void cliFunc_outputDebug( char* args )
+{
+	// Parse number from argument
+	//  NOTE: Only first argument is used
+	char* arg1Ptr;
+	char* arg2Ptr;
+	CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );
+
+	// Default to 1 if no argument is given
+	Output_DebugMode = 1;
+
+	if ( arg1Ptr[0] != '\0' )
+	{
+		Output_DebugMode = (uint16_t)numToInt( arg1Ptr );
+	}
+}
+
+
 void cliFunc_readLEDs( char* args )
 {
 	print( NL );
--- a/Output/pjrcUSB/output_com.h	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/pjrcUSB/output_com.h	Sun Mar 08 17:33:29 2015 -0700
@@ -81,6 +81,8 @@
 
 extern          uint8_t  Output_Available; // 0 - Output module not fully functional, 1 - Output module working
 
+extern          uint8_t  Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled
+
 
 
 // ----- Capabilities -----
--- a/Output/usbMuxUart/capabilities.kll	Sun Mar 08 17:25:13 2015 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,14 +0,0 @@
-Name = usbMuxUartCapabilities;
-Version = 0.1;
-Author = "HaaTa (Jacob Alexander) 2014";
-KLL = 0.3;
-
-# Modified Date
-Date = 2014-09-28;
-
-
-# Capabilties available to the usbMuxUart output module
-consCtrlOut => Output_consCtrlSend_capability( consCode : 2 );
-sysCtrlOut  => Output_sysCtrlSend_capability( sysCode : 1 );
-usbKeyOut   => Output_usbCodeSend_capability( usbCode : 1 );
-
--- a/Output/usbMuxUart/output_com.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/usbMuxUart/output_com.c	Sun Mar 08 17:33:29 2015 -0700
@@ -33,10 +33,10 @@
 // USB Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
 #elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
-#include <uartOut/arm/uart_serial.h>
-#include <pjrcUSB/arm/usb_dev.h>
-#include <pjrcUSB/arm/usb_keyboard.h>
-#include <pjrcUSB/arm/usb_serial.h>
+#include <arm/uart_serial.h>
+#include <arm/usb_dev.h>
+#include <arm/usb_keyboard.h>
+#include <arm/usb_serial.h>
 #endif
 
 // Local Includes
@@ -135,10 +135,69 @@
 // 0 is often used to show that a USB cable is not plugged in (but has power)
          uint8_t  Output_Available = 0;
 
+// Debug control variable for Output modules
+// 0 - Debug disabled (default)
+// 1 - Debug enabled
+         uint8_t  Output_DebugMode = 0;
+
 
 
 // ----- Capabilities -----
 
+// Set Boot Keyboard Protocol
+void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args )
+{
+	// Display capability name
+	if ( stateType == 0xFF && state == 0xFF )
+	{
+		print("Output_kbdProtocolBoot()");
+		return;
+	}
+
+	// Only set if necessary
+	if ( USBKeys_Protocol == 0 )
+		return;
+
+	// TODO Analog inputs
+	// Only set on key press
+	if ( stateType != 0x01 )
+		return;
+
+	// Flush the key buffers
+	Output_flushBuffers();
+
+	// Set the keyboard protocol to Boot Mode
+	USBKeys_Protocol = 0;
+}
+
+
+// Set NKRO Keyboard Protocol
+void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args )
+{
+	// Display capability name
+	if ( stateType == 0xFF && state == 0xFF )
+	{
+		print("Output_kbdProtocolNKRO()");
+		return;
+	}
+
+	// Only set if necessary
+	if ( USBKeys_Protocol == 1 )
+		return;
+
+	// TODO Analog inputs
+	// Only set on key press
+	if ( stateType != 0x01 )
+		return;
+
+	// Flush the key buffers
+	Output_flushBuffers();
+
+	// Set the keyboard protocol to NKRO Mode
+	USBKeys_Protocol = 1;
+}
+
+
 // Sends a Consumer Control code to the USB Output buffer
 void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args )
 {
@@ -374,6 +433,20 @@
 
 // ----- Functions -----
 
+// Flush Key buffers
+void Output_flushBuffers()
+{
+	// Zero out USBKeys_Keys array
+	for ( uint8_t c = 0; c < USB_NKRO_BITFIELD_SIZE_KEYS; c++ )
+		USBKeys_Keys[ c ] = 0;
+
+	// Zero out other key buffers
+	USBKeys_ConsCtrl = 0;
+	USBKeys_Modifiers = 0;
+	USBKeys_SysCtrl = 0;
+}
+
+
 // USB Module Setup
 inline void Output_setup()
 {
--- a/Output/usbMuxUart/output_com.h	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/usbMuxUart/output_com.h	Sun Mar 08 17:33:29 2015 -0700
@@ -80,6 +80,8 @@
 
 extern          uint8_t  Output_Available; // 0 - Output module not fully functional, 1 - Output module working
 
+extern          uint8_t  Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled
+
 
 
 // ----- Capabilities -----
@@ -88,6 +90,10 @@
 void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args );
 void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args );
 
+// Configuration capabilities
+void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args );
+void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args );
+
 
 
 // ----- Functions -----
@@ -95,6 +101,8 @@
 void Output_setup();
 void Output_send();
 
+void Output_flushBuffers();
+
 void Output_firmwareReload();
 void Output_softReset();
 
--- a/Output/usbMuxUart/setup.cmake	Sun Mar 08 17:25:13 2015 -0700
+++ b/Output/usbMuxUart/setup.cmake	Sun Mar 08 17:33:29 2015 -0700
@@ -23,6 +23,12 @@
 	output_com.c
 )
 
+# Remove duplicate output_com.c files from pjrcUSB and uartOut
+list ( REMOVE_ITEM Output_SRCS
+	Output/pjrcUSB/output_com.c
+	Output/uartOut/output_com.c
+)
+
 
 ###
 # Compiler Family Compatibility
--- a/README.markdown	Sun Mar 08 17:25:13 2015 -0700
+++ b/README.markdown	Sun Mar 08 17:33:29 2015 -0700
@@ -9,8 +9,9 @@
 Linux is the ideal build environment (preferably recent'ish). In the near
 future I'll make available an Arch Linux VM for building/manufacturing tests.
 
-Building on Mac should be ok for 99% of users with Macports (haven't tried
-Brew). The dfu Bootloader will not build correctly with the old version of
+Building on Mac should be ok for 99% of users with Macports or Homebrew. For
+Homebrew, use `brew tap PX4/homebrew-px4` to get the arm-none-eabi-gcc installer.
+The dfu Bootloader will not build correctly with the old version of
 arm-none-eabi-gcc that Macports currently has (4.7.3). This is due to a bug
 with lto (link time optimizations) which makes the resulting binary too big to
 fit on the chip (must be less than 4096 Bytes).
@@ -58,7 +59,7 @@
 
 - Arch Linux / Mac Ports
     - arm-none-eabi-gcc
-    - arm-none-eaby-binutils
+    - arm-none-eabi-binutils
 
 - Windows (https://launchpad.net/gcc-arm-embedded/+download)
     - gcc-arm-none-eabi (win32.zip)
@@ -262,6 +263,112 @@
 easier to just edit the file. e.g. `cmake -DScanModuleOverride=<module name>`.
 
 
+Keymap Configuration
+--------------------
+
+This is where you define the layout for your keyboard.
+Currently, the only way to define kebyoard layouts is using [KLL](https://www.overleaf.com/read/zzqbdwqjfwwf).
+
+KLL is built up of 3 different kinds of keymaps in total.
+The BaseMap, DefaultMap and PartialMaps.
+
+For each type of keymap, it is possible to combine multiple .kll files together to create new ones using
+the compiler. The order of the files matter, as the right-most file will overwrite any setting in the
+previous files.
+
+> NOTE: Each keymap is done after the entire file is processed. This means that within the file the order
+>       of assignment doesa *not* matter (if you assign the same thing twice, then yes the most recent one
+>       takes priority).
+
+
+BaseMap defines what the keyboard can do. This includes specific capabilities of the keyboard (such as USB),
+the mapping of Scan Codes to USB Codes and any specific configurations for the keyboard.
+In general, the BaseMap rarely needs to be changed. Usually only when adding a new keyboard to the firmware
+does the Basemap need any modification.
+The BaseMap is what both DefaultMap and PartialMaps are based upon. This allows for a common reference
+when defining custom keymappings.
+
+> NOTE: Don't use defaultMap.kll to change your layouts. This will work, but they will not be portable.
+
+
+The DefaultMap is the normal state of the keyboard, i.e. your default layer.
+Using the BaseMap as a base, the DefaultMap is a modification of the BaseMap to what the keyboard should do.
+Since the DefaultMap uses USB Code to USB Code translations, this means that keymaps used for one keyboard
+will work with another keyboard.
+For example, I use Colemak, so this means I only have to define Colemak once for every keyboard that supports
+the kiibohd firmware. This is possible because every BaseMap defines the keyboard as a US ANSI like keyboard
+layout.
+The DefaultMap can also be thought of as Layer 0.
+
+
+PartialMaps are optional keymaps that can be "stacked" on top of the DefaultMap.
+They can be dynamically swapped out using the layer control capabilities:
+
+- layerLatch( `<layer number>` )
+- layerLock( `<layer number>` )
+- layerShift( `<layer number>` )
+
+layerShift is usually what you want as it works just like a standard shift key.
+layerLock is similar to the CapsLock key. While layerLatch is a latch, where only the next key you press
+will use that layer (e.g. stickykeys).
+
+A unique aspect of KLL layers is that it's a true stack of layers.
+When a layer is activated, only the keys that are specified by the layer will change.
+This means, if you define a layer that only sets `CapsLock -> LCtrl` and `LCtrl->Capslock` only those keys
+will change when you active the layer. All the other keys will use the layer that is "underneath" to
+lookup the keypress (usually the DefaultMap).
+
+This means that you can combine .kll files statically using the compiler or dynamically using the firmware.
+
+You can set the max number of layers by changing the `stateWordSize` define in one of your kll files.
+By default it is set to 8 in Macro/PartialMap/capabilities.kll. This means you can have up to 256 layers
+total (this includes the DefaultMap).
+You can increase this number to either 16 or 32 (this will use more Flash and RAM btw) which will give you
+2^16 and 2^32 possible layers respectively (65 535 and 4 294 967 295).
+
+
+```cmake
+###
+# Keymap Configuration (do not include the .kll extension)
+#
+
+#| Do not include the .kll extension
+#| * BaseMap maps the native keyboard scan codes to USB Codes so the layout is compatible with all other layouts
+#| * DefaultMap allows the default keymap to be modified from the BaseMap
+#| * PartialMaps is a set of dynamically set layers (there is no limit, but too many may use up too much RAM...)
+#| BaseMap generally does not need to be changed from "defaultMap"
+#|
+#| Syntax:
+#|  myMap
+#|    * defines a single .kll layout file, double-quotes are needed to distinguish between layers
+#|  "myMap specialLayer"
+#|    * defines myMap to be the main layout, then replace specialLayers on top of it
+#|
+#| - Only for PartialMaps -
+#|  "myMap specialLayer" "myMap colemak" dvorak
+#|    * As before, but also generates a second layer at index 2 and third at index 3
+#|
+#| NOTE:  Remember to add key(s) to enable each Partial Layer
+#| NOTE2: Layers are always based up the BaseMap (which should be an ANSI-like mapping)
+#| NOTE3: Compiler looks in kll/layouts and the build directory for layout files (precedence on build directory)
+
+##| Set the base keyboard .kll map, defaults to "defaultMap" if not found
+##| Looks in Scan/<Module Name> for the available BaseMaps
+set(     BaseMap "defaultMap"
+        CACHE STRING "KLL BaseMap/Scancode Keymapping" )
+
+##| Layer additonal .kll maps on the BaseMap, layers are in order from 1st to nth
+##| Can be set to ""
+set(  DefaultMap "md1Overlay stdFuncMap"
+        CACHE STRING "KLL DefaultMap" )
+
+##| ParitalMaps available on top of the BaseMap. See above for syntax on specifying multiple layers vs. layering
+##| Can be set to ""
+set( PartialMaps "hhkbpro2"
+        CACHE STRING "KLL PartialMaps/Layer Definitions" )
+```
+
+
 Linux Building
 --------------
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MatrixARM/capabilities.kll	Sun Mar 08 17:33:29 2015 -0700
@@ -0,0 +1,34 @@
+Name = MatrixArmCapabilities;
+Version = 0.1;
+Author = "HaaTa (Jacob Alexander) 2015";
+KLL = 0.3a;
+
+# Modified Date
+Date = 2015-02-28;
+
+# Defines available to the MatrixArm sub-module
+# This debounce scheme uses a rolling counter for press/unpress on each key
+# Each counter is incremented if pressed/unpressed and the opposite counter is divided by 2
+# Using the default division threshold (0xFFFF), there are approximately 13 cycles in a perfect cycle
+# If debounce is actually necessary, this will increase (better switches will debounce faster)
+#
+# The maximum threshold is 0xFFFFFFFF, which will give around ~32 -> 36 cycles per perfect cycle
+# Using a threshold higher than 0xFFFF will require 32 bit variables, and double the ram usage.
+DebounceDivThreshold => DebounceDivThreshold_define;
+DebounceDivThreshold = 0xFFFF; # Default debounce
+#DebounceDivThreshold = 0xFFFFFFFF; # Max debounce
+
+# This defines how often the matrix is scanned
+# By, default the key matrix is scanned once per macro processing loop
+# For fast uCs and bouncy switches, this can be non-ideal
+# 0 - Bit-shift of 0
+# 1 - Bit-shift of 1 (i.e. divide by 2)
+# 2 - Bit-shift of 2 (i.e. divide by 4)
+# 3 - Bit-shift of 3 (i.e. divide by 8)
+# etc.
+# Depending on the architecture, this is either a maximum of 16 or 32
+# Increasing this value will increase switch latency
+DebounceThrottleDiv => DebounceThrottleDiv_define;
+DebounceThrottleDiv = 0; # Default
+#DebounceThrottleDiv = 2; # /4 divider
+
--- a/Scan/MatrixARM/matrix_scan.c	Sun Mar 08 17:25:13 2015 -0700
+++ b/Scan/MatrixARM/matrix_scan.c	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 by Jacob Alexander
+/* Copyright (C) 2014-2015 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@
 
 // Project Includes
 #include <cli.h>
+#include <kll.h>
 #include <led.h>
 #include <print.h>
 #include <macro.h>
@@ -38,6 +39,14 @@
 
 
 
+// ----- Defines -----
+
+#if ( DebounceThrottleDiv_define > 0 )
+nat_ptr_t Matrix_divCounter = 0;
+#endif
+
+
+
 // ----- Function Declarations -----
 
 // CLI Functions
@@ -191,7 +200,7 @@
 		Matrix_scanArray[ item ].prevState     = KeyState_Off;
 		Matrix_scanArray[ item ].curState      = KeyState_Off;
 		Matrix_scanArray[ item ].activeCount   = 0;
-		Matrix_scanArray[ item ].inactiveCount = 0xFFFF; // Start at 'off' steady state
+		Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state
 	}
 
 	// Clear scan stats counters
@@ -232,6 +241,15 @@
 // NOTE: scanNum should be reset to 0 after a USB send (to reset all the counters)
 void Matrix_scan( uint16_t scanNum )
 {
+#if ( DebounceThrottleDiv_define > 0 )
+	// Scan-rate throttling
+	// By scanning using a divider, the scan rate slowed down
+	// DebounceThrottleDiv_define == 1 means -> /2 or half scan rate
+	// This helps with bouncy switches on fast uCs
+	if ( !( Matrix_divCounter++ & (1 << ( DebounceThrottleDiv_define - 1 )) ) )
+		return;
+#endif
+
 	// Increment stats counters
 	if ( scanNum > matrixMaxScans ) matrixMaxScans = scanNum;
 	if ( scanNum == 0 )
@@ -275,14 +293,14 @@
 			if ( Matrix_pin( Matrix_rows[ sense ], Type_Sense ) )
 			{
 				// Only update if not going to wrap around
-				if ( state->activeCount < 0xFFFF ) state->activeCount += 1;
+				if ( state->activeCount < DebounceDivThreshold_define ) state->activeCount += 1;
 				state->inactiveCount >>= 1;
 			}
 			// Signal Not Detected
 			else
 			{
 				// Only update if not going to wrap around
-				if ( state->inactiveCount < 0xFFFF ) state->inactiveCount += 1;
+				if ( state->inactiveCount < DebounceDivThreshold_define ) state->inactiveCount += 1;
 				state->activeCount >>= 1;
 			}
 
--- a/Scan/MatrixARM/matrix_scan.h	Sun Mar 08 17:25:13 2015 -0700
+++ b/Scan/MatrixARM/matrix_scan.h	Sun Mar 08 17:33:29 2015 -0700
@@ -1,4 +1,4 @@
-/* Copyright (C) 2014 by Jacob Alexander
+/* Copyright (C) 2014-2015 by Jacob Alexander
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,23 @@
 
 // ----- Includes -----
 
+// KLL Generated Defines
+#include <kll_defs.h>
+
+
+
+// ----- Defines -----
+
+#if   ( DebounceDivThreshold_define < 0xFF + 1 )
+#define DebounceCounter uint8_t
+#elif ( DebounceDivThreshold_define < 0xFFFF + 1 )
+#define DebounceCounter uint16_t
+#elif ( DebounceDivThreshold_define < 0xFFFFFFFF + 1 )
+#define DebounceCounter uint32_t
+#else
+#error "Debounce threshold is too high... 32 bit max. Check .kll defines."
+#endif
+
 
 
 // ----- Enums -----
@@ -110,10 +127,10 @@
 
 // Debounce Element
 typedef struct KeyState {
-	KeyPosition prevState;
-	KeyPosition curState;
-	uint16_t activeCount;
-	uint16_t inactiveCount;
+	KeyPosition     prevState;
+	KeyPosition     curState;
+	DebounceCounter activeCount;
+	DebounceCounter inactiveCount;
 } KeyState;