changeset 280:18b61e53753c

Merge remote-tracking branch 'upstream/master'
author Rowan Decker <Smasher816@gmail.com>
date Thu, 12 Feb 2015 19:37:19 -0800
parents 21bea54bb286 (current diff) 42e801e0b444 (diff)
children 71882cd1c362
files Debug/off/led.h Debug/off/print.h Debug/off/setup.cmake README
diffstat 67 files changed, 2772 insertions(+), 1063 deletions(-) [+]
line wrap: on
line diff
--- a/Bootloader/CMakeLists.txt	Mon Dec 22 20:27:33 2014 -0600
+++ b/Bootloader/CMakeLists.txt	Thu Feb 12 19:37:19 2015 -0800
@@ -20,10 +20,26 @@
 #| You _MUST_ clean the build directory if you change this value
 #|
 set( CHIP
-	"mk20dx128vlf5"    # McHCK    mk20dx128vlf5
+	"mk20dx128vlf5"    # McHCK       mk20dx128vlf5
+#	"mk20dx256vlh7"    # Kiibohd-dfu mk20dx256vlh7
 )
 
 
+
+###
+# Compiler Selection
+#
+
+#| *** EXPERIMENTAL ***
+#| Stick with gcc unless you know what you're doing
+#| Currently only arm is supported with clang
+set( COMPILER
+	"gcc"	# arm-none-eabi-gcc / avr-gcc - Default
+#	"clang" # arm-none-eabi
+	CACHE STRING "Compiler Type" )
+
+
+
 ###
 # Bootloader Configuration
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bootloader/Scripts/easyMode.bash	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# Just in case there was an extra ledTest.bash (don't care if error)
+rm /dev/ttyACM0
+
+./swdLoad.bash kiibohd_manufacturing_2014-11-16.bin 0
+
+echo "Press CTRL+C to Continue"
+
+while true; do
+	sleep 1
+	if [ -e /dev/ttyACM0 ]; then
+		./ledTest.bash
+	fi
+done
+
+exit 0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Bootloader/Scripts/ledTest.bash	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,6 @@
+#!/bin/bash
+
+printf "led\r" > /dev/ttyACM0
+
+exit 0
+
--- a/Bootloader/flash.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Bootloader/flash.c	Thu Feb 12 19:37:19 2015 -0800
@@ -68,7 +68,6 @@
 
 int flash_program_section(uintptr_t addr, size_t num_words)
 {
-	GPIOA_PSOR |= (1<<19);
         FTFL.fccob.program_section.fcmd = FTFL_FCMD_PROGRAM_SECTION;
         FTFL.fccob.program_section.addr = addr;
         FTFL.fccob.program_section.num_words = num_words;
--- a/Bootloader/main.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Bootloader/main.c	Thu Feb 12 19:37:19 2015 -0800
@@ -1,5 +1,5 @@
 /* Copyright (c) 2011,2012 Simon Schubert <2@0x2c.org>.
- * Modifications by Jacob Alexander 2014 <haata@kiibohd.com>
+ * Modifications by Jacob Alexander 2014-2015 <haata@kiibohd.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
@@ -15,8 +15,9 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-// ----- Local Includes -----
+// ----- Includes -----
 
+// Local Includes
 #include "mchck.h"
 #include "dfu.desc.h"
 
@@ -79,12 +80,24 @@
 
 void main()
 {
+#if defined(_mk20dx128vlf5_) // Kiibohd-dfu / Infinity
+	// XXX McHCK uses B16 instead of A19
+
 	// Enabling LED to indicate we are in the bootloader
 	GPIOA_PDDR |= (1<<19);
 	// Setup pin - A19 - See Lib/pin_map.mchck for more details on pins
 	PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
 	GPIOA_PSOR |= (1<<19);
 
+#elif defined(_mk20dx256vlh7_) // Kiibohd-dfu
+	// Enabling LED to indicate we are in the bootloader
+	GPIOA_PDDR |= (1<<5);
+	// Setup pin - A5 - See Lib/pin_map.mchck for more details on pins
+	PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+	GPIOA_PSOR |= (1<<5);
+
+#endif
+
         flash_prepare_flashing();
 
         usb_init( &dfu_device );
--- a/CMakeLists.txt	Mon Dec 22 20:27:33 2014 -0600
+++ b/CMakeLists.txt	Thu Feb 12 19:37:19 2015 -0800
@@ -22,13 +22,28 @@
 #	"at90usb646"       # Teensy++ 1.0 (avr)
 #	"at90usb1286"      # Teensy++ 2.0 (avr)
 #	"mk20dx128"        # Teensy   3.0 (arm)
-	"mk20dx128vlf5"    # McHCK    mk20dx128vlf5
+	"mk20dx128vlf5"    # McHCK       mk20dx128vlf5
 #	"mk20dx256"        # Teensy   3.1 (arm)
+#	"mk20dx256vlh7"    # Kiibohd-dfu mk20dx256vlh7
 	CACHE STRING "Microcontroller Chip" )
 
 
 
 ###
+# Compiler Selection
+#
+
+#| *** EXPERIMENTAL ***
+#| Stick with gcc unless you know what you're doing
+#| Currently only arm is supported with clang
+set( COMPILER
+	"gcc"	# arm-none-eabi-gcc / avr-gcc - Default
+#	"clang" # arm-none-eabi
+	CACHE STRING "Compiler Type" )
+
+
+
+###
 # Compiler Intialization
 #
 set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/Lib/CMake )
--- a/Debug/cli/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Debug/cli/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Debug Module |###
 #
-# 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
 #
@@ -11,31 +11,15 @@
 # Module C files
 #
 
-set( DEBUG_SRCS
+set ( Module_SRCS
 	cli.c
 )
 
 
 ###
-# Setup File Dependencies
-#
-
-
-###
-# Module Specific Options
-#
-
-
-###
-# Just in case, you only want this module and are using others as well
-#
-add_definitions( -I${HEAD_DIR}/Debug/off )
-
-
-###
 # Compiler Family Compatibility
 #
-set( DebugModuleCompatibility
+set ( ModuleCompatibility
 	arm
 	avr
 )
--- a/Debug/full/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Debug/full/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Debug Module |###
 #
-# 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
 #
@@ -8,31 +8,18 @@
 
 
 ###
-# Module C files
+# Required Submodules
 #
 
-#| XXX Requires the ../ due to how the paths are constructed
-set( DEBUG_SRCS
-	../cli/cli.c
-	../led/led.c
-	../print/print.c
-)
-
-
-###
-# Module Specific Options
-#
-add_definitions(
-	-I${HEAD_DIR}/Debug/cli
-	-I${HEAD_DIR}/Debug/led
-	-I${HEAD_DIR}/Debug/print
-)
+AddModule ( Debug cli )
+AddModule ( Debug led )
+AddModule ( Debug print )
 
 
 ###
 # Compiler Family Compatibility
 #
-set( DebugModuleCompatibility
+set ( ModuleCompatibility
 	arm
 	avr
 )
--- a/Debug/led/led.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Debug/led/led.c	Thu Feb 12 19:37:19 2015 -0800
@@ -50,7 +50,7 @@
 	// Setup pin - Pin 13 -> C5 - See Lib/pin_map.teensy3 for more details on pins
 	PORTC_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
 
-// MCHCK
+// MCHCK / Kiibohd-dfu
 #elif defined(_mk20dx128vlf5_)
 
 /* Actual MCHCK
@@ -67,6 +67,14 @@
 	// Setup pin - A19 - See Lib/pin_map.mchck for more details on pins
 	PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
 
+// Kiibohd-dfu
+#elif defined(_mk20dx256vlh7_)
+	// Kiibohd-dfu
+	// Enable pin
+	GPIOA_PDDR |= (1<<5);
+
+	// Setup pin - A5 - See Lib/pin_map.mchck for more details on pins
+	PORTA_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
 #endif
 }
 
@@ -120,6 +128,18 @@
 		GPIOA_PCOR |= (1<<19);
 	}
 
+// Kiibohd-dfu
+#elif defined(_mk20dx256vlh7_)
+	// Kiibohd-dfu
+	// Error LED On (A5)
+	if ( on ) {
+		GPIOA_PSOR |= (1<<5);
+	}
+	// Error LED Off
+	else {
+		GPIOA_PCOR |= (1<<5);
+	}
+
 #endif
 }
 
--- a/Debug/led/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Debug/led/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Debug Module |###
 #
-# 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
 #
@@ -11,26 +11,15 @@
 # Module C files
 #
 
-set( DEBUG_SRCS
+set ( Module_SRCS
 	led.c
 )
 
 
 ###
-# Module Specific Options
-#
-
-
-###
-# Just in case, you only want this module and are using others as well
-#
-add_definitions( -I${HEAD_DIR}/Debug/off )
-
-
-###
 # Compiler Family Compatibility
 #
-set( DebugModuleCompatibility
+set ( ModuleCompatibility
 	arm
 	avr
 )
--- a/Debug/off/led.h	Mon Dec 22 20:27:33 2014 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,30 +0,0 @@
-/* Copyright (C) 2011 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
- * 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 __led_h
-#define __led_h
-
-// ----- Disabler Defines -----
-#define init_errorLED()
-#define errorLED(on)
-
-#endif
-
--- a/Debug/off/print.h	Mon Dec 22 20:27:33 2014 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/* Copyright (C) 2011 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
- * 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__
-
-// ----- Disabler Defines -----
-
-#define dPrint(c)
-#define dPrintStr(c)
-#define dPrintStrs(...)
-#define dPrintStrNL(c)
-#define dPrintStrsNL(...)
-
-// Special Msg Constructs (Uses VT100 tags)
-#define dPrintMsg(colour_code_str,msg,...)
-#define printMsg(colour_code_str,msg,str)
-
-// Info Messages
-#define info_dPrint(...)
-#define info_print(str)
-
-// Warning Messages
-#define warn_dPrint(...)
-#define warn_print(str)
-
-// Error Messages
-#define erro_dPrint(...)
-#define erro_print(str)
-
-// Debug Messages
-#define dbug_dPrint(...)
-#define dbug_print(str)
-
-// Static String Printing
-#define print(s) _print(PSTR(s))
-
-// Output Functions
-#define _print(s)
-#define usb_debug_putstr(s)
-#define usb_debug_putstrs(s, ...)
-
-// String Functions
-#define hexToStr(hex, out)
-#define int8ToStr(in, out)
-#define int16ToStr(in, out)
-#define hexToStr_op(in, out, op)
-#define revsStr(in)
-#define lenStr(in)
-
-#endif
-
--- a/Debug/off/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-###| CMake Kiibohd Controller Debug Module |###
-#
-# Written by Jacob Alexander in 2011 for the Kiibohd Controller
-#
-# Released into the Public Domain
-#
-###
-
-
-###
-# Module C files
-#
-#| None!
-
-
-###
-# Module Specific Options
-#
-
-
-###
-# Compiler Family Compatibility
-#
-set( DebugModuleCompatibility
-	arm
-	avr
-)
-
--- a/Debug/print/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Debug/print/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Debug Module |###
 #
-# 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
 #
@@ -11,26 +11,15 @@
 # Module C files
 #
 
-set( DEBUG_SRCS
+set ( Module_SRCS
 	print.c
 )
 
 
 ###
-# Module Specific Options
-#
-
-
-###
-# Just in case, you only want this module and are using others as well
-#
-add_definitions( -I${HEAD_DIR}/Debug/off )
-
-
-###
 # Compiler Family Compatibility
 #
-set( DebugModuleCompatibility
+set ( ModuleCompatibility
 	arm
 	avr
 )
--- a/Lib/CMake/arm.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/CMake/arm.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -13,9 +13,20 @@
 
 #| Set the Compilers (must be set first)
 include( CMakeForceCompiler )
-cmake_force_c_compiler  ( arm-none-eabi-gcc ARMCCompiler )
-cmake_force_cxx_compiler( arm-none-eabi-g++ ARMCxxCompiler )
-set( _CMAKE_TOOLCHAIN_PREFIX arm-none-eabi- )
+message( STATUS "Compiler Selected:" )
+if ( "${COMPILER}" MATCHES "gcc" )
+	cmake_force_c_compiler  ( arm-none-eabi-gcc ARMCCompiler )
+	cmake_force_cxx_compiler( arm-none-eabi-g++ ARMCxxCompiler )
+	set( _CMAKE_TOOLCHAIN_PREFIX arm-none-eabi- )
+	message( "gcc" )
+elseif ( "${COMPILER}" MATCHES "clang" )
+	cmake_force_c_compiler  ( clang   ARMCCompiler )
+	cmake_force_cxx_compiler( clang++ ARMCxxCompiler )
+	set( _CMAKE_TOOLCHAIN_PREFIX llvm- )
+	message( "clang" )
+else ()
+	message( AUTHOR_WARNING "COMPILER: ${COMPILER} - Unknown compiler selection" )
+endif ()
 
 
 
@@ -25,7 +36,9 @@
 
 #| Chip Name (Linker)
 #|
-#| "mk20dx128"        # Teensy   3.0 and McHCK mk20dx128
+#| "mk20dx128vlf5"    # McHCK / Kiibohd-dfu
+#| "mk20dx256vlh7"    # Kiibohd-dfu
+#| "mk20dx128"        # Teensy   3.0
 #| "mk20dx256"        # Teensy   3.1
 
 message( STATUS "Chip Selected:" )
@@ -34,11 +47,16 @@
 
 
 #| Chip Size Database
-#| MCHCK Based
+#| MCHCK Based / Kiibohd-dfu
 if ( "${CHIP}" MATCHES "mk20dx128vlf5" )
 	set( SIZE_RAM    16384 )
 	set( SIZE_FLASH 126976 )
 
+#| Kiibohd-dfu
+elseif ( "${CHIP}" MATCHES "mk20dx256vlh7" )
+	set( SIZE_RAM    65536 )
+	set( SIZE_FLASH 253952 )
+
 #| Teensy 3.0
 elseif ( "${CHIP}" MATCHES "mk20dx128" )
 	set( SIZE_RAM    16384 )
@@ -89,18 +107,21 @@
 
 
 #| USB Defines, this is how the loader programs detect which type of chip base is used
-if ( "${CHIP}" MATCHES "mk20dx128vlf5" )
+message( STATUS "Bootloader Type:" )
+if ( "${CHIP}" MATCHES "mk20dx128vlf5" OR "${CHIP}" MATCHES "mk20dx256vlh7" )
 	set( VENDOR_ID       "0x1C11" )
 	set( PRODUCT_ID      "0xB04D" )
 	set( BOOT_VENDOR_ID  "0x1C11" )
 	set( BOOT_PRODUCT_ID "0xB007" )
 	set( DFU 1 )
+	message( "dfu" )
 elseif ( "${CHIP}" MATCHES "mk20dx128" OR "${CHIP}" MATCHES "mk20dx256" )
 	set( VENDOR_ID       "0x1C11" )
 	set( PRODUCT_ID      "0xB04D" )
 	set( BOOT_VENDOR_ID  "0x16c0" ) # TODO Double check, this is likely incorrect
 	set( BOOT_PRODUCT_ID "0x0487" )
 	set( TEENSY 1 )
+	message( "Teensy" )
 endif ()
 
 
@@ -124,6 +145,8 @@
 if( BOOTLOADER )
 	set( TUNING "-D_bootloader_ -Wno-main -msoft-float -mthumb -fplan9-extensions -ffunction-sections -fdata-sections -fno-builtin -fstrict-volatile-bitfields -flto -fno-use-linker-plugin -nostdlib" )
 	#set( TUNING "-mthumb -fdata-sections -ffunction-sections -fno-builtin -msoft-float -fstrict-volatile-bitfields -flto -fno-use-linker-plugin -fwhole-program -Wno-main -nostartfiles -fplan9-extensions -D_bootloader_" )
+elseif ( "${COMPILER}" MATCHES "clang" )
+	set( TUNING "-target arm-none-eabi -mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin" )
 else()
 	set( TUNING "-mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin -nostartfiles" )
 endif()
@@ -171,5 +194,9 @@
 
 
 #| Lss Flags
-set( LSS_FLAGS -h -S -z )
+if ( "${COMPILER}" MATCHES "clang" )
+	set( LSS_FLAGS -section-headers -triple=arm-none-eabi )
+else ()
+	set( LSS_FLAGS -h -S -z )
+endif ()
 
--- a/Lib/CMake/avr.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/CMake/avr.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -36,10 +36,6 @@
 message( "${MCU}" )
 
 
-#| Indicate to later build step that this is a Teensy
-set( Teensy )
-
-
 #| Chip Size Database
 #| Teensy 1.0
 if ( "${CHIP}" MATCHES "at90usb162" )
@@ -67,10 +63,6 @@
 endif ()
 
 
-#| Only Teensy based AVRs supported
-set ( TEENSY 1 )
-
-
 #| Extra Compiler Sources
 #| Mostly for convenience functions like interrupt handlers
 set( COMPILER_SRCS
@@ -94,6 +86,12 @@
 set( BOOT_PRODUCT_ID "0x047D" )
 
 
+#| Only Teensy based AVRs supported
+set ( TEENSY 1 )
+message( STATUS "Bootloader Type:" )
+message( "Teensy" )
+
+
 #| Compiler flag to set the C Standard level.
 #|     c89   = "ANSI" C
 #|     gnu89 = c89 plus GCC extensions
--- a/Lib/CMake/build.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/CMake/build.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -33,22 +33,33 @@
 	SUFFIX ""                               # XXX Force Windows to keep the .exe off
 )
 
+#| llvm-clang does not have an objcopy equivalent
+if ( "${COMPILER}" MATCHES "clang" )
+	if ( "${COMPILER_FAMILY}" MATCHES "arm" )
+		set ( OBJ_COPY arm-none-eabi-objcopy )
+	elseif ( "${COMPILER_FAMILY}" MATCHES "arm" )
+		set ( OBJ_COPY avr-objcopy )
+	endif ()
+else ()
+	set ( OBJ_COPY ${CMAKE_OBJCOPY} )
+endif ()
+
 
 #| Convert the .ELF into a .bin to load onto the McHCK
-if( DEFINED DFU )
+if ( DEFINED DFU )
 	set( TARGET_BIN ${TARGET}.dfu.bin )
 	add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
-		COMMAND ${CMAKE_OBJCOPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
+		COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
 		COMMENT "Creating dfu binary file:      ${TARGET_BIN}"
 	)
-endif()
+endif ()
 
 
 #| Convert the .ELF into a .HEX to load onto the Teensy
 if ( DEFINED TEENSY )
 	set( TARGET_HEX ${TARGET}.teensy.hex )
 	add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
-		COMMAND ${CMAKE_OBJCOPY} ${HEX_FLAGS} ${TARGET_ELF} ${TARGET_HEX}
+		COMMAND ${OBJ_COPY} ${HEX_FLAGS} ${TARGET_ELF} ${TARGET_HEX}
 		COMMENT "Creating iHex file to load:    ${TARGET_HEX}"
 	)
 endif()
--- a/Lib/CMake/kll.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/CMake/kll.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -20,6 +20,8 @@
 #
 
 if ( NOT EXISTS "${PROJECT_SOURCE_DIR}/kll/kll.py" )
+	message ( STATUS "Downloading latest kll version:" )
+
 	# Make sure git is available
 	find_package ( Git REQUIRED )
 
@@ -27,7 +29,9 @@
 	execute_process ( COMMAND ${GIT_EXECUTABLE} clone https://github.com/kiibohd/kll.git
 		WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
 	)
-else () # Otherwise attempt to update the repo
+elseif ( REFRESH_KLL ) # Otherwise attempt to update the repo
+	message ( STATUS "Checking for latest kll version:" )
+
 	# Clone kll git repo
 	execute_process ( COMMAND ${GIT_EXECUTABLE} pull --rebase
 		WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/kll
--- a/Lib/CMake/modules.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/CMake/modules.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -24,6 +24,7 @@
 
 
 
+
 ###
 # Path Setup
 #
@@ -41,36 +42,16 @@
 # Module Check Function
 #
 
-#| Usage:
-#|  PathPrepend( ModulePath <ListOfFamiliesSupported> )
-#| Uses the ${COMPILER_FAMILY} variable
-function( ModuleCompatibility ModulePath )
-	foreach( mod_var ${ARGN} )
+function ( ModuleCompatibility ModulePath )
+	foreach ( mod_var ${ARGN} )
 		if ( ${mod_var} STREQUAL ${COMPILER_FAMILY} )
 			# Module found, no need to scan further
 			return()
 		endif ()
-	endforeach()
-
-	message( FATAL_ERROR "${ModulePath} does not support the ${COMPILER_FAMILY} family..." )
-endfunction()
-
-
-
-###
-# Module Configuration
-#
+	endforeach ()
 
-#| Additional options, usually define settings
-add_definitions()
-
-#| Include path for each of the modules
-add_definitions(
-	-I${HEAD_DIR}/${ScanModulePath}
-	-I${HEAD_DIR}/${MacroModulePath}
-	-I${HEAD_DIR}/${OutputModulePath}
-	-I${HEAD_DIR}/${DebugModulePath}
-)
+	message ( FATAL_ERROR "${ModulePath} does not support the ${COMPILER_FAMILY} family..." )
+endfunction ()
 
 
 
@@ -81,54 +62,86 @@
 #| Go through lists of sources and append paths
 #| Usage:
 #|  PathPrepend( OutputListOfSources <Prepend Path> <InputListOfSources> )
-macro( PathPrepend Output SourcesPath )
-	unset( tmpSource )
+macro ( PathPrepend Output SourcesPath )
+	unset ( tmpSource )
 
 	# Loop through items
-	foreach( item ${ARGN} )
+	foreach ( item ${ARGN} )
 		# Set the path
-		set( tmpSource ${tmpSource} "${SourcesPath}/${item}" )
-	endforeach()
+		set ( tmpSource ${tmpSource} "${SourcesPath}/${item}" )
+	endforeach ()
 
 	# Finalize by writing the new list back over the old one
-	set( ${Output} ${tmpSource} )
-endmacro()
+	set ( ${Output} ${tmpSource} )
+endmacro ()
+
 
 
-#| Scan Module
-include    (            "${ScanModulePath}/setup.cmake"  )
-PathPrepend(  SCAN_SRCS  ${ScanModulePath} ${SCAN_SRCS}  )
+###
+# Add Module Macro
+#
+# Optional Arg 1: Main Module Check, set to True/1 if adding a main module
+
+function ( AddModule ModuleType ModuleName )
+	# Module path
+	set ( ModulePath                 ${ModuleType}/${ModuleName} )
+	set ( ModuleFullPath ${HEAD_DIR}/${ModuleType}/${ModuleName} )
 
-#| Macro Module
-include    (           "${MacroModulePath}/setup.cmake"  )
-PathPrepend( MACRO_SRCS ${MacroModulePath} ${MACRO_SRCS} )
+	# Include setup.cmake file
+	include ( ${ModuleFullPath}/setup.cmake )
+
+	# Check if this is a main module add
+	foreach ( extraArg ${ARGN} )
+		# Make sure this isn't a submodule
+		if ( DEFINED SubModule )
+			message ( FATAL_ERROR
+			"The '${ModuleName}' module is not a stand-alone module, and requires further setup."
+			)
+		endif ()
+	endforeach ()
 
-#| Output Module
-include    (             "${OutputModulePath}/setup.cmake"   )
-PathPrepend( OUTPUT_SRCS  ${OutputModulePath} ${OUTPUT_SRCS} )
+	# PathPrepend to give proper paths to each of the source files
+	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} )
+
+	# Add .h files
+	add_definitions ( -I${ModuleFullPath} )
 
-#| Debugging Module
-include    (           "${DebugModulePath}/setup.cmake"  )
-PathPrepend( DEBUG_SRCS ${DebugModulePath} ${DEBUG_SRCS} )
+	# Check module compatibility
+	ModuleCompatibility( ${ModulePath} ${ModuleCompatibility} )
+
+	# Check if this is a main module add
+	foreach ( extraArg ${ARGN} )
+		# Display detected source files
+		if ( NOT DEFINED SubModule )
+			message ( STATUS "Detected ${ModuleType} Module Source Files:" )
+			message ( "${${ModuleType}_SRCS}" )
+		endif ()
+	endforeach ()
+
+	# Finally, add the sources to the parent scope (i.e. return)
+	set ( ${ModuleType}_SRCS ${${ModuleType}_SRCS} PARENT_SCOPE )
+endfunction ()
 
 
-#| Print list of all module sources
-message( STATUS "Detected Scan Module Source Files:" )
-message( "${SCAN_SRCS}" )
-message( STATUS "Detected Macro Module Source Files:" )
-message( "${MACRO_SRCS}" )
-message( STATUS "Detected Output Module Source Files:" )
-message( "${OUTPUT_SRCS}" )
-message( STATUS "Detected Debug Module Source Files:" )
-message( "${DEBUG_SRCS}" )
+#| Add main modules
+AddModule ( Scan   ${ScanModule}   1 )
+AddModule ( Macro  ${MacroModule}  1 )
+AddModule ( Output ${OutputModule} 1 )
+AddModule ( Debug  ${DebugModule}  1 )
 
 
 
 ###
 # CMake Module Checking
 #
-find_package( Git REQUIRED )
-find_package( Ctags ) # Optional
+find_package ( Git REQUIRED )
+find_package ( Ctags ) # Optional
 
 
 
@@ -220,10 +233,10 @@
 set( SRCS
 	${MAIN_SRCS}
 	${COMPILER_SRCS}
-	${SCAN_SRCS}
-	${MACRO_SRCS}
-	${OUTPUT_SRCS}
-	${DEBUG_SRCS}
+	${Scan_SRCS}
+	${Macro_SRCS}
+	${Output_SRCS}
+	${Debug_SRCS}
 )
 
 #| Directories to include by default
@@ -232,18 +245,6 @@
 
 
 ###
-# Module Compatibility Check
-#
-
-#| Check for whether the set modules are compatible with the specified compiler family
-ModuleCompatibility( ${ScanModulePath}   ${ScanModuleCompatibility}   )
-ModuleCompatibility( ${MacroModulePath}  ${MacroModuleCompatibility}  )
-ModuleCompatibility( ${OutputModulePath} ${OutputModuleCompatibility} )
-ModuleCompatibility( ${DebugModulePath}  ${DebugModuleCompatibility}  )
-
-
-
-###
 # ctag Generation
 #
 
--- a/Lib/Interrupts.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/Interrupts.h	Thu Feb 12 19:37:19 2015 -0800
@@ -29,7 +29,7 @@
 #define __INTERRUPTS_H
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 #include <Lib/mk20dx.h>
 
@@ -45,7 +45,7 @@
 // ----- Defines -----
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 // Map the Interrupt Enable/Disable to the AVR names
 #define cli() __disable_irq()
--- a/Lib/MacroLib.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/MacroLib.h	Thu Feb 12 19:37:19 2015 -0800
@@ -34,7 +34,7 @@
 
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 #include <Lib/mk20dx.h>
 #include <Lib/delay.h>
--- a/Lib/MainLib.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/MainLib.h	Thu Feb 12 19:37:19 2015 -0800
@@ -34,7 +34,7 @@
 
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 #include <Lib/mk20dx.h>
 
--- a/Lib/OutputLib.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/OutputLib.h	Thu Feb 12 19:37:19 2015 -0800
@@ -30,7 +30,7 @@
 // ----- Includes -----
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 #include <Lib/mk20dx.h>
 #include <Lib/delay.h>
--- a/Lib/ScanLib.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/ScanLib.h	Thu Feb 12 19:37:19 2015 -0800
@@ -34,7 +34,7 @@
 
 
 // ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 
 #include <Lib/mk20dx.h>
 #include <Lib/delay.h>
--- a/Lib/mk20dx.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/mk20dx.c	Thu Feb 12 19:37:19 2015 -0800
@@ -1,7 +1,7 @@
 /* Teensyduino Core Library
  * http://www.pjrc.com/teensy/
  * Copyright (c) 2013 PJRC.COM, LLC.
- * Modifications by Jacob Alexander 2014
+ * Modifications by Jacob Alexander 2014-2015
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -29,6 +29,8 @@
  * SOFTWARE.
  */
 
+// ----- Includes -----
+
 // Local Includes
 #include "mk20dx.h"
 
@@ -246,7 +248,7 @@
 	portd_isr,                                      // 59 Pin detect (Port D)
 	porte_isr,                                      // 60 Pin detect (Port E)
 	software_isr,                                   // 61 Software interrupt
-#elif defined(_mk20dx256_)
+#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 	dma_ch0_isr,                                    // 16 DMA channel 0 transfer complete
 	dma_ch1_isr,                                    // 17 DMA channel 1 transfer complete
 	dma_ch2_isr,                                    // 18 DMA channel 2 transfer complete
@@ -377,12 +379,34 @@
 	0xFF, // EEPROM Protection Byte FEPROT
 	0xFF, // Data Flash Protection Byte FDPROT
 };
+#elif defined(_mk20dx256vlh7_) && defined(_bootloader_)
+// XXX Byte labels may be in incorrect positions, double check before modifying
+//     FSEC is in correct location -Jacob
+__attribute__ ((section(".flashconfig"), used))
+const uint8_t flashconfigbytes[16] = {
+	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Backdoor Verif Key 28.3.1
+
+	//
+	// Protecting the first 8k of Flash memory from being over-written while running (bootloader protection)
+	// Still possible to overwrite the bootloader using an external flashing device
+	// For more details see:
+	//  http://cache.freescale.com/files/training/doc/dwf/AMF_ENT_T1031_Boston.pdf (page 8)
+	//  http://cache.freescale.com/files/microcontrollers/doc/app_note/AN4507.pdf
+	//  http://cache.freescale.com/files/32bit/doc/ref_manual/K20P64M72SF1RM.pdf (28.34.6)
+	//
+	0xFF, 0xFF, 0xFF, 0xFE, // Program Flash Protection Bytes FPROT0-3
+
+	0xBE, // Flash security byte FSEC
+	0x03, // Flash nonvolatile option byte FOPT
+	0xFF, // EEPROM Protection Byte FEPROT
+	0xFF, // Data Flash Protection Byte FDPROT
 #endif
 
 
 
 // ----- Functions -----
 
+#if ( defined(_mk20dx128vlf5_) || defined(_mk20dx256vlh7_) ) && defined(_bootloader_) // Bootloader Section
 __attribute__((noreturn))
 static inline void jump_to_app( uintptr_t addr )
 {
@@ -393,6 +417,7 @@
         // NOTREACHED
         __builtin_unreachable();
 }
+#endif
 
 void *memset( void *addr, int val, unsigned int len )
 {
@@ -430,18 +455,20 @@
 __attribute__ ((section(".startup")))
 void ResetHandler()
 {
-	// Disable Watchdog
-	WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
-	WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
-	WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
-
-#if defined(_mk20dx128vlf5_) && defined(_bootloader_) // Bootloader Section
+#if ( defined(_mk20dx128vlf5_) || defined(_mk20dx256vlh7_) ) && defined(_bootloader_) // Bootloader Section
 	extern uint32_t _app_rom;
 
 	// We treat _app_rom as pointer to directly read the stack
 	// pointer and check for valid app code.  This is no fool
 	// proof method, but it should help for the first flash.
-	if ( RCM_SRS0 & 0x40 || _app_rom == 0xffffffff ||
+	//
+	// Purposefully disabling the watchdog *after* the reset check this way
+	// if the chip goes into an odd state we'll reset to the bootloader (invalid firmware image)
+	// RCM_SRS0 & 0x20
+	//
+	// Also checking for ARM lock-up signal (invalid firmware image)
+	// RCM_SRS1 & 0x02
+	if ( RCM_SRS0 & 0x40 || RCM_SRS0 & 0x20 || RCM_SRS1 & 0x02 || _app_rom == 0xffffffff ||
 	  memcmp( (uint8_t*)&VBAT, sys_reset_to_loader_magic, sizeof(sys_reset_to_loader_magic) ) == 0 ) // Check for soft reload
 	{
 		memset( (uint8_t*)&VBAT, 0, sizeof(VBAT) );
@@ -453,9 +480,13 @@
 		jump_to_app( addr );
 	}
 #endif
+	// Disable Watchdog
+	WDOG_UNLOCK = WDOG_UNLOCK_SEQ1;
+	WDOG_UNLOCK = WDOG_UNLOCK_SEQ2;
+	WDOG_STCTRLH = WDOG_STCTRLH_ALLOWUPDATE;
 
-	uint32_t *src = &_etext;
-	uint32_t *dest = &_sdata;
+	uint32_t *src = (uint32_t*)&_etext;
+	uint32_t *dest = (uint32_t*)&_sdata;
 
 	// Enable clocks to always-used peripherals
 	SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO
@@ -483,11 +514,11 @@
 	}
 
 	// Prepare RAM
-	while ( dest < &_edata ) *dest++ = *src++;
-	dest = &_sbss;
-	while ( dest < &_ebss ) *dest++ = 0;
+	while ( dest < (uint32_t*)&_edata ) *dest++ = *src++;
+	dest = (uint32_t*)&_sbss;
+	while ( dest < (uint32_t*)&_ebss ) *dest++ = 0;
 
-// MCHCK
+// MCHCK / Kiibohd-dfu
 #if defined(_mk20dx128vlf5_)
 	// Default all interrupts to medium priority level
 	for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ )
@@ -501,14 +532,12 @@
 	// USB Clock and FLL select
 	SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_TRACECLKSEL;
 
-// Teensy 3.0 and 3.1
+// Teensy 3.0 and 3.1 and Kiibohd-dfu (mk20dx256vlh7)
 #else
-	unsigned int i;
-
 	SCB_VTOR = 0;	// use vector table in flash
 
 	// default all interrupts to medium priority level
-	for ( i = 0; i < NVIC_NUM_INTERRUPTS; i++ )
+	for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ )
 	{
 		NVIC_SET_PRIORITY( i, 128 );
 	}
--- a/Lib/mk20dx.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/mk20dx.h	Thu Feb 12 19:37:19 2015 -0800
@@ -1847,7 +1847,7 @@
 #define IRQ_SOFTWARE		45
 #define NVIC_NUM_INTERRUPTS	46
 
-#elif defined(_mk20dx256_)
+#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 #define IRQ_DMA_CH0		0
 #define IRQ_DMA_CH1		1
 #define IRQ_DMA_CH2		2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/mk20dx256vlh7.bootloader.ld	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,114 @@
+/* Teensyduino Core Library
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2013 PJRC.COM, LLC.
+ * Modifications by Jacob Alexander 2014 for use with McHCK and Kiibohd-dfu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 2. If the Software is incorporated into a build system that allows
+ * selection among a list of target devices, then similar target
+ * devices manufactured by PJRC.COM must be included in the list of
+ * target devices and selectable in the same manner.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* XXX Not tested yet -HaaTa */
+
+MEMORY
+{
+	FLASH (rx)     : ORIGIN = 0x0, LENGTH = 256K
+	FLASH_APP (rx) : ORIGIN = 8K, LENGTH = 256K-8K
+	RAM  (rwx)     : ORIGIN = 0x20000000 - 64K / 2, LENGTH = 64K
+}
+
+/* Starting Address of the application ROM */
+_app_rom = ORIGIN( FLASH_APP );
+
+FlexRAM = 0x14000000;
+FTFL = 0x40020000;
+SCB = 0xe000ed00;
+USB0 = 0x40072000;
+SIM = 0x40047000;
+
+/* Section Definitions */
+SECTIONS
+{
+	.text :
+	{
+		. = 0;
+		KEEP(* (.vectors))
+		*(.startup*)
+		*(.rodata*)
+		. = 0x400;
+		KEEP(* (.flashconfig))
+		*(.text*)
+		. = ALIGN(4);
+		KEEP(*(.init))
+	} > FLASH
+
+	.ARM.exidx :
+	{
+		__exidx_start = .;
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+		__exidx_end = .;
+	} > FLASH
+	_etext = .;
+
+	.usbdescriptortable (NOLOAD) : {
+		. = ALIGN(512);
+		*(.usbdescriptortable*)
+	} > RAM
+
+	.dmabuffers (NOLOAD) : {
+		. = ALIGN(4);
+		*(.dmabuffers*)
+	} > RAM
+
+	.usbbuffers (NOLOAD) : {
+		. = ALIGN(4);
+		*(.usbbuffers*)
+	} > RAM
+
+	.data : AT (_etext) {
+		. = ALIGN(4);
+		_sdata = .;
+		*(SORT_BY_ALIGNMENT(.ramtext.*) SORT_BY_ALIGNMENT(.data*))
+		*(.data*)
+		. = ALIGN(4);
+		_edata = .;
+	} > RAM
+
+	.noinit (NOLOAD) : {
+		*(.noinit*)
+	} > RAM
+
+	.bss : {
+		. = ALIGN(4);
+		_sbss = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		_ebss = .;
+		__bss_end = .;
+	} > RAM
+
+	_estack = ORIGIN(RAM) + LENGTH(RAM);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Lib/mk20dx256vlh7.ld	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,101 @@
+/* Teensyduino Core Library
+ * http://www.pjrc.com/teensy/
+ * Copyright (c) 2013 PJRC.COM, LLC.
+ * Modifications by Jacob Alexander 2014 for use with McHCK and Kiibohd-dfu
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * 1. The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * 2. If the Software is incorporated into a build system that allows
+ * selection among a list of target devices, then similar target
+ * devices manufactured by PJRC.COM must be included in the list of
+ * target devices and selectable in the same manner.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/* XXX Not tested yet -HaaTa */
+
+MEMORY
+{
+	FLASH (rx) : ORIGIN = 8K, LENGTH = 256K-8K
+	RAM  (rwx) : ORIGIN = 0x20000000 - 64K / 2, LENGTH = 64K
+}
+
+/* Section Definitions */
+SECTIONS
+{
+	.text :
+	{
+		. = 0;
+		KEEP(* (.vectors))
+		*(.startup*)
+		*(.text*)
+		*(.rodata*)
+		. = ALIGN(4);
+		KEEP(*(.init))
+	} > FLASH
+
+	.ARM.exidx :
+	{
+		__exidx_start = .;
+		*(.ARM.exidx* .gnu.linkonce.armexidx.*)
+		__exidx_end = .;
+	} > FLASH
+	_etext = .;
+
+	.usbdescriptortable (NOLOAD) : {
+		. = ALIGN(512);
+		*(.usbdescriptortable*)
+	} > RAM
+
+	.dmabuffers (NOLOAD) : {
+		. = ALIGN(4);
+		*(.dmabuffers*)
+	} > RAM
+
+	.usbbuffers (NOLOAD) : {
+		. = ALIGN(4);
+		*(.usbbuffers*)
+	} > RAM
+
+	.data : AT (_etext) {
+		. = ALIGN(4);
+		_sdata = .;
+		*(.data*)
+		. = ALIGN(4);
+		_edata = .;
+	} > RAM
+
+	.noinit (NOLOAD) : {
+		*(.noinit*)
+	} > RAM
+
+	.bss : {
+		. = ALIGN(4);
+		_sbss = .;
+		*(.bss*)
+		*(COMMON)
+		. = ALIGN(4);
+		_ebss = .;
+		__bss_end = .;
+	} > RAM
+
+	_estack = ORIGIN(RAM) + LENGTH(RAM);
+}
+
--- a/Lib/pin_map.teensy3	Mon Dec 22 20:27:33 2014 -0600
+++ b/Lib/pin_map.teensy3	Thu Feb 12 19:37:19 2015 -0800
@@ -1,39 +1,39 @@
-// Pin  Name    Function     Hardware
+// Pin  Name      Function     Hardware
 // ----------------------------------
-//  0   B16                  RX1
-//  1   B17                  TX1
-//  2   D0                   PCS0
-//  3   A12     FTM1_CH0     PWM (CAN TX - Teensy 3.1) I2S_TXD0
-//  4   A13     FTM1_CH1     PWM (CAN RX - Teensy 3.1) I2S_TX_FS
-//  5   D7      FTM0_CH7     PWM
-//  6   D4      FTM0_CH4     PWM PCS1
-//  7   D2                   RX3 SOUT0
-//  8   D3                   TX3 SIN0
-//  9   C3      FTM0_CH2     RX2 PWM PCS1 I2S_TX_BCLK
-// 10   C4      FTM0_CH3     TX2 PWM PCS0
-// 11   C6                   SOUT0 I2S_RX_BCLK I2S_MCLK
-// 12   C7                   SIN0 I2S_RX_FS
-// 13   C5      LED          SCK0 I2S_RXD0
-// 14   D1                   SCK0
-// 15   C0
-// 16   B0     (FTM1_CH0)    SCL0
-// 17   B1     (FTM1_CH1)    SDA0
-// 18   B3                   SDA0
-// 19   B2                   SCL0
-// 20   D5      FTM0_CH5     PWM PCS2
-// 21   D6      FTM0_CH6     PWM PCS3
-// 22   C1      FTM0_CH0     PWM PCS3 I2S_TXD0
-// 23   C2      FTM0_CH1     PWM PCS2 I2S_TX_FS
-// 24   A5     (FTM0_CH2)    I2S_TX_BCLK
-// 25   B19                 (PWM - Teensy 3.1) I2S_TX_FS
-// 26   E1
-// 27   C9                   I2S_RX_BCLK
-// 28   C8                   I2S_MCLK
-// 29   C10                 (SCL1 - Teensy 3.1) I2S_RX_FS
-// 30   C11                 (SDA1 - Teensy 3.1) I2S_RXD1
-// 31   E0
-// 32   B18                 (PWM - Teensy 3.1) I2S_TX_BCLK
-// 33   A4    (FTM0_CH1)
+//  0   PTB16                  RX0
+//  1   PTB17                  TX0
+//  2   PTD0                   PCS0
+//  3   PTA12     FTM1_CH0     PWM (CAN TX - Teensy 3.1) I2S_TXD0
+//  4   PTA13     FTM1_CH1     PWM (CAN RX - Teensy 3.1) I2S_TX_FS
+//  5   PTD7      FTM0_CH7     PWM
+//  6   PTD4      FTM0_CH4     PWM PCS1
+//  7   PTD2                   RX2 SOUT0
+//  8   PTD3                   TX2 SIN0
+//  9   PTC3      FTM0_CH2     RX1 PWM PCS1 I2S_TX_BCLK
+// 10   PTC4      FTM0_CH3     TX1 PWM PCS0
+// 11   PTC6                   SOUT0 I2S_RX_BCLK I2S_MCLK
+// 12   PTC7                   SIN0 I2S_RX_FS
+// 13   PTC5      LED          SCK0 I2S_RXD0
+// 14   PTD1                   SCK0
+// 15   PTC0                   PCS4 I2S_TXD1
+// 16   PTB0     (FTM1_CH0)    SCL0
+// 17   PTB1     (FTM1_CH1)    SDA0
+// 18   PTB3                   SDA0
+// 19   PTB2                   SCL0
+// 20   PTD5      FTM0_CH5     PWM PCS2
+// 21   PTD6      FTM0_CH6     PWM PCS3
+// 22   PTC1      FTM0_CH0     PWM PCS3 I2S_TXD0
+// 23   PTC2      FTM0_CH1     PWM PCS2 I2S_TX_FS
+// 24   PTA5     (FTM0_CH2)    I2S_TX_BCLK
+// 25   PTB19                 (PWM - Teensy 3.1) I2S_TX_FS
+// 26   PTE1                   RX1 SCL1
+// 27   PTC9                   I2S_RX_BCLK
+// 28   PTC8                   I2S_MCLK
+// 29   PTC10                 (SCL1 - Teensy 3.1) I2S_RX_FS
+// 30   PTC11                 (SDA1 - Teensy 3.1) I2S_RXD1
+// 31   PTE0                   TX1 SDA1
+// 32   PTB18                 (PWM - Teensy 3.1) I2S_TX_BCLK
+// 33   PTA4    (FTM0_CH1)
 // 34          analog only
 // 35          analog only
 // 36          analog only
@@ -43,13 +43,10 @@
 // 40          DAC/A14
 
 // not available to user:
-//      A0      FTM0_CH5      SWD Clock
-//      A1      FTM0_CH6      USB ID
-//      A2      FTM0_CH7      SWD Trace
-//      A3      FTM0_CH0      SWD Data
-
-// misc
-        C0                    PCS4 I2S_TXD1
+//      A0        FTM0_CH5      SWD Clock
+//      A1        FTM0_CH6      USB ID
+//      A2        FTM0_CH7      SWD Trace
+//      A3        FTM0_CH0      SWD Data
 
 // Analog              Channel     Channel
 //  Pin   Pin   Name   ADC0        ADC1
--- a/LoadFile/load.dfu	Mon Dec 22 20:27:33 2014 -0600
+++ b/LoadFile/load.dfu	Thu Feb 12 19:37:19 2015 -0800
@@ -1,8 +1,67 @@
 #!/bin/bash
+# Convenience script for loading firmware onto a dfu type device
+# By default, initiates dfu-util
+
+SERIAL_PORT=""
+AUTO_SCREEN_SESSION=""
+PROG_NAME=$(basename $0)
+
+# Parse all the command line arguments
+while (( "$#" >= "1" )); do
+	# Scan each argument
+	key="$1"
+	case $key in
+	-a|--autoscreen)
+		AUTO_SCREEN_SESSION="$2"
+		shift
+		;;
+	-f|--fastload)
+		SERIAL_PORT="$2"
+		shift
+		;;
+	-h|--help)
+		echo "Usage: $PROG_NAME [options...]"
+		echo ""
+		echo "Loads the most recent built firmware (@TARGET_BIN@) to the device."
+		echo "  (load.dfu)"
+		echo ""
+		echo "Arguments:"
+		echo " -a, --autoscreen SERIAL_PORT  Use screen on the specified serial port after loading."
+		echo "                               e.g. /dev/ttyACM0"
+		echo " -f, --fastload SERIAL_PORT    Send the reload command to the debug terminal."
+		echo "                               e.g. /dev/ttyACM0"
+		echo "                               NOTE: May not work due to non-functional terminal, or disable remote flashing"
+		echo " -h, --help                    This message."
+		exit 1
+		;;
+	*)
+		echo "INVALID ARG: '$1'"
+		exit 2
+		;;
+	esac
+
+	# Shift to the next argument
+	shift
+done
+
+# If a SERIAL_PORT was specified set the uC into reflash mode
+# XXX May not be successful if uC is not in a good state (or does not allow remote flashing)
+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
+fi
 
 # Load via dfu-util
 # Used for McHCK based uCs
 dfu-util -D @TARGET_BIN@
+EXIT_STATUS=$?
 
-exit $?
+# Load Screen Session if specified
+if (( "$EXIT_STATUS" == "0" )) && [[ "$AUTO_SCREEN_SESSION" != "" ]]; then
+	sleep 0.1
+	screen $AUTO_SCREEN_SESSION
+fi
 
+exit $EXIT_STATUS
+
--- a/LoadFile/load.teensy	Mon Dec 22 20:27:33 2014 -0600
+++ b/LoadFile/load.teensy	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,50 @@
 #!/bin/bash
+# Convenience script for loading firmware onto a teensy type device
+# By default, initiates teensy-load-cli
+
+SERIAL_PORT=""
+AUTO_SCREEN_SESSION=""
+PROG_NAME=$(basename $0)
 
-#| First check to see teensy-loader-cli has been compiled
+# Parse all the command line arguments
+while (( "$#" >= "1" )); do
+	# Scan each argument
+	key="$1"
+	case $key in
+	-a|--autoscreen)
+		AUTO_SCREEN_SESSION="$2"
+		shift
+		;;
+	-f|--fastload)
+		SERIAL_PORT="$2"
+		shift
+		;;
+	-h|--help)
+		echo "Usage: $PROG_NAME [options...]"
+		echo ""
+		echo "Loads the most recent built firmware (@TARGET_BIN@) to the device."
+		echo "  (load.teensy)"
+		echo ""
+		echo "Arguments:"
+		echo " -a, --autoscreen SERIAL_PORT  Use screen on the specified serial port after loading."
+		echo "                               e.g. /dev/ttyACM0"
+		echo " -f, --fastload SERIAL_PORT    Send the reload command to the debug terminal."
+		echo "                               e.g. /dev/ttyACM0"
+		echo "                               NOTE: May not work due to non-functional terminal, or disable remote flashing"
+		echo " -h, --help                    This message."
+		exit 1
+		;;
+	*)
+		echo "INVALID ARG: '$1'"
+		exit 2
+		;;
+	esac
+
+	# Shift to the next argument
+	shift
+done
+
+# First check to see teensy-loader-cli has been compiled
 if [ ! -e teensy-loader-cli/teensy-loader-cli ]; then
 	# Compile teensy-loader-cli
 	mkdir -p teensy-loader-cli
@@ -10,8 +54,23 @@
 	cd -
 fi
 
-#| Loads the hex file onto the teensy
-teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@
+# If a SERIAL_PORT was specified set the uC into reflash mode
+# XXX May not be successful if uC is not in a good state (or does not allow remote flashing)
+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
+fi
 
-exit $?
+# Loads the hex file onto the teensy
+teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@
+EXIT_STATUS=$?
 
+# Load Screen Session if specified
+if (( "$EXIT_STATUS" == "0" )) && [[ "$AUTO_SCREEN_SESSION" != "" ]]; then
+	sleep 0.1
+	screen $AUTO_SCREEN_SESSION
+fi
+
+exit $EXIT_STATUS
+
--- a/LoadFile/winload.teensy	Mon Dec 22 20:27:33 2014 -0600
+++ b/LoadFile/winload.teensy	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,49 @@
 #!/bin/bash
+# Convenience script for loading firmware onto a teensy type device
+# By default, initiates teensy-load-cli
+
+SERIAL_PORT=""
+AUTO_SCREEN_SESSION=""
+PROG_NAME=$(basename $0)
 
-#| First check to see teensy-loader-cli has been compiled
+# Parse all the command line arguments
+while (( "$#" >= "1" )); do
+	# Scan each argument
+	key="$1"
+	case $key in
+	-a|--autoscreen)
+		AUTO_SCREEN_SESSION="$2"
+		shift
+		;;
+	-f|--fastload)
+		SERIAL_PORT="$2"
+		shift
+		;;
+	-h|--help)
+		echo "Usage: $PROG_NAME [options...]"
+		echo ""
+		echo "Loads the most recent built firmware (@TARGET_BIN@) to the device."
+		echo "Requires Cygwin."
+		echo "  (winload.teensy)"
+		echo ""
+		echo "Arguments:"
+		echo " -f, --fastload SERIAL_PORT    Send the reload command to the debug terminal."
+		echo "                               e.g. /dev/ttyACM0"
+		echo "                               NOTE: May not work due to non-functional terminal, or disable remote flashing"
+		echo " -h, --help                    This message."
+		exit 1
+		;;
+	*)
+		echo "INVALID ARG: '$1'"
+		exit 2
+		;;
+	esac
+
+	# Shift to the next argument
+	shift
+done
+
+# First check to see teensy-loader-cli has been compiled
 if [ ! -e teensy-loader-cli/teensy-loader-cli ]; then
 	# Compile teensy-loader-cli
 	mkdir -p teensy-loader-cli
@@ -10,8 +53,17 @@
 	cd -
 fi
 
-#| Loads the hex file onto the teensy
-teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@
+# If a SERIAL_PORT was specified set the uC into reflash mode
+# XXX May not be successful if uC is not in a good state (or does not allow remote flashing)
+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
+fi
 
-exit $?
+# Loads the hex file onto the teensy
+teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@
+EXIT_STATUS=$?
 
+exit $EXIT_STATUS
+
--- a/Macro/PartialMap/kll.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Macro/PartialMap/kll.h	Thu Feb 12 19:37:19 2015 -0800
@@ -54,7 +54,7 @@
 // This needs to be defined per microcontroller
 // e.g. mk20s  -> 32 bit
 //      atmega -> 16 bit
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 typedef uint32_t nat_ptr_t;
 #elif defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 typedef uint16_t nat_ptr_t;
--- a/Macro/PartialMap/macro.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Macro/PartialMap/macro.c	Thu Feb 12 19:37:19 2015 -0800
@@ -616,7 +616,7 @@
 
 
 // Evaluate/Update TriggerMacro
-inline TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex )
+TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex )
 {
 	// Lookup TriggerMacro
 	const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ];
@@ -1006,7 +1006,7 @@
 void cliFunc_capList( char* args )
 {
 	print( NL );
-	info_msg("Capabilities List");
+	info_msg("Capabilities List ");
 	printHex( CapabilitiesNum );
 
 	// Iterate through all of the capabilities and display them
--- a/Macro/PartialMap/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Macro/PartialMap/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Macro Module |###
 #
-# 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
 #
@@ -11,20 +11,15 @@
 # Module C files
 #
 
-set( MACRO_SRCS
+set ( Module_SRCS
 	macro.c
 )
 
 
 ###
-# Module Specific Options
-#
-
-
-###
 # Compiler Family Compatibility
 #
-set( MacroModuleCompatibility
+set ( ModuleCompatibility
 	arm
 	avr
 )
--- a/Output/pjrcUSB/arm/usb_desc.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/arm/usb_desc.c	Thu Feb 12 19:37:19 2015 -0800
@@ -567,17 +567,17 @@
 struct usb_string_descriptor_struct usb_string_manufacturer_name_default = {
         sizeof(STR_MANUFACTURER),
         3,
-        STR_MANUFACTURER
+        {STR_MANUFACTURER}
 };
 struct usb_string_descriptor_struct usb_string_product_name_default = {
 	sizeof(STR_PRODUCT),
         3,
-        STR_PRODUCT
+        {STR_PRODUCT}
 };
 struct usb_string_descriptor_struct usb_string_serial_number_default = {
 	sizeof(STR_SERIAL),
         3,
-	STR_SERIAL
+	{STR_SERIAL}
 };
 
 
--- a/Output/pjrcUSB/arm/usb_dev.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/arm/usb_dev.c	Thu Feb 12 19:37:19 2015 -0800
@@ -1098,12 +1098,17 @@
 
 
 
-void usb_init()
+uint8_t usb_init()
 {
 	#ifdef UART_DEBUG
 	print("USB INIT"NL);
 	#endif
 
+	// If no USB cable is attached, do not initialize usb
+	// XXX Test -HaaTa
+	//if ( USB0_OTGISTAT & USB_OTGSTAT_ID )
+	//	return 0;
+
 	// Clear out endpoints table
 	for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ )
 	{
@@ -1147,6 +1152,8 @@
 
 	// enable d+ pullup
 	USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
+
+	return 1;
 }
 
 // return 0 if the USB is not configured, or the configuration
--- a/Output/pjrcUSB/arm/usb_dev.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/arm/usb_dev.h	Thu Feb 12 19:37:19 2015 -0800
@@ -61,8 +61,8 @@
 // ----- Functions -----
 
 uint8_t usb_configured(); // is the USB port configured
+uint8_t usb_init(); // Returns 1 on success, 0 if no cable is attached
 
-void usb_init();
 void usb_isr();
 void usb_tx( uint32_t endpoint, usb_packet_t *packet );
 void usb_tx_isr( uint32_t endpoint, usb_packet_t *packet );
--- a/Output/pjrcUSB/avr/usb_keyboard_serial.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/avr/usb_keyboard_serial.c	Thu Feb 12 19:37:19 2015 -0800
@@ -590,8 +590,13 @@
 
 
 // initialize USB
-void usb_init()
+uint8_t usb_init()
 {
+	// Check to see if a usb cable has been plugged in
+	// XXX Not tested (also, not currently needed) -HaaTa
+	//if ( USB0_STAT & (1 << 1)
+	//	return 0;
+
 	HW_CONFIG();
 	USB_FREEZE();				// enable USB
 	PLL_CONFIG();				// config PLL
@@ -604,6 +609,8 @@
 
 	// Disable watchdog timer after possible software reset
 	//wdt_init(); // XXX Not working...seems to be ok without this, not sure though
+
+	return 1;
 }
 
 // return 0 if the USB is not configured, or the configuration
--- a/Output/pjrcUSB/avr/usb_keyboard_serial.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/avr/usb_keyboard_serial.h	Thu Feb 12 19:37:19 2015 -0800
@@ -46,7 +46,7 @@
 // ----- Function Declarations -----
 
 // Basic USB Configuration
-void usb_init();			// initialize everything
+uint8_t usb_init();			// initialize everything
 uint8_t usb_configured();		// is the USB port configured
 
 // Keyboard HID Functions
--- a/Output/pjrcUSB/output_com.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/output_com.c	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -33,7 +33,7 @@
 // USB Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
 #include "avr/usb_keyboard_serial.h"
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 #include "arm/usb_dev.h"
 #include "arm/usb_keyboard.h"
 #include "arm/usb_serial.h"
@@ -124,6 +124,11 @@
 // count until idle timeout
          uint8_t  USBKeys_Idle_Count = 0;
 
+// Indicates whether the Output module is fully functional
+// 0 - Not fully functional, 1 - Fully functional
+// 0 is often used to show that a USB cable is not plugged in (but has power)
+         uint8_t  Output_Available = 0;
+
 
 
 // ----- Capabilities -----
@@ -473,9 +478,11 @@
 {
 	// Initialize the USB, and then wait for the host to set configuration.
 	// This will hang forever if USB does not initialize
-	usb_init();
-
-	while ( !usb_configured() );
+	// If no USB cable is attached, does not try and initialize USB
+	if ( usb_init() )
+	{
+		while ( !usb_configured() );
+	}
 
 	// Register USB Output CLI dictionary
 	CLI_registerDictionary( outputCLIDict, outputCLIDictName );
@@ -549,7 +556,7 @@
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 	uint16_t count = 0;
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 	uint32_t count = 0;
 #endif
 	// Count characters until NULL character, then send the amount counted
--- a/Output/pjrcUSB/output_com.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/output_com.h	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -79,6 +79,8 @@
 
 extern USBKeyChangeState USBKeys_Changed;
 
+extern          uint8_t  Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
 
 
 // ----- Capabilities -----
--- a/Output/pjrcUSB/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/pjrcUSB/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller USB Module |###
 #
-# Written by Jacob Alexander in 2011-2013 for the Kiibohd Controller
+# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller
 #
 # Released into the Public Domain
 #
@@ -11,11 +11,10 @@
 # Module C files
 #
 
-
 #| AVR Compiler
 if ( ${COMPILER_FAMILY} MATCHES "avr" )
 
-	set( OUTPUT_SRCS
+	set ( Module_SRCS
 		output_com.c
 		avr/usb_keyboard_serial.c
 	)
@@ -23,7 +22,7 @@
 #| ARM Compiler
 elseif ( ${COMPILER_FAMILY} MATCHES "arm" )
 
-	set( OUTPUT_SRCS
+	set ( Module_SRCS
 		output_com.c
 		arm/usb_desc.c
 		arm/usb_dev.c
@@ -36,13 +35,9 @@
 
 
 ###
-# Module Specific Options
-#
-
-###
 # Compiler Family Compatibility
 #
-set( OutputModuleCompatibility
+set( ModuleCompatibility
 	arm
 	avr
 )
--- a/Output/uartOut/arm/uart_serial.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/uartOut/arm/uart_serial.c	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -19,18 +19,74 @@
  * THE SOFTWARE.
  */
 
-#include "uart_serial.h"
+// ----- Includes -----
+
+// Compiler Includes
+#include <string.h> // For memcpy
+
+// Project Includes
 #include <Lib/OutputLib.h>
 #include <Lib/Interrupts.h>
-#include <string.h> // For memcpy
+
+// Local Includes
+#include "uart_serial.h"
+
+
+
+// ----- Defines -----
+
+// UART Configuration
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug
+#define UART_BDH    UART0_BDH
+#define UART_BDL    UART0_BDL
+#define UART_C1     UART0_C1
+#define UART_C2     UART0_C2
+#define UART_C3     UART0_C3
+#define UART_C4     UART0_C4
+#define UART_CFIFO  UART0_CFIFO
+#define UART_D      UART0_D
+#define UART_PFIFO  UART0_PFIFO
+#define UART_RCFIFO UART0_RCFIFO
+#define UART_RWFIFO UART0_RWFIFO
+#define UART_S1     UART0_S1
+#define UART_S2     UART0_S2
+#define UART_SFIFO  UART0_SFIFO
+#define UART_TWFIFO UART0_TWFIFO
+
+#define SIM_SCGC4_UART  SIM_SCGC4_UART0
+#define IRQ_UART_STATUS IRQ_UART0_STATUS
+
+#elif defined(_mk20dx256vlh7_) // UART2 Debug
+#define UART_BDH    UART2_BDH
+#define UART_BDL    UART2_BDL
+#define UART_C1     UART2_C1
+#define UART_C2     UART2_C2
+#define UART_C3     UART2_C3
+#define UART_C4     UART2_C4
+#define UART_CFIFO  UART2_CFIFO
+#define UART_D      UART2_D
+#define UART_PFIFO  UART2_PFIFO
+#define UART_RCFIFO UART2_RCFIFO
+#define UART_RWFIFO UART2_RWFIFO
+#define UART_S1     UART2_S1
+#define UART_S2     UART2_S2
+#define UART_SFIFO  UART2_SFIFO
+#define UART_TWFIFO UART2_TWFIFO
+
+#define SIM_SCGC4_UART  SIM_SCGC4_UART2
+#define IRQ_UART_STATUS IRQ_UART2_STATUS
+
+#endif
+
+
 
 // ----- Variables -----
 
-#define uart0_buffer_size 128 // 128 byte buffer
-volatile uint8_t uart0_buffer_head = 0;
-volatile uint8_t uart0_buffer_tail = 0;
-volatile uint8_t uart0_buffer_items = 0;
-volatile uint8_t uart0_buffer[uart0_buffer_size];
+#define uart_buffer_size 128 // 128 byte buffer
+volatile uint8_t uart_buffer_head = 0;
+volatile uint8_t uart_buffer_tail = 0;
+volatile uint8_t uart_buffer_items = 0;
+volatile uint8_t uart_buffer[uart_buffer_size];
 
 volatile uint8_t uart_configured = 0;
 
@@ -38,21 +94,25 @@
 
 // ----- Interrupt Functions -----
 
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug
 void uart0_status_isr()
+#elif defined(_mk20dx256vlh7_) // UART2 Debug
+void uart2_status_isr()
+#endif
 {
 	cli(); // Disable Interrupts
 
 	// UART0_S1 must be read for the interrupt to be cleared
-	if ( UART0_S1 & ( UART_S1_RDRF | UART_S1_IDLE ) )
+	if ( UART_S1 & ( UART_S1_RDRF | UART_S1_IDLE ) )
 	{
-		uint8_t available = UART0_RCFIFO;
+		uint8_t available = UART_RCFIFO;
 
 		// If there was actually nothing
 		if ( available == 0 )
 		{
 			// Cleanup
-			available = UART0_D;
-			UART0_CFIFO = UART_CFIFO_RXFLUSH;
+			available = UART_D;
+			UART_CFIFO = UART_CFIFO_RXFLUSH;
 			sei();
 			return;
 		}
@@ -60,25 +120,25 @@
 		// Read UART0 into buffer until FIFO is empty
 		while ( available-- > 0 )
 		{
-			uart0_buffer[uart0_buffer_tail++] = UART0_D;
-			uart0_buffer_items++;
+			uart_buffer[uart_buffer_tail++] = UART_D;
+			uart_buffer_items++;
 
 			// Wrap-around of tail pointer
-			if ( uart0_buffer_tail >= uart0_buffer_size )
+			if ( uart_buffer_tail >= uart_buffer_size )
 			{
-				uart0_buffer_tail = 0;
+				uart_buffer_tail = 0;
 			}
 
 			// Make sure the head pointer also moves if circular buffer is overwritten
-			if ( uart0_buffer_head == uart0_buffer_tail )
+			if ( uart_buffer_head == uart_buffer_tail )
 			{
-				uart0_buffer_head++;
+				uart_buffer_head++;
 			}
 
 			// Wrap-around of head pointer
-			if ( uart0_buffer_head >= uart0_buffer_size )
+			if ( uart_buffer_head >= uart_buffer_size )
 			{
-				uart0_buffer_head = 0;
+				uart_buffer_head = 0;
 			}
 		}
 	}
@@ -96,14 +156,20 @@
 	uart_configured = 0;
 
 	// Setup the the UART interface for keyboard data input
-	SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
+	SIM_SCGC4 |= SIM_SCGC4_UART; // Disable clock gating
 
-// MCHCK
+// MCHCK / Kiibohd-dfu
 #if defined(_mk20dx128vlf5_)
 	// Pin Setup for UART0
 	PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin
 	PORTA_PCR2 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(2); // TX Pin
 
+// Kiibohd-dfu
+#elif defined(_mk20dx256vlh7_)
+	// Pin Setup for UART2
+	PORTD_PCR2 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(3); // RX Pin
+	PORTD_PCR3 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
+
 // Teensy
 #else
 	// Pin Setup for UART0
@@ -111,44 +177,66 @@
 	PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin
 #endif
 
+
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug
 	// Setup baud rate - 115200 Baud
 	// 48 MHz / ( 16 * Baud ) = BDH/L
 	// Baud: 115200 -> 48 MHz / ( 16 * 115200 ) = 26.0416667
 	// Thus baud setting = 26
 	// NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
 	uint16_t baud = 26; // Max setting of 8191
-	UART0_BDH = (uint8_t)(baud >> 8);
-	UART0_BDL = (uint8_t)baud;
-	UART0_C4 = 0x02;
+	UART_BDH = (uint8_t)(baud >> 8);
+	UART_BDL = (uint8_t)baud;
+	UART_C4 = 0x02;
+
+#elif defined(_mk20dx256vlh7_) // UART2 Debug
+	// Setup baud rate - 115200 Baud
+	// Uses Bus Clock
+	// 24 MHz / ( 16 * Baud ) = BDH/L
+	// Baud: 115200 -> 24 MHz / ( 16 * 115200 ) = 13.021
+	// Thus baud setting = 13
+	// NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet
+	uint16_t baud = 13; // Max setting of 8191
+	UART_BDH = (uint8_t)(baud >> 8);
+	UART_BDL = (uint8_t)baud;
+	UART_C4 = 0x01;
+
+#endif
 
 	// 8 bit, No Parity, Idle Character bit after stop
-	UART0_C1 = UART_C1_ILT;
+	UART_C1 = UART_C1_ILT;
 
 	// Interrupt notification watermarks
-	UART0_TWFIFO = 2;
-	UART0_RWFIFO = 4;
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug
+	UART_TWFIFO = 2;
+	UART_RWFIFO = 4;
+#elif defined(_mk20dx256vlh7_) // UART2 Debug
+	// UART2 has a single byte FIFO
+	UART_TWFIFO = 1;
+	UART_RWFIFO = 1;
+#endif
 
-	// TX FIFO Disabled, TX FIFO Size 1 (Max 8 datawords), RX FIFO Enabled, RX FIFO Size 1 (Max 8 datawords)
+	// TX FIFO Enabled, TX FIFO Size 1 (Max 8 datawords), RX FIFO Enabled, RX FIFO Size 1 (Max 8 datawords)
 	// TX/RX FIFO Size:
 	//  0x0 - 1 dataword
 	//  0x1 - 4 dataword
 	//  0x2 - 8 dataword
-	UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
+	UART_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE;
 
 	// Reciever Inversion Disabled, LSBF
 	// UART_S2_RXINV UART_S2_MSBF
-	UART0_S2 |= 0x00;
+	UART_S2 |= 0x00;
 
 	// Transmit Inversion Disabled
 	// UART_C3_TXINV
-	UART0_C3 |= 0x00;
+	UART_C3 |= 0x00;
 
 	// TX Enabled, RX Enabled, RX Interrupt Enabled, Generate idles
 	// UART_C2_TE UART_C2_RE UART_C2_RIE UART_C2_ILIE
-	UART0_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE;
+	UART_C2 = UART_C2_TE | UART_C2_RE | UART_C2_RIE | UART_C2_ILIE;
 
 	// Add interrupt to the vector table
-	NVIC_ENABLE_IRQ( IRQ_UART0_STATUS );
+	NVIC_ENABLE_IRQ( IRQ_UART_STATUS );
 
 	// UART is now ready to use
 	uart_configured = 1;
@@ -164,15 +252,15 @@
 	unsigned int value = -1;
 
 	// Check to see if the FIFO has characters
-	if ( uart0_buffer_items > 0 )
+	if ( uart_buffer_items > 0 )
 	{
-		value = uart0_buffer[uart0_buffer_head++];
-		uart0_buffer_items--;
+		value = uart_buffer[uart_buffer_head++];
+		uart_buffer_items--;
 
 		// Wrap-around of head pointer
-		if ( uart0_buffer_head >= uart0_buffer_size )
+		if ( uart_buffer_head >= uart_buffer_size )
 		{
-			uart0_buffer_head = 0;
+			uart_buffer_head = 0;
 		}
 	}
 
@@ -183,16 +271,16 @@
 // Number of bytes available in the receive buffer
 int uart_serial_available()
 {
-	return uart0_buffer_items;
+	return uart_buffer_items;
 }
 
 
 // Discard any buffered input
 void uart_serial_flush_input()
 {
-	uart0_buffer_head = 0;
-	uart0_buffer_tail = 0;
-	uart0_buffer_items = 0;
+	uart_buffer_head = 0;
+	uart_buffer_tail = 0;
+	uart_buffer_items = 0;
 }
 
 
@@ -202,8 +290,8 @@
 	if ( !uart_configured )
 		return -1;
 
-	while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
-	UART0_D = c;
+	while ( !( UART_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
+	UART_D = c;
 
 	return 0;
 }
@@ -220,8 +308,8 @@
 	// While buffer is not empty and transmit buffer is
 	while ( position < size )
 	{
-		while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
-		UART0_D = data[position++];
+		while ( !( UART_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
+		UART_D = data[position++];
 	}
 
 	return 0;
@@ -231,7 +319,7 @@
 void uart_serial_flush_output()
 {
 	// Delay until buffer has been sent
-	while ( !( UART0_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
+	while ( !( UART_SFIFO & UART_SFIFO_TXEMPT ) ); // Wait till there is room to send
 }
 
 
--- a/Output/uartOut/output_com.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/uartOut/output_com.c	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -32,7 +32,7 @@
 
 // USB Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 #include "arm/uart_serial.h"
 #endif
 
@@ -107,6 +107,11 @@
 // count until idle timeout
          uint8_t  USBKeys_Idle_Count = 0;
 
+// Indicates whether the Output module is fully functional
+// 0 - Not fully functional, 1 - Fully functional
+// 0 is often used to show that a USB cable is not plugged in (but has power)
+         uint8_t  Output_Available = 0;
+
 
 
 // ----- Capabilities -----
@@ -180,7 +185,7 @@
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 	uint16_t count = 0;
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 	uint32_t count = 0;
 #endif
 	// Count characters until NULL character, then send the amount counted
@@ -195,7 +200,7 @@
 inline void Output_softReset()
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 	SOFTWARE_RESET();
 #endif
 }
--- a/Output/uartOut/output_com.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/uartOut/output_com.h	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -76,6 +76,8 @@
 
 extern USBKeyChangeState USBKeys_Changed;
 
+extern          uint8_t  Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
 
 
 // ----- Capabilities -----
--- a/Output/uartOut/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/uartOut/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller UART Output Module |###
 #
-# 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
 #
@@ -11,11 +11,10 @@
 # Module C files
 #
 
-
 #| AVR Compiler
 if ( ${COMPILER_FAMILY} MATCHES "avr" )
 
-	set( OUTPUT_SRCS
+	set ( Module_SRCS
 		output_com.c
 		avr/uart_serial.c
 	)
@@ -23,7 +22,7 @@
 #| ARM Compiler
 elseif ( ${COMPILER_FAMILY} MATCHES "arm" )
 
-	set( OUTPUT_SRCS
+	set ( Module_SRCS
 		output_com.c
 		arm/uart_serial.c
 	)
@@ -32,13 +31,9 @@
 
 
 ###
-# Module Specific Options
-#
-
-###
 # Compiler Family Compatibility
 #
-set( OutputModuleCompatibility
+set( ModuleCompatibility
 	arm
 #	avr # TODO
 )
--- a/Output/usbMuxUart/output_com.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/usbMuxUart/output_com.c	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -32,11 +32,11 @@
 
 // USB Includes
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
-#include "../uartOut/arm/uart_serial.h"
-#include "../pjrcUSB/arm/usb_dev.h"
-#include "../pjrcUSB/arm/usb_keyboard.h"
-#include "../pjrcUSB/arm/usb_serial.h"
+#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>
 #endif
 
 // Local Includes
@@ -130,6 +130,11 @@
 // count until idle timeout
          uint8_t  USBKeys_Idle_Count = 0;
 
+// Indicates whether the Output module is fully functional
+// 0 - Not fully functional, 1 - Fully functional
+// 0 is often used to show that a USB cable is not plugged in (but has power)
+         uint8_t  Output_Available = 0;
+
 
 
 // ----- Capabilities -----
@@ -468,7 +473,7 @@
 {
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 	uint16_t count = 0;
-#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 	uint32_t count = 0;
 #endif
 	// Count characters until NULL character, then send the amount counted
--- a/Output/usbMuxUart/output_com.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/usbMuxUart/output_com.h	Thu Feb 12 19:37:19 2015 -0800
@@ -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
@@ -78,6 +78,8 @@
 
 extern USBKeyChangeState USBKeys_Changed;
 
+extern          uint8_t  Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
 
 
 // ----- Capabilities -----
--- a/Output/usbMuxUart/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Output/usbMuxUart/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Muxed UART and USB Output Module |###
 #
-# 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
 #
@@ -8,43 +8,26 @@
 
 
 ###
+# Required Submodules
+#
+
+AddModule ( Output pjrcUSB )
+AddModule ( Output uartOut )
+
+
+###
 # Module C files
 #
 
-
-#| AVR Compiler
-if ( ${COMPILER_FAMILY} MATCHES "avr" )
-
-	set( OUTPUT_SRCS
-	)
-
-#| ARM Compiler
-elseif ( ${COMPILER_FAMILY} MATCHES "arm" )
-
-	set( OUTPUT_SRCS
-		output_com.c
-		../pjrcUSB/arm/usb_desc.c
-		../pjrcUSB/arm/usb_dev.c
-		../pjrcUSB/arm/usb_keyboard.c
-		../pjrcUSB/arm/usb_mem.c
-		../pjrcUSB/arm/usb_serial.c
-		../uartOut/arm/uart_serial.c
-	)
-
-endif ()
-
-
-
-###
-# Module Specific Options
-#
-
+set( Module_SRCS
+	output_com.c
+)
 
 
 ###
 # Compiler Family Compatibility
 #
-set( OutputModuleCompatibility
+set( ModuleCompatibility
 	arm
 #	avr # TODO
 )
--- a/README	Mon Dec 22 20:27:33 2014 -0600
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,489 +0,0 @@
-The Kiibohd Controller
-----------------------
-
-This README is a bit long, just look at the sections you are interested in.
-Linux is the ideal build environment (preferably recent'ish).
-
-
-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 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).
-
-Building on Windows should also be fine for 99% of users, but takes a bunch of work to setup (because Windows is a crappy dev environment).
-Cygwin is currently required along with some non-Cygwin compilers and utilities (because they are not available for Cygwin).
-The dfu Bootloader will not build because of a Make 3.81+ bug/feature that removed support for non-Unix (Windows) filenames as dependencies of targets.
-If you replace the version of Make in Cygwin it should work (e.g. http://stackoverflow.com/questions/601516/cygwin-make-error-target-pattern-contains-no).
-However, make sure that the flash size is no larger than 4096 Bytes or the bootloader will not work.
-
-
-Please give authors credit for modules used if you use in a distributed product :D
-
-
-
-----------------------
-Dependencies
-----------------------
-
-Below listed are the Arch Linux pacman names, AUR packages may be required.
-
-These depend a bit on which targets you are trying to build, but the general one:
-- cmake (2.8 and higher)
-- git
-- ctags (recommended, not required)
-- python3
-- libusb1.0 (and -devel)
-- make
-
-
-AVR Specific (Teensy 1.0/++,2.0/++) (try to use something recent, suggested versions below)
-- avr-gcc      (~4.8.0)
-- avr-binutils (~2.23.2)
-- avr-libc     (~1.8.0)
-
-
-ARM Specific (Teensy 3.0/3.1) (Sourcery CodeBench Lite for ARM EABI
-(http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/)
-- arm-none-eabi
-OR
-- arm-none-eabi-gcc
-- arm-none-eaby-binutils
-(I've actually had some issues with Sourcery CodeBench on Linux, so I often just use these)
-
-
-
-----------------------
-Windows Setup
-----------------------
-
-Compiling on Windows does work, just it's a bunch more work.
-
-First make sure Cygwin is installed - http://www.cygwin.com/ - 32bit or 64bit is fine. Make sure the following are installed:
-- make
-- git (needed for some compilation info)
-- cmake
-- gcc-core
-- gcc-g++
-- libusb1.0
-- libusb1.0-devel
-- python3
-- ctags (recommended, not required)
-
-Please note, I use cygwin term exclusively for any command line options. Unless mentioned otherwise use it.
-Do NOT use CMD or Powershell.
-
-Also install the Windows version of CMake (3+ is ideal) - http://cmake.org/cmake/resources/software.html
-This is in addition to the Cygwin version. This is an easier alternative to installing another C compiler.
-Add the following line to your .bashrc, making sure the CMake path is correct:
-  echo "alias wincmake=\"PATH='/cygdrive/c/Program Files (x86)/CMake'/bin:'${PATH}' cmake -G 'Unix Makefiles'\"" >> ~/.bashrc
-
-Install the PJRC Virtual Serial Port Driver:
-(http://pjrc.com/teensy/serial_install.exe)
-
-Next, install the compiler(s) you want.
-
-
-
- ---------
-| AVR GCC |
- ---------
-
-You just need the Atmel AVR 8-bit Toolchain. The latest should be fine, as of writing it was 3.4.3.
-
-http://www.atmel.com/tools/atmelavrtoolchainforwindows.aspx
-(Atmel AVR 8-bit Toolchain 3.4.3 - Windows)
-
-Extract the files to a directory, say C:\avr8-gnu-toolchain. Then copy all the folders in that directory to the Cygwin /usr/local directory.
-Mine is C:\cygwin64\usr\local.
-(You can also just setup the paths, but this is faster/simpler. Might screw up your Cygwin though).
-
-
- ----------
-| ARM EABI |
- ----------
-
-Download the latest version of Mentor Graphics Sourcery CodeBench ARM EABI.
-
-http://www.mentor.com/embedded-software/sourcery-tools/sourcery-codebench/editions/lite-edition/
-
-Look for "Download the EABI Release".
-Enter your info to get the download link.
-Select the most recent download.
-Then download the "IA32 Windows Installer".
-
-Then copy all the folders/files installed (e.g. C:\Users\Haata\MentorGraphics\Sourcery_CodeBench_Lite_for_ARM_EABI\) to Cygwin /usr/local directory.
-Mine is C:\cygwin64\usr\local.
-Or, you can setup paths using the installer (you have to be more careful though).
-
-
-
-----------------------
-Selecting Microcontroller
-----------------------
-
-This is where you select the chip you want to compile for.
-The build system will automatically select the compiler needed to compile for your chip.
-
-Open up CMakeLists.txt in your favourite text editor.
-You are looking for:
-
-	###
-	# Chip Selection
-	#
-
-	#| You _MUST_ set this to match the microcontroller you are trying to compile for
-	#| You _MUST_ clean the build directory if you change this value
-	#|
-	set( CHIP
-	#	"at90usb162"       # Teensy   1.0 (avr)
-	#	"atmega32u4"       # Teensy   2.0 (avr)
-	#	"at90usb646"       # Teensy++ 1.0 (avr)
-		"at90usb1286"      # Teensy++ 2.0 (avr)
-	#	"mk20dx128"        # Teensy   3.0 (arm)
-	#	"mk20dx256"        # Teensy   3.1 (arm)
-	)
-
-Just uncomment the chip you want, and comment out the old one.
-
-NOTE: If you change this option, you will *need* to delete the build directory that is created in the Building sections below.
-
-
-
-----------------------
-Selecting Modules
-----------------------
-
-WARNING: Not all modules are compatible, and some modules may have dependencies on other modules.
-
-This is where the options start getting interesting.
-The Kiibohd Controller is designed around a set of 4 types of modules that correspond to different functionality:
-
-- Scan Module
-- Macro Module
-- Output Module
-- Debug Module
-
-The Scan Module is where the most interesting stuff happens. These modules take in "keypress data".
-A converter Scan Module will interpret a protocol into key press/releases.
-A matrix Scan Module may inherit from the matrix module to scan keypress from a matrix
-This module just has to give press/release codes, but does have some callback control to other modules depending on the lifecycle for press/release codes (this can be very complicated depending on the protocol).
-Each Scan Module has it's own default keymap/modifier map. (TODO recommend keymap changing in the Macro Module).
-
-Some scan modules have very specialized hardware requirements, each module directory should have at least a link to the needed parts and/or schematics (TODO!).
-
-
-The Macro Module takes care of the mapping of the key press/release code into an Output (USB) scan code.
-Any layering, macros, keypress intelligence/reaction is done here.
-
-
-The Output Module is the module dealing with output from the microcontroller. Currently USB is the only output protocol.
-Different USB output implementations are available, pjrc being the safest/least featureful one.
-Debug capabilities may depend on the module selected.
-
-
-The Debug Module enables various things like the Teensy LED on errors, debug terminal output.
-(TODO get true UART working in avr, not just arm)
-
-
-
-Open up CMakeLists.txt in your favourite text editor.
-Look for:
-
-	###
-	# Project Modules
-	#
-
-	#| Note: This is the only section you probably want to modify
-	#| Each module is defined by it's own folder (e.g. Scan/Matrix represents the "Matrix" module)
-	#| All of the modules must be specified, as they generate the sources list of files to compile
-	#| Any modifications to this file will cause a complete rebuild of the project
-
-	#| Please look at the {Scan,Macro,Output,Debug}/module.txt for information on the modules and how to create new ones
-
-	##| Deals with acquiring the keypress information and turning it into a key index
-	set(  ScanModule  "avr-capsense" )
-
-	##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code
-	set( MacroModule  "buffer"  )
-
-	##| Sends the current list of usb key codes through USB HID
-	set(   OutputModule  "pjrc"   )
-
-	##| Debugging source to use, each module has it's own set of defines that it sets
-	set( DebugModule  "full"   )
-
-
-Look at each module individually for it's requirements. There is chip/architecture dependency checking but some permutations of modules may not be tested/compile.
-
-
-There are also CMake options for temporarily selecting modules. But it's easier to just edit the file.
-e.g. cmake -DScanModuleOverride=<module name>
-
-
-
-----------------------
-Linux Building
-----------------------
-
-From this directory.
-mkdir build
-cd build
-cmake ..
-make
-
-
-Example output:
-
-	[master]: cmake ..                 [...sy/avr-capsense-haata/build](hyatt@901Mas:pts/4)
-	-- Compiler Family:
-	avr
-	-- MCU Selected:
-	at90usb1286
-	-- Detected Scan Module Source Files:
-	Scan/avr-capsense/scan_loop.c
-	-- Detected Macro Module Source Files:
-	Macro/buffer/macro.c
-	-- Detected Output Module Source Files:
-	Output/pjrc/usb_com.c;Output/pjrc/avr/usb_keyboard_debug.c
-	-- Detected Debug Module Source Files:
-	Debug/full/../led/led.c;Debug/full/../print/print.c
-	-- Configuring done
-	-- Generating done
-	-- Build files have been written to: /home/hyatt/Source/Teensy/avr-capsense-haata/build
-	[master]: make                     [...sy/avr-capsense-haata/build](hyatt@901Mas:pts/4)
-	Scanning dependencies of target kiibohd.elf
-	[ 12%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
-	[ 25%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/avr-capsense/scan_loop.c.o
-	[ 37%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/buffer/macro.c.o
-	[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/usb_com.c.o
-	[ 62%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrc/avr/usb_keyboard_debug.c.o
-	[ 75%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o
-	[ 87%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o
-	Linking C executable kiibohd.elf
-	Creating load file for Flash:  kiibohd.hex
-	Creating Extended Listing:     kiibohd.lss
-	Creating Symbol Table:         kiibohd.sym
-	[ 87%] Built target kiibohd.elf
-	Scanning dependencies of target SizeAfter
-	[100%] Size after generation:
-	   text    data     bss     dec     hex filename
-	      0    6112       0    6112    17e0 kiibohd.hex
-	   5792     320     852    6964    1b34 kiibohd.elf
-	[100%] Built target SizeAfter
-
-
-
-----------------------
-Linux Loading Firmware
-----------------------
-
-First place the keyboard into re-flash mode.
-This can be done either by pressing the re-flash button on the PCB/Teensy.
-Or by entering the Kiibohd Virtual Serial Port and using the 'reload' command.
-
-The 'load' script that is created during the build can load the firmware over USB.
-Either run it with sudo, or install the 98-kiibohd.rules to /etc/udev/rules.d
- and run: udevadm control --reload-rules
-
-
-To load the newly built firmware:
-./load
-
-
-
-----------------------
-Linux Building Bootloader
-----------------------
-
-*NOTE* Does not apply to Teensy based builds.
-
-From this directory.
-cd Bootloader
-mkdir build
-cd build
-cmake ..
-make
-
-Example output:
-TODO
-
-
-
-----------------------
-Linux Loading Bootloader
-----------------------
-
-*NOTE* Does not apply to Teensy based builds.
-
-It's recommended to use an SWD-type flasher like a Bus Pirate.
-TODO
-(Guidelines here https://github.com/mchck/mchck/wiki/Getting-Started)
-
-
-
-----------------------
-Windows Building
-----------------------
-
-From this directory.
-mkdir build
-cd build
-wincmake ..
-make
-
-
-Example output:
-
-	$ cmake -G "Unix Makefiles" ..
-	-- Compiler Family:
-	avr
-	-- MCU Selected:
-	atmega32u4
-	-- CPU Selected:
-	megaAVR
-	-- Detected Scan Module Source Files:
-	Scan/SKM67001/../matrix/matrix_scan.c;Scan/SKM67001/../matrix/scan_loop.c
-	-- Detected Macro Module Source Files:
-	Macro/PartialMap/macro.c
-	-- Detected Output Module Source Files:
-	Output/pjrcUSB/output_com.c;Output/pjrcUSB/avr/usb_keyboard_serial.c
-	-- Detected Debug Module Source Files:
-	Debug/full/../cli/cli.c;Debug/full/../led/led.c;Debug/full/../print/print.c
-	-- Found Git: C:/cygwin64/bin/git.exe (found version "1.7.9")
-	-- Configuring done
-	-- Generating done
-	-- Build files have been written to: C:/cygwin64/home/jacob.alexander/src/capsense-beta/build
-
-	jacob.alexander@JALEXANDER2-LT ~/src/capsense-beta/build
-	$ make
-	Scanning dependencies of target kiibohd.elf
-	[ 10%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.obj
-	[ 20%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/matrix/matrix_scan.c.obj
-	[ 30%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/matrix/scan_loop.c.obj
-	[ 40%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/macro.c.obj
-	[ 50%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/output_com.c.obj
-	[ 60%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/avr/usb_keyboard_serial.c.obj
-	[ 70%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/cli/cli.c.obj
-	[ 80%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.obj
-	[ 90%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.obj
-	Linking C executable kiibohd.elf
-	Creating load file for Flash:  kiibohd.hex
-	Creating Extended Listing:     kiibohd.lss
-	Creating Symbol Table:         kiibohd.sym
-	[ 90%] Built target kiibohd.elf
-	Scanning dependencies of target SizeAfter
-	[100%] Size after generation
-		Flash Usage: data (hex)
-		  RAM Usage: data (elf)
-	   text    data     bss     dec     hex filename
-	      0    9738       0    9738    260a kiibohd.hex
-	   7982    1756     264   10002    2712 kiibohd.elf
-	[100%] Built target SizeAfter
-
-
-
-----------------------
-Windows Loading Firmware
-----------------------
-
-First place the keyboard into re-flash mode.
-This can be done either by pressing the re-flash button on the PCB/Teensy.
-Or by entering the Kiibohd Virtual Serial Interface and using the 'reload' command.
-
-The 'load' script that is created during the build can load the firmware over USB.
-
-To load the newly built firmware:
-./load
-
-Be patient the couple of times, Windows is slow at installing drivers...
-
-
-
-----------------------
-Mac OS X Building
-----------------------
-
-From this directory.
-mkdir build
-cd build
-cmake ..
-make
-
-
-Example output:
-TODO
-
-
-
-----------------------
-Mac OS X Loading Firmware
-----------------------
-
-First place the keyboard into re-flash mode.
-This can be done either by pressing the re-flash button on the PCB/Teensy.
-Or by entering the Kiibohd Virtual Serial Port and using the 'reload' command.
-
-The 'load' script that is created during the build can load the firmware over USB.
-
-
-To load the newly built firmware:
-./load
-
-
-
-----------------------
-Virtual Serial Port - CLI
-----------------------
-
-Rather than use a special program that can interpret Raw HID, this controller exposes a USB Serial CDC endpoint.
-This allows for you to use a generic serial terminal to debug/control the keyboard firmware (e.g. Tera Term, minicom, screen)
-
-
- -------
-| Linux |
- -------
-
-I generally use screen.
-You will need sudo/root priviledges if you haven't installed the 98-kiibohd.rules file to /etc/udev/rules.d
-
-screen /dev/ttyACM0
-(Might be ACM1, ACM2, etc.)
-
-
- ---------
-| Windows |
- ---------
-
-Make sure the Teensy Virtual Serial Port driver is installed.
-If possible use screen (as part of Cygwin).
-Check which COM port the virtual serial port has been assigned to:
-   Device Manager->Ports (COM & LPT)->Teensy USB Serial
-   In brackets it will say which COM port (e.g. COM3)
-
-
-putty works well when using DTR/DSR or RTS/CTS flow control.
-Connection type: Serial
-Serial line:     <Your COM port, e.g. COM3>
-Speed:           (doesn't matter, it's auto-negotiated)
-
-Under Category->Connections->Serial
-Flow control:    DTR/DSR
-
-If stuff is hard to read (you have a dumb colour scheme):
-Category->Window->Colours->Use system colur
-That seems to make text at least readable (I use a custom colour scheme that makes each colour easy to see -HaaTa).
-
-
-Unfortunately, screen for Cygwin seems to be broken for serial ports, but you can try it...
-screen /dev/ttyS2
-(Might be a different file, ttyS0, ttyACM0, ttyUSB0, etc.)
-
-Gnu screen doesn't seem to echo all the characters (it works though).
-I believe it's a problem with stty, but I don't know how to fix it...
-
-
- ----------
-| Mac OS X |
- ----------
-
-I recommend screen (can be installed via Macports).
-screen /dev/tty.<usb something>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.markdown	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,643 @@
+The Kiibohd Controller
+======================
+
+This README is a bit long, just look at the sections you are interested in.
+You only need to install avr-gcc if you want to build for the Teensy 2.0/2.0++.
+Everything else needs an arm-none-eabi-gcc compiler (e.g. Infinity keyboard,
+Teensy 3.0/3.1, McHCK).
+
+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
+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).
+
+Building on Windows should also be fine for 99% of users, but takes a bunch of
+work to setup (because Windows is a crappy dev environment).  Cygwin is
+currently required along with some non-Cygwin compilers and utilities (because
+they are not available for Cygwin).  The dfu Bootloader will not build because
+of a Make 3.81+ bug/feature that removed support for non-Unix (Windows)
+filenames as dependencies of targets.  If you [replace the version of Make in
+Cygwin](http://stackoverflow.com/questions/601516/cygwin-make-error-target-pattern-contains-no)
+it should work.  However, make sure that the flash size is no larger than 4096
+Bytes or the bootloader will not work. Things will likely break if there are
+**SPACES IN YOUR PATHS**. I install cygwin to `C:\cygwin64`.  If you are brave
+and have programming knowledge, I will accept patches to fix any issues
+regarding spaces in paths.
+
+Please give authors credit for modules used if you use in a distributed
+product :D
+
+
+General Dependencies
+--------------------
+
+Below listed are the Arch Linux pacman names, AUR packages may be required.
+
+These depend a bit on which targets you are trying to build, but the general
+one:
+
+- cmake (2.8 and higher)
+- git
+- ctags (recommended, not required)
+- python3
+- libusb1.0 (and -devel)
+- make
+
+AVR Specific (Teensy 1.0/++,2.0/++) (try to use something recent, suggested
+versions below)
+
+- avr-gcc      (~4.8.0)
+- avr-binutils (~2.23.2)
+- avr-libc     (~1.8.0)
+
+ARM Specific (Teensy 3.0/3.1, Infinity Keyboard, McHCK)
+
+- Arch Linux / Mac Ports
+    - arm-none-eabi-gcc
+    - arm-none-eaby-binutils
+
+- Windows (https://launchpad.net/gcc-arm-embedded/+download)
+    - gcc-arm-none-eabi (win32.zip)
+
+
+Windows Setup
+-------------
+
+Compiling on Windows does work, just it's a bunch more work.
+
+First make sure Cygwin is installed - http://www.cygwin.com/ - 32bit or 64bit
+is fine. Make sure the following are installed:
+
+- make
+- git (needed for some compilation info)
+- cmake
+- gcc-core
+- gcc-g++
+- libusb1.0
+- libusb1.0-devel
+- python3
+- ctags (recommended, not required)
+
+Please note, I use cygwin term exclusively for any command line options.
+Unless mentioned otherwise, use it.  Do NOT use CMD or Powershell.
+
+Also install the [Windows version of CMake](http://cmake.org/cmake/resources/software.html)
+(3+ is ideal) - Select "Do not add CMake to system PATH".  This is in addition
+to the Cygwin version. This is an easier alternative to installing another C
+compiler.  Add the following line to your .bashrc, making sure the CMake path
+is correct:
+
+    echo "alias wincmake=\"PATH='/cygdrive/c/Program Files (x86)/CMake'/bin:'${PATH}' cmake -G 'Unix Makefiles'\"" >> ~/.bashrc
+
+Install the [PJRC Virtual Serial Port Driver](http://pjrc.com/teensy/serial_install.exe).
+
+Next, install the compiler(s) you want.
+
+
+### AVR GCC
+
+You just need the
+[Atmel AVR 8-bit Toolchain](http://www.atmel.com/tools/atmelavrtoolchainforwindows.aspx).
+The latest should be fine, as of writing it was 3.4.3.
+
+Extract the files to a directory, say `C:\avr8-gnu-toolchain`. Then copy all
+the folders in that directory to the Cygwin `/usr/local` directory.  Mine is
+`C:\cygwin64\usr\local`. (You can also just setup the paths, but this is
+faster/simpler. Might screw up your Cygwin though).
+
+
+### ARM EABI
+
+Download the latest
+[GNU Tools for Embedded Processors
+gcc-arm-none-eabi](https://launchpad.net/gcc-arm-embedded/+download).
+
+Download `gcc-arm-none-eabi*win32.zip`.
+
+Then extract all the folders/files in the zip to the Cygwin `/usr/local`
+directory.  Mine is `C:\cygwin64\usr\local`.  Or, you can setup paths using
+the installer (you have to be more careful, avoid spaces in paths).
+
+
+CMake Info
+----------
+
+One of the big benefits of using CMake is the ability to build multiple
+configurations (for different microcontrollers) at the same time.  The
+following sections explain in detail what each CMakeLists.txt configuration
+option does and what you can change it to.  However, it is possible to
+configure each of these options using the `-D` command line flag.
+
+For example, to build the Infinity Keyboard default configuration:
+
+```bash
+$ mkdir build_infinity
+$ cd build_infinity
+$ cmake -DCHIP=mk20dx128vlf5 -DScanModule=MD1 -DMacroModule=PartialMap \
+        -DOutputModule=pjrcUSB -DDebugModule=full -DBaseMap=defaultMap \
+        -DDefaultMap="md1Overlay stdFuncMap" -DPartialMaps="hhkbpro2" \
+        ..
+$ make
+```
+
+CMake defaults to the values specified in CMakeLists.txt if not overridden via
+the command line.
+
+> NOTE: On Windows, you will have to use "wincmake" instead of "cmake".
+
+
+Selecting Microcontroller
+-------------------------
+
+This is where you select the chip you want to compile for.  The build system
+will automatically select the compiler needed to compile for your chip.
+
+Open up CMakeLists.txt in your favourite text editor. You are looking for:
+
+```cmake
+###
+# Chip Selection
+#
+
+#| You _MUST_ set this to match the microcontroller you are trying to compile for
+#| You _MUST_ clean the build directory if you change this value
+#|
+set( CHIP
+#	"at90usb162"       # Teensy   1.0 (avr)
+#	"atmega32u4"       # Teensy   2.0 (avr)
+#	"at90usb646"       # Teensy++ 1.0 (avr)
+#	"at90usb1286"      # Teensy++ 2.0 (avr)
+#	"mk20dx128"        # Teensy   3.0 (arm)
+    "mk20dx128vlf5"    # McHCK    mk20dx128vlf5
+#	"mk20dx256"        # Teensy   3.1 (arm)
+    CACHE STRING "Microcontroller Chip" )
+```
+
+Just uncomment the chip you want, and comment out the old one.
+
+> NOTE: If you change this option, you will *need* to delete the build
+> directory that is created in the Building sections below.
+
+
+Selecting Modules
+-----------------
+
+> WARNING: Not all modules are compatible, and some modules may have
+> dependencies on other modules.
+
+This is where the options start getting interesting.  The Kiibohd Controller
+is designed around a set of 4 types of modules that correspond to different
+functionality:
+
+- Scan Module
+- Macro Module
+- Output Module
+- Debug Module
+
+The Scan Module is where the most interesting stuff happens. These modules
+take in "keypress data".  A converter Scan Module will interpret a protocol
+into key press/releases.  A matrix Scan Module may inherit from the matrix
+module to scan keypress from a matrix This module just has to give
+press/release codes, but does have some callback control to other modules
+depending on the lifecycle for press/release codes (this can be very
+complicated depending on the protocol).  Each Scan Module has it's own default
+keymap/modifier map. (TODO recommend keymap changing in the Macro Module).
+
+Some scan modules have very specialized hardware requirements, each module
+directory should have at least a link to the needed parts and/or schematics
+(TODO!).
+
+The Macro Module takes care of the mapping of the key press/release code into
+an Output (USB) scan code.  Any layering, macros, keypress
+intelligence/reaction is done here.
+
+The Output Module is the module dealing with output from the microcontroller.
+Currently USB is the only output protocol.  Different USB output
+implementations are available, pjrc being the safest/least featureful one.
+Debug capabilities may depend on the module selected.
+
+The Debug Module enables various things like the Teensy LED on errors, debug
+terminal output.  (TODO get true UART working in avr, not just arm)
+
+Open up CMakeLists.txt in your favourite text editor.  Look for:
+
+```cmake
+###
+# Project Modules
+#
+
+#| Note: This is the only section you probably want to modify
+#| Each module is defined by it's own folder (e.g. Scan/Matrix represents the "Matrix" module)
+#| All of the modules must be specified, as they generate the sources list of files to compile
+#| Any modifications to this file will cause a complete rebuild of the project
+
+#| Please look at the {Scan,Macro,Output,Debug} for information on the modules and how to create new ones
+
+##| Deals with acquiring the keypress information and turning it into a key index
+set(   ScanModule "MD1"
+    CACHE STRING "Scan Module" )
+
+##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule
+set(  MacroModule "PartialMap"
+    CACHE STRING "Macro Module" )
+
+##| Sends the current list of usb key codes through USB HID
+set( OutputModule "pjrcUSB"
+    CACHE STRING "Output Module" )
+
+##| Debugging source to use, each module has it's own set of defines that it sets
+set(  DebugModule "full"
+    CACHE STRING "Debug Module" )
+```
+
+Look at each module individually for it's requirements. There is
+chip/architecture dependency checking but some permutations of modules may not
+be tested/compile.
+
+There are also CMake options for temporarily selecting modules. But it's
+easier to just edit the file. e.g. `cmake -DScanModuleOverride=<module name>`.
+
+
+Linux Building
+--------------
+
+From this directory.
+
+```bash
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+```
+
+Example output:
+
+```
+$ cmake ..
+-- Compiler Family:
+arm
+-- Chip Selected:
+mk20dx128vlf5
+-- Chip Family:
+mk20dx
+-- CPU Selected:
+cortex-m4
+-- Compiler Source Files:
+Lib/mk20dx.c;Lib/delay.c
+-- Bootloader Type:
+dfu
+-- Detected Scan Module Source Files:
+Scan/MD1/scan_loop.c;Scan/MD1/../MatrixARM/matrix_scan.c
+-- Detected Macro Module Source Files:
+Macro/PartialMap/macro.c
+-- Detected Output Module Source Files:
+Output/pjrcUSB/output_com.c;Output/pjrcUSB/arm/usb_desc.c;Output/pjrcUSB/arm/usb_dev.c;
+Output/pjrcUSB/arm/usb_keyboard.c;Output/pjrcUSB/arm/usb_mem.c;Output/pjrcUSB/arm/usb_serial.c
+-- Detected Debug Module Source Files:
+Debug/full/../cli/cli.c;Debug/full/../led/led.c;Debug/full/../print/print.c
+-- Found Git: /usr/bin/git (found version "2.2.1")
+-- Found Ctags: /usr/bin/ctags (found version "5.8")
+-- Checking for latest kll version:
+Current branch master is up to date.
+-- Detected Layout Files:
+/home/hyatt/Source/controller/Macro/PartialMap/capabilities.kll
+/home/hyatt/Source/controller/Output/pjrcUSB/capabilities.kll
+/home/hyatt/Source/controller/Scan/MD1/defaultMap.kll
+/home/hyatt/Source/controller/kll/layouts/md1Overlay.kll
+/home/hyatt/Source/controller/kll/layouts/stdFuncMap.kll
+/home/hyatt/Source/controller/kll/layouts/hhkbpro2.kll
+-- Configuring done
+-- Generating done
+-- Build files have been written to: /home/hyatt/Source/controller/build
+[master]: make                                [~/Source/controller/build](hyatt@x230mas:pts/6)
+[  5%] Generating KLL Layout
+Scanning dependencies of target kiibohd.elf
+[ 11%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
+[ 17%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/mk20dx.c.o
+[ 23%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/delay.c.o
+[ 29%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/MD1/scan_loop.c.o
+[ 35%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/MatrixARM/matrix_scan.c.o
+[ 41%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/macro.c.o
+[ 47%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/output_com.c.o
+[ 52%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_desc.c.o
+[ 58%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_dev.c.o
+[ 64%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_keyboard.c.o
+[ 70%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_mem.c.o
+[ 76%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_serial.c.o
+[ 82%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/cli/cli.c.o
+[ 88%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.o
+[ 94%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.o
+Linking C executable kiibohd.elf
+[ 94%] Built target kiibohd.elf
+Scanning dependencies of target SizeAfter
+[100%] Chip usage for mk20dx128vlf5
+     SRAM:  32%     5384/16384      bytes
+    Flash:  18%     23384/126976    bytes
+[100%] Built target SizeAfter
+```
+
+Linux Loading Firmware
+----------------------
+
+First place the keyboard into re-flash mode.  This can be done either by
+pressing the re-flash button on the PCB/Teensy.  Or by entering the Kiibohd
+Virtual Serial Port and using the 'reload' command.
+
+The `load` script that is created during the build can load the firmware over
+USB.  Either run it with sudo, or install the `98-kiibohd.rules` to
+`/etc/udev/rules.d` and run: `udevadm control --reload-rules`.
+
+To load the newly built firmware: `./load`.
+
+
+Linux Building Bootloader
+-------------------------
+
+> NOTE: Does not apply to Teensy based builds.
+
+From this directory.
+
+```bash
+$ cd Bootloader
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+```
+
+Example output:
+
+```bash
+$ cmake ..
+-- Compiler Family:
+arm
+-- Chip Selected:
+mk20dx128vlf5
+-- Chip Family:
+mk20dx
+-- CPU Selected:
+cortex-m4
+-- Compiler Source Files:
+Lib/mk20dx.c;Lib/delay.c
+-- Bootloader Type:
+dfu
+-- Bootloader Source Files:
+main.c;dfu.c;dfu.desc.c;flash.c;kinetis.c;usb.c
+-- Found Git: /usr/bin/git (found version "2.2.1")
+-- Found Ctags: /usr/bin/ctags (found version "5.8")
+-- Configuring done
+-- Generating done
+-- Build files have been written to: /home/hyatt/Source/controller/Bootloader/build
+[master]: make                                 [~/Source/controller/Bootloader/build](hyatt@x230mas:pts/6)
+Scanning dependencies of target kiibohd_bootloader.elf
+[ 11%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/main.c.o
+[ 22%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/dfu.c.o
+[ 33%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/dfu.desc.c.o
+[ 44%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/flash.c.o
+[ 55%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/kinetis.c.o
+[ 66%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/usb.c.o
+[ 77%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/home/hyatt/Source/controller/Lib/mk20dx.c.o
+[ 88%] Building C object CMakeFiles/kiibohd_bootloader.elf.dir/home/hyatt/Source/controller/Lib/delay.c.o
+Linking C executable kiibohd_bootloader.elf
+[ 88%] Built target kiibohd_bootloader.elf
+Scanning dependencies of target SizeAfter
+[100%] Chip usage for mk20dx128vlf5
+     SRAM:  19%     3176/16384      bytes
+    Flash:  2%      3736/126976     bytes
+[100%] Built target SizeAfter
+```
+
+
+Linux Loading Bootloader
+------------------------
+
+> NOTE: Does not apply to Teensy based builds.
+
+It's recommended to use an SWD-type flasher like a Bus Pirate.  There is a
+convenience script for loading the firmware once the system is setup.
+
+```bash
+$ cd Bootloader/Scripts
+$ ./swdLoad.bash
+```
+
+The above script requires Ruby, Ruby serial port module, git, and a
+`/dev/buspirate` udev rule.
+
+Additional Notes:
+
+* https://github.com/mchck/mchck/wiki/Getting-Started (See Bus-Pirate section)
+* https://wiki.archlinux.org/index.php/Bus_pirate
+
+
+Windows Building
+----------------
+
+From this directory.
+
+```bash
+$ mkdir build
+$ cd build
+$ wincmake ..
+$ make
+```
+
+Example output:
+
+```bash
+$ wincmake ..
+-- Compiler Family:
+arm
+-- Chip Selected:
+mk20dx128vlf5
+-- Chip Family:
+mk20dx
+-- CPU Selected:
+cortex-m4
+-- Compiler Source Files:
+Lib/mk20dx.c;Lib/delay.c
+-- Bootloader Type:
+dfu
+-- Detected Scan Module Source Files:
+Scan/MD1/scan_loop.c;Scan/MD1/../MatrixARM/matrix_scan.c
+-- Detected Macro Module Source Files:
+Macro/PartialMap/macro.c
+-- Detected Output Module Source Files:
+Output/pjrcUSB/output_com.c;Output/pjrcUSB/arm/usb_desc.c;Output/pjrcUSB/arm/usb_dev.c;Output/pjrcUSB/arm/usb_keyboard.c;Output/pjrcUSB/arm/usb_mem.c;Output/pjrcUSB/arm/usb_serial.c
+-- Detected Debug Module Source Files:
+Debug/full/../cli/cli.c;Debug/full/../led/led.c;Debug/full/../print/print.c
+-- Found Git: C:/cygwin64/bin/git.exe (found version "2.1.1")
+-- Found Ctags: C:/cygwin64/bin/ctags.exe (found version "5.8")
+-- Checking for latest kll version:
+Current branch master is up to date.
+-- Detected Layout Files:
+C:/cygwin64/home/Jacob/controller/Macro/PartialMap/capabilities.kll
+C:/cygwin64/home/Jacob/controller/Output/pjrcUSB/capabilities.kll
+C:/cygwin64/home/Jacob/controller/Scan/MD1/defaultMap.kll
+C:/cygwin64/home/Jacob/controller/kll/layouts/md1Overlay.kll
+C:/cygwin64/home/Jacob/controller/kll/layouts/stdFuncMap.kll
+C:/cygwin64/home/Jacob/controller/kll/layouts/hhkbpro2.kll
+-- Configuring done
+-- Generating done
+-- Build files have been written to: C:/cygwin64/home/Jacob/controller/build
+
+$ make
+[  5%] Generating KLL Layout
+Scanning dependencies of target kiibohd.elf
+[ 11%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.obj
+[ 17%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/mk20dx.c.obj
+[ 23%] Building C object CMakeFiles/kiibohd.elf.dir/Lib/delay.c.obj
+[ 29%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/MD1/scan_loop.c.obj
+[ 35%] Building C object CMakeFiles/kiibohd.elf.dir/Scan/MatrixARM/matrix_scan.c.obj
+[ 41%] Building C object CMakeFiles/kiibohd.elf.dir/Macro/PartialMap/macro.c.obj
+[ 47%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/output_com.c.obj
+[ 52%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_desc.c.obj
+[ 58%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_dev.c.obj
+[ 64%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_keyboard.c.obj
+[ 70%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_mem.c.obj
+[ 76%] Building C object CMakeFiles/kiibohd.elf.dir/Output/pjrcUSB/arm/usb_serial.c.obj
+[ 82%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/cli/cli.c.obj
+[ 88%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/led/led.c.obj
+[ 94%] Building C object CMakeFiles/kiibohd.elf.dir/Debug/print/print.c.obj
+Linking C executable kiibohd.elf
+[ 94%] Built target kiibohd.elf
+Scanning dependencies of target SizeAfter
+[100%] Chip usage for mk20dx128vlf5
+     SRAM:  32%     5384/16384      bytes
+    Flash:  18%     23296/126976    bytes
+[100%] Built target SizeAfter
+```
+
+### NOTES:
+
+If you get the following error, you have not setup wincmake correctly:
+
+```bash
+$ make
+[  5%] Generating KLL Layout
+Scanning dependencies of target kiibohd.elf
+[ 11%] Building C object CMakeFiles/kiibohd.elf.dir/main.c.o
+../main.c:28:19: fatal error: macro.h: No such file or directory
+ #include <macro.h>
+                   ^
+compilation terminated.
+CMakeFiles/kiibohd.elf.dir/build.make:67: recipe for target 'CMakeFiles/kiibohd.elf.dir/main.c.o' failed
+make[2]: *** [CMakeFiles/kiibohd.elf.dir/main.c.o] Error 1
+CMakeFiles/Makefile2:98: recipe for target 'CMakeFiles/kiibohd.elf.dir/all' failed
+make[1]: *** [CMakeFiles/kiibohd.elf.dir/all] Error 2
+Makefile:75: recipe for target 'all' failed
+make: *** [all] Error 2
+```
+
+If you have already added the line to your `~/.bashrc` try restarting your
+cygwin shell.
+
+
+Windows Loading Firmware
+------------------------
+
+First place the keyboard into re-flash mode.  This can be done either by
+pressing the re-flash button on the PCB/Teensy.  Or by entering the Kiibohd
+Virtual Serial Interface and using the `reload` command.
+
+The `load` script that is created during the build can load the firmware over
+USB.
+
+To load the newly built firmware: `./load`
+
+Be patient the couple of times, Windows is slow at installing drivers...
+
+
+Mac OS X Building
+-----------------
+
+From this directory.
+
+```bash
+$ mkdir build
+$ cd build
+$ cmake ..
+$ make
+```
+
+Example output:
+
+> TODO
+
+
+Mac OS X Loading Firmware
+-------------------------
+
+First place the keyboard into re-flash mode.  This can be done either by
+pressing the re-flash button on the PCB/Teensy.  Or by entering the Kiibohd
+Virtual Serial Port and using the `reload` command.
+
+The `load` script that is created during the build can load the firmware over
+USB.
+
+To load the newly built firmware: `./load`.
+
+
+Virtual Serial Port - CLI
+-------------------------
+
+Rather than use a special program that can interpret Raw HID, this controller exposes a USB Serial CDC endpoint.
+This allows for you to use a generic serial terminal to debug/control the keyboard firmware (e.g. Tera Term, minicom, screen)
+
+
+### Linux
+
+I generally use screen.  You will need sudo/root priviledges if you haven't
+installed the `98-kiibohd.rules` file to `/etc/udev/rules.d`.
+
+```
+$ screen /dev/ttyACM0
+# (Might be ACM1, ACM2, etc.)
+```
+
+### Windows
+
+Make sure the Teensy Virtual Serial Port driver is installed.  If possible use
+screen (as part of Cygwin).  Check which COM port the virtual serial port has
+been assigned to: `Device Manager->Ports (COM & LPT)->Teensy USB Serial`. In
+brackets it will say which COM port (e.g. COM3)
+
+putty works well when using DTR/DSR or RTS/CTS flow control.
+
+| Setting         | Value                                 |
+| --------------- | ------------------------------------- |
+| Connection type | Serial                                |
+| Serial line     | Your COM port, e.g. COM3              |
+| Speed           | doesn't matter, it's auto-negotiated  |
+
+Under `Category->Connections->Serial`: `Flow control: DTR/DSR`.
+
+If stuff is hard to read (you have a dumb colour scheme):
+`Category->Window->Colours->Use system color`.  That seems to make text at
+least readable 
+
+> I use a custom colour scheme that makes each colour easy to see.
+> -HaaTa.
+
+Unfortunately, screen for Cygwin seems to be broken for serial ports, but you
+can try it...
+
+```bash
+$ screen /dev/ttyS2
+# Might be a different file, ttyS0, ttyACM0, ttyUSB0, etc.
+```
+
+Gnu screen doesn't seem to echo all the characters (it works though).
+I believe it's a problem with stty, but I don't know how to fix it...
+
+### Mac OS X
+
+I recommend screen (can be installed via Macports).
+
+```bash
+$ screen /dev/tty.<usb something>
+```
--- a/Scan/ADCTest/analog.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/ADCTest/analog.c	Thu Feb 12 19:37:19 2015 -0800
@@ -62,28 +62,28 @@
 	if (analog_config_bits == 8) {
 		ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
 		ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0);
 		ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
 		#endif
 	} else if (analog_config_bits == 10) {
 		ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
 		ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP;
 		ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3);
 		#endif
 	} else if (analog_config_bits == 12) {
 		ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
 		ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP;
 		ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
 		#endif
 	} else {
 		ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
 		ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP;
 		ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2);
 		#endif
@@ -91,12 +91,12 @@
 
 	if (analog_reference_internal) {
 		ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref
 		#endif
 	} else {
 		ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref
 		#endif
 	}
@@ -104,27 +104,27 @@
 	num = analog_num_average;
 	if (num <= 1) {
 		ADC0_SC3 = ADC_SC3_CAL;  // begin cal
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC3 = ADC_SC3_CAL;  // begin cal
 		#endif
 	} else if (num <= 4) {
 		ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0);
 		#endif
 	} else if (num <= 8) {
 		ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1);
 		#endif
 	} else if (num <= 16) {
 		ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2);
 		#endif
 	} else {
 		ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
-		#if defined(_mk20dx256_)
+		#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3);
 		#endif
 	}
@@ -140,7 +140,7 @@
 	while (ADC0_SC3 & ADC_SC3_CAL) {
 		// wait
 	}
-#elif defined(_mk20dx256_)
+#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 	while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) {
 		// wait
 	}
@@ -160,7 +160,7 @@
 		//serial_print("ADC0_MG = ");
 		//serial_phex16(sum);
 		//serial_print("\n");
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 		sum = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0;
 		sum = (sum / 2) | 0x8000;
 		ADC1_PG = sum;
@@ -192,7 +192,7 @@
 			analog_reference_internal = 1;
 			if (calibrating) {
 				ADC0_SC3 = 0; // cancel cal
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 				ADC1_SC3 = 0; // cancel cal
 #endif
 			}
@@ -204,7 +204,7 @@
 			analog_reference_internal = 0;
 			if (calibrating) {
 				ADC0_SC3 = 0; // cancel cal
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 				ADC1_SC3 = 0; // cancel cal
 #endif
 			}
@@ -266,7 +266,7 @@
 	5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
 	0, 19, 3, 21, 26, 22, 23
 };
-#elif defined(_mk20dx256_)
+#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 static const uint8_t channel2sc1a[] = {
 	5, 14, 8, 9, 13, 12, 6, 7, 15, 4,
 	0, 19, 3, 19+128, 26, 22, 23,
@@ -284,7 +284,7 @@
 
 // TODO: perhaps this should store the NVIC priority, so it works recursively?
 static volatile uint8_t analogReadBusyADC0 = 0;
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 static volatile uint8_t analogReadBusyADC1 = 0;
 #endif
 
@@ -300,7 +300,7 @@
 		index = pin;      // 0-13 refer to A0-A13
 	} else if (pin <= 23) {
 		index = pin - 14; // 14-23 are A0-A9
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 	} else if (pin >= 26 && pin <= 31) {
 		index = pin - 9;  // 26-31 are A15-A20
 #endif
@@ -323,7 +323,7 @@
 	if (calibrating) wait_for_cal();
 	//pin = 5; // PTD1/SE5b, pin 14, analog 0
 
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 	if (channel & 0x80) goto beginADC1;
 #endif
 
@@ -350,7 +350,7 @@
 		yield();
 	}
 
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 beginADC1:
 	__disable_irq();
 startADC1:
@@ -387,7 +387,7 @@
 
 void analogWriteDAC0(int val)
 {
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
 	SIM_SCGC2 |= SIM_SCGC2_DAC0;
 	if (analog_reference_internal) {
 		DAC0_C0 = DAC_C0_DACEN;  // 1.2V ref is DACREF_1
--- a/Scan/ADCTest/scan_loop.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/ADCTest/scan_loop.c	Thu Feb 12 19:37:19 2015 -0800
@@ -67,7 +67,7 @@
 // Scan Module command dictionary
 char scanCLIDictName[] = "ADC Test Module Commands";
 const CLIDictItem scanCLIDict[] = {
-#if defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
+#if defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 	{ "adc",     "Read the specified number of values from the ADC at the given pin: <pin> [# of reads]"
 	          NL "\t\t See \033[35mLib/pin_map.teensy3\033[0m for ADC0 channel number.", cliFunc_adc },
 	{ "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>"
@@ -75,7 +75,7 @@
 	          NL "\t\t          Vref -> 0 (1.2 V), 1 (External)"
 	          NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit },
 #endif
-#if defined(_mk20dx256_) // DAC is only supported on Teensy 3.1
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
 	{ "dac",     "Set DAC output value, from 0 to 4095 (1/4096 Vref to Vref).", cliFunc_dac },
 	{ "dacVref", "Set DAC Vref. 0 is 1.2V. 1 is 3.3V.", cliFunc_dacVref },
 #endif
@@ -94,7 +94,7 @@
 	// Register Scan CLI dictionary
 	CLI_registerDictionary( scanCLIDict, scanCLIDictName );
 }
-#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 {
 	// Register Scan CLI dictionary
 	CLI_registerDictionary( scanCLIDict, scanCLIDictName );
@@ -103,7 +103,7 @@
 	VREF_TRM = 0x60;
 	VREF_SC  = 0xE1; // Enable 1.2V Vref
 
-#if defined(_mk20dx256_) // DAC is only supported on Teensy 3.1
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
 	// DAC Setup
 	SIM_SCGC2 |= SIM_SCGC2_DAC0;
 	DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2
@@ -167,7 +167,7 @@
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 {
 }
-#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 {
 	// Parse code from argument
 	//  NOTE: Only first argument is used
@@ -220,7 +220,7 @@
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 {
 }
-#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM
 {
 	// Parse code from argument
 	//  NOTE: Only first argument is used
@@ -335,7 +335,7 @@
 
 void cliFunc_dac( char* args )
 {
-#if defined(_mk20dx256_) // DAC is only supported on Teensy 3.1
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
 	// Parse code from argument
 	//  NOTE: Only first argument is used
 	char* arg1Ptr;
@@ -354,7 +354,7 @@
 
 void cliFunc_dacVref( char* args )
 {
-#if defined(_mk20dx256_) // DAC is only supported on Teensy 3.1
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // DAC is only supported on Teensy 3.1
 	// Parse code from argument
 	//  NOTE: Only first argument is used
 	char* arg1Ptr;
--- a/Scan/DPH/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/DPH/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,6 +1,6 @@
 ###| CMake Kiibohd Controller Scan Module |###
 #
-# Written by Jacob Alexander in 2013-2014 for the Kiibohd Controller
+# Written by Jacob Alexander in 2013-2015 for the Kiibohd Controller
 #
 # Released into the Public Domain
 #
@@ -10,21 +10,15 @@
 ###
 # Module C files
 #
-
-set( SCAN_SRCS
+set ( Module_SRCS
 	scan_loop.c
 )
 
 
 ###
-# Module Specific Options
-#
-
-
-###
 # Compiler Family Compatibility
 #
-set( ScanModuleCompatibility
+set ( ModuleCompatibility
 	avr
 )
 
--- a/Scan/MBC-55X/scan_loop.c	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/MBC-55X/scan_loop.c	Thu Feb 12 19:37:19 2015 -0800
@@ -61,7 +61,7 @@
 // UART Receive Buffer Full Interrupt
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 ISR(USART1_RX_vect)
-#elif defined(_mk20dx128_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
 void uart0_status_isr(void)
 #endif
 {
@@ -72,7 +72,7 @@
 
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 	keyValue = UDR1;
-#elif defined(_mk20dx128_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
 	// UART0_S1 must be read for the interrupt to be cleared
 	if ( UART0_S1 & UART_S1_RDRF )
 	{
@@ -129,7 +129,7 @@
 	// Reset the keyboard before scanning, we might be in a wierd state
 	Scan_resetKeyboard();
 }
-#elif defined(_mk20dx128_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
 {
 	// Setup the the UART interface for keyboard data input
 	SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating
@@ -345,7 +345,7 @@
 
 #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR
 	UDR1 = dataPayload;
-#elif defined(_mk20dx128_) // ARM
+#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM
 	UART0_D = dataPayload;
 #endif
 
--- a/Scan/MD1/matrix.h	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/MD1/matrix.h	Thu Feb 12 19:37:19 2015 -0800
@@ -22,13 +22,10 @@
 #ifndef __MATRIX_H
 #define __MATRIX_H
 
-// ----- Macros -----
+// ----- Includes -----
 
-// Convenience Macros
-#define gpio( port, pin ) { Port_##port, Pin_##pin }
-#define Matrix_colsNum sizeof( Matrix_cols ) / sizeof( GPIO_Pin )
-#define Matrix_rowsNum sizeof( Matrix_rows ) / sizeof( GPIO_Pin )
-#define Matrix_maxKeys sizeof( Matrix_scanArray ) / sizeof( KeyState )
+// Project Includes
+#include <matrix_setup.h>
 
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD1/prototype.kll	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,73 @@
+Name = MD1;
+Version = 0.2;
+Author = "HaaTa (Jacob Alexander) 2014";
+KLL = 0.3;
+
+# Modified Date
+Date = 2014-09-14;
+
+
+S0x00 : U"Esc";
+S0x01 : U"1";
+S0x02 : U"2";
+S0x03 : U"3";
+S0x04 : U"4";
+S0x05 : U"5";
+S0x06 : U"6";
+S0x07 : U"7";
+S0x08 : U"8";
+S0x09 : U"9";
+S0x0A : U"0";
+S0x0B : U"Minus";
+S0x0C : U"Equal";
+S0x0D : U"Backslash";
+S0x0E : U"Tab";
+S0x0F : U"Q";
+S0x10 : U"W";
+S0x11 : U"E";
+S0x12 : U"R";
+S0x13 : U"T";
+S0x14 : U"Y";
+S0x15 : U"U";
+S0x16 : U"I";
+S0x17 : U"O";
+S0x18 : U"P";
+S0x19 : U"LBrace";
+S0x1A : U"RBrace";
+S0x1B : U"Backspace";
+S0x1C : U"Ctrl";
+S0x1D : U"A";
+S0x1E : U"S";
+S0x1F : U"D";
+S0x20 : U"F";
+S0x21 : U"G";
+S0x22 : U"H";
+S0x23 : U"J";
+S0x24 : U"K";
+S0x25 : U"L";
+S0x26 : U"Semicolon";
+S0x27 : U"Quote";
+S0x28 : U"Enter";
+S0x29 : U"LShift";
+S0x2A : U"Z";
+S0x2B : U"X";
+S0x2C : U"C";
+S0x2D : U"V";
+S0x2E : U"B";
+S0x2F : U"N";
+S0x30 : U"M";
+S0x31 : U"Comma";
+S0x32 : U"Period";
+S0x33 : U"Slash";
+S0x34 : U"RShift";
+S0x35 : U"Function1"; # Fun key
+S0x36 : U"Function2"; # Left Blank Key
+S0x37 : U"LAlt";
+S0x38 : U"LGui";
+S0x39 : U"Space";
+S0x3A : U"RGui";
+S0x3B : U"RAlt";
+S0x3C : U"Function3"; # Right Blank Key 1
+S0x3D : U"Function4"; # Right Blank Key 2
+S0x3E : U"BackTick";
+
--- a/Scan/MD1/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/MD1/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -8,27 +8,25 @@
 
 
 ###
+# Required Submodules
+#
+
+AddModule ( Scan MatrixARM )
+
+
+###
 # Module C files
 #
 
-set( SCAN_SRCS
+set ( Module_SRCS
 	scan_loop.c
-	../MatrixARM/matrix_scan.c
-)
-
-
-###
-# Module Specific Options
-#
-add_definitions(
-	-I${HEAD_DIR}/Scan/MatrixARM
 )
 
 
 ###
 # Compiler Family Compatibility
 #
-set( ScanModuleCompatibility
+set ( ModuleCompatibility
 	arm
 )
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/defaultMap.kll	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,73 @@
+Name = MD1;
+Version = 0.2;
+Author = "HaaTa (Jacob Alexander) 2014";
+KLL = 0.3;
+
+# Modified Date
+Date = 2014-09-14;
+
+
+S0x00 : U"Esc";
+S0x01 : U"1";
+S0x02 : U"2";
+S0x03 : U"3";
+S0x04 : U"4";
+S0x05 : U"5";
+S0x06 : U"6";
+S0x07 : U"7";
+S0x08 : U"8";
+S0x09 : U"9";
+S0x0A : U"0";
+S0x0B : U"Minus";
+S0x0C : U"Equal";
+S0x0D : U"Backslash";
+S0x0E : U"Tab";
+S0x0F : U"Q";
+S0x10 : U"W";
+S0x11 : U"E";
+S0x12 : U"R";
+S0x13 : U"T";
+S0x14 : U"Y";
+S0x15 : U"U";
+S0x16 : U"I";
+S0x17 : U"O";
+S0x18 : U"P";
+S0x19 : U"LBrace";
+S0x1A : U"RBrace";
+S0x1B : U"Backspace";
+S0x1C : U"Ctrl";
+S0x1D : U"A";
+S0x1E : U"S";
+S0x1F : U"D";
+S0x20 : U"F";
+S0x21 : U"G";
+S0x22 : U"H";
+S0x23 : U"J";
+S0x24 : U"K";
+S0x25 : U"L";
+S0x26 : U"Semicolon";
+S0x27 : U"Quote";
+S0x28 : U"Enter";
+S0x29 : U"LShift";
+S0x2A : U"Z";
+S0x2B : U"X";
+S0x2C : U"C";
+S0x2D : U"V";
+S0x2E : U"B";
+S0x2F : U"N";
+S0x30 : U"M";
+S0x31 : U"Comma";
+S0x32 : U"Period";
+S0x33 : U"Slash";
+S0x34 : U"RShift";
+S0x35 : U"Function1"; # Fun key
+S0x36 : U"Function2"; # Left Blank Key
+S0x37 : U"LAlt";
+S0x38 : U"LGui";
+S0x39 : U"Space";
+S0x3A : U"RGui";
+S0x3B : U"RAlt";
+S0x3C : U"Function3"; # Right Blank Key 1
+S0x3D : U"Function4"; # Right Blank Key 2
+S0x3E : U"BackTick";
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/matrix.h	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,63 @@
+/* Copyright (C) 2014 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
+ * 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 __MATRIX_H
+#define __MATRIX_H
+
+// ----- Macros -----
+
+// Convenience Macros
+#define gpio( port, pin ) { Port_##port, Pin_##pin }
+#define Matrix_colsNum sizeof( Matrix_cols ) / sizeof( GPIO_Pin )
+#define Matrix_rowsNum sizeof( Matrix_rows ) / sizeof( GPIO_Pin )
+#define Matrix_maxKeys sizeof( Matrix_scanArray ) / sizeof( KeyState )
+
+
+
+// ----- Matrix Definition -----
+
+// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31
+// Not all chips have access to all of these pins (most don't have 160 pins :P)
+//
+// NOTE:
+// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down
+// Checking this is completely on the ownness of the user
+
+// MD1
+//
+// Columns (Strobe)
+//  PTB0..3,16,17
+//  PTC4,5
+//  PTD0
+//
+// Rows (Sense)
+//  PTD1..7
+
+// Define Rows (Sense) and Columns (Strobes)
+GPIO_Pin Matrix_cols[] = { gpio(B,0), gpio(B,1), gpio(B,2), gpio(B,3), gpio(B,16), gpio(B,17), gpio(C,4), gpio(C,5), gpio(D,0) };
+GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,2), gpio(D,3), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7) };
+
+// Define type of scan matrix
+Config Matrix_type = Config_Pulldown;
+
+
+#endif // __MATRIX_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/pinout	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,118 @@
+Pin Usage
+=========
+
+mk20dx256vlh7
+
+ ----
+|Keys|
+ ----
+
+* Strobe (Columns)
+
+TODO
+
+* Sense (Rows)
+
+TODO
+
+
+ -----
+|Clock|
+ -----
+
+PTA18 <-> PTA19
+
+
+ ---
+|I2C|
+ ---
+
+* Main - Connect to all ISSI Chips - Also break out header for debugging
+
+PTB0 - SCL0
+PTB1 - SDA0
+
+* Reserve - Might be used later if I2C bus is too slow with more than 1 ISSI chip
+
+PTE0 - SDA1
+PTE1 - SCL1
+
+* ISSI Control (enough pins for 3 chips reserved)
+
+PTC0 - INTB Chip 1
+PTC1 - INTB Chip 2
+PTC2 - INTB Chip 3 (Only needed if more than 96 RGB LEDs are required)
+
+PTA4 - SDB (tied to tall Chips, hardware shutdown)
+
+
+ ---
+|DAC|
+ ---
+
+DAC0 (N/C)
+
+
+ ----
+|UART|
+ ----
+
+* Comm - Will be used on split keyboards
+
+PTC3 - RX1 (N/C)
+PTC4 - TX1 (N/C)
+
+
+ -----
+|Debug|
+ -----
+
+* SWD - (Main reflash header)
+
+PTA0 (Pull-down)
+PTA3 (Pull-up)
+
+* LEDs
+
+PTA5 (LED only for PCB, not Teensy)
+
+* UARTs
+
+PTA1 - RX0 (UART Debug Header)
+PTA2 - TX0 (UART Debug Header)
+
+
+ ------
+|Unused|
+ ------
+
+* GPIO
+
+PTA12
+PTA13
+PTB2
+PTB3
+PTB16
+PTB17
+PTB18
+PTB19
+PTC5
+PTC6
+PTC7
+PTC8
+PTC9
+PTC10
+PTC11
+PTD0
+PTD1
+PTD2
+PTD3
+PTD4
+PTD5
+PTD6
+PTD7
+
+* Analog
+
+TODO
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/scan_loop.c	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,682 @@
+/* Copyright (C) 2014 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
+ * 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.
+ */
+
+// ----- Includes -----
+
+// Compiler Includes
+#include <Lib/ScanLib.h>
+
+// Project Includes
+#include <cli.h>
+#include <led.h>
+#include <print.h>
+#include <matrix_scan.h>
+
+// Local Includes
+#include "scan_loop.h"
+#include "macro.h"
+
+
+
+
+typedef struct I2C_Buffer {
+	uint16_t  head;
+	uint16_t  tail;
+	uint8_t   sequencePos;
+	uint16_t  size;
+	uint8_t  *buffer;
+} I2C_Buffer;
+
+// ----- Function Declarations -----
+
+// CLI Functions
+void cliFunc_echo( char* args );
+void cliFunc_i2cRecv( char* args );
+void cliFunc_i2cSend( char* args );
+void cliFunc_ledZero( char* args );
+
+uint8_t I2C_TxBufferPop();
+void I2C_BufferPush( uint8_t byte, I2C_Buffer *buffer );
+uint16_t I2C_BufferLen( I2C_Buffer *buffer );
+uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen );
+
+
+
+// ----- Variables -----
+
+// Scan Module command dictionary
+CLIDict_Entry( echo,        "Example command, echos the arguments." );
+CLIDict_Entry( i2cRecv,     "Send I2C sequence of bytes and expect a reply of 1 byte on the last sequence. Use |'s to split sequences with a stop." );
+CLIDict_Entry( i2cSend,     "Send I2C sequence of bytes. Use |'s to split sequences with a stop." );
+CLIDict_Entry( ledZero,     "Zero out LED register pages (non-configuration)." );
+
+CLIDict_Def( scanCLIDict, "Scan Module Commands" ) = {
+	CLIDict_Item( echo ),
+	CLIDict_Item( i2cRecv ),
+	CLIDict_Item( i2cSend ),
+	CLIDict_Item( ledZero ),
+	{ 0, 0, 0 } // Null entry for dictionary end
+};
+
+// Number of scans since the last USB send
+uint16_t Scan_scanCount = 0;
+
+
+
+// Before sending the sequence, I2C_TxBuffer_CurLen is assigned and as each byte is sent, it is decremented
+// Once I2C_TxBuffer_CurLen reaches zero, a STOP on the I2C bus is sent
+#define I2C_TxBufferLength 300
+#define I2C_RxBufferLength 8
+volatile uint8_t I2C_TxBufferPtr[ I2C_TxBufferLength ];
+volatile uint8_t I2C_RxBufferPtr[ I2C_TxBufferLength ];
+
+volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, (uint8_t*)I2C_TxBufferPtr };
+volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, (uint8_t*)I2C_RxBufferPtr };
+
+void I2C_setup()
+{
+	// Enable I2C internal clock
+	SIM_SCGC4 |= SIM_SCGC4_I2C0; // Bus 0
+
+	// External pull-up resistor
+	PORTB_PCR0 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
+	PORTB_PCR1 = PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(2);
+
+	// SCL Frequency Divider
+	// 400kHz -> 120 (0x85) @ 48 MHz F_BUS
+	I2C0_F = 0x85;
+	I2C0_FLT = 4;
+	I2C0_C1 = I2C_C1_IICEN;
+	I2C0_C2 = I2C_C2_HDRS; // High drive select
+
+	// Enable I2C Interrupt
+	NVIC_ENABLE_IRQ( IRQ_I2C0 );
+}
+
+
+
+// ----- Interrupt Functions -----
+
+void i2c0_isr()
+{
+	cli(); // Disable Interrupts
+
+	uint8_t status = I2C0_S; // Read I2C Bus status
+
+	// Master Mode Transmit
+	if ( I2C0_C1 & I2C_C1_TX )
+	{
+		// Check current use of the I2C bus
+		// Currently sending data
+		if ( I2C_TxBuffer.sequencePos > 0 )
+		{
+			// Make sure slave sent an ACK
+			if ( status & I2C_S_RXAK )
+			{
+				// NACK Detected, disable interrupt
+				erro_print("I2C NAK detected...");
+				I2C0_C1 = I2C_C1_IICEN;
+
+				// Abort Tx Buffer
+				I2C_TxBuffer.head = 0;
+				I2C_TxBuffer.tail = 0;
+				I2C_TxBuffer.sequencePos = 0;
+			}
+			else
+			{
+				// Transmit byte
+				I2C0_D = I2C_TxBufferPop();
+			}
+		}
+		// Receiving data
+		else if ( I2C_RxBuffer.sequencePos > 0 )
+		{
+			// Master Receive, addr sent
+			if ( status & I2C_S_ARBL )
+			{
+				// Arbitration Lost
+				erro_print("Arbitration lost...");
+				// TODO Abort Rx
+
+				I2C0_C1 = I2C_C1_IICEN;
+				I2C0_S = I2C_S_ARBL | I2C_S_IICIF; // Clear ARBL flag and interrupt
+			}
+			if ( status & I2C_S_RXAK )
+			{
+				// Slave Address NACK Detected, disable interrupt
+				erro_print("Slave Address I2C NAK detected...");
+				// TODO Abort Rx
+
+				I2C0_C1 = I2C_C1_IICEN;
+			}
+			else
+			{
+				dbug_print("Attempting to read byte");
+				I2C0_C1 = I2C_RxBuffer.sequencePos == 1
+					? I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK // Single byte read
+					: I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST; // Multi-byte read
+			}
+		}
+		else
+		{
+			/*
+			dbug_msg("STOP - ");
+			printHex( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) );
+			print(NL);
+			*/
+
+			// Delay around STOP to make sure it actually happens...
+			delayMicroseconds( 1 );
+			I2C0_C1 = I2C_C1_IICEN; // Send STOP
+			delayMicroseconds( 7 );
+
+			// If there is another sequence, start sending
+			if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) < I2C_TxBuffer.size )
+			{
+				// Clear status flags
+				I2C0_S = I2C_S_IICIF | I2C_S_ARBL;
+
+				// Wait...till the master dies
+				while ( I2C0_S & I2C_S_BUSY );
+
+				// Enable I2C interrupt
+				I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX;
+
+				// Transmit byte
+				I2C0_D = I2C_TxBufferPop();
+			}
+		}
+	}
+	// Master Mode Receive
+	else
+	{
+		// XXX Do we need to handle 2nd last byte?
+		//I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK; // No STOP, Rx, NAK on recv
+
+		// Last byte
+		if ( I2C_TxBuffer.sequencePos <= 1 )
+		{
+			// Change to Tx mode
+			I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
+
+			// Grab last byte
+			I2C_BufferPush( I2C0_D, (I2C_Buffer*)&I2C_RxBuffer );
+
+			delayMicroseconds( 1 ); // Should be enough time before issuing the stop
+			I2C0_C1 = I2C_C1_IICEN; // Send STOP
+		}
+		else
+		{
+			// Retrieve data
+			I2C_BufferPush( I2C0_D, (I2C_Buffer*)&I2C_RxBuffer );
+		}
+	}
+
+	I2C0_S = I2C_S_IICIF; // Clear interrupt
+
+	sei(); // Re-enable Interrupts
+}
+
+
+
+// ----- Functions -----
+
+void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t pageLen )
+{
+	// Page Setup
+	uint8_t pageSetup[] = { 0xE8, 0xFD, 0x00 };
+
+	// Max length of a page + chip id + reg start
+	uint8_t fullPage[ 0xB3 + 2 ] = { 0 };
+	fullPage[0] = 0xE8; // Set chip id, starting reg is already 0x00
+
+	// Iterate through given pages, zero'ing out the given register regions
+	for ( uint8_t page = startPage; page < startPage + numPages; page++ )
+	{
+		// Set page
+		pageSetup[2] = page;
+
+		// Setup page
+		while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 )
+			delay(1);
+
+		// Zero out page
+		while ( I2C_Send( fullPage, pageLen + 2, 0 ) == 0 )
+			delay(1);
+	}
+}
+
+
+// Setup
+inline void LED_setup()
+{
+	I2C_setup();
+
+	// Zero out Frame Registers
+	LED_zeroPages( 0x00, 8, 0xB3 ); // LED Registers
+	LED_zeroPages( 0x0B, 1, 0x0C ); // Control Registers
+
+	// Disable Hardware shutdown of ISSI chip (pull high)
+	GPIOD_PDDR |= (1<<1);
+	PORTD_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+	GPIOD_PSOR |= (1<<1);
+}
+
+
+inline uint8_t I2C_BufferCopy( uint8_t *data, uint8_t sendLen, uint8_t recvLen, I2C_Buffer *buffer )
+{
+	uint8_t reTurn = 0;
+
+	// If sendLen is greater than buffer fail right away
+	if ( sendLen > buffer->size )
+		return 0;
+
+	// Calculate new tail to determine if buffer has enough space
+	// The first element specifies the expected number of bytes from the slave (+1)
+	// The second element in the new buffer is the length of the buffer sequence (+1)
+	uint16_t newTail = buffer->tail + sendLen + 2;
+	if ( newTail >= buffer->size )
+		newTail -= buffer->size;
+
+	if ( I2C_BufferLen( buffer ) < sendLen + 2 )
+		return 0;
+
+/*
+	print("|");
+	printHex( sendLen + 2 );
+	print("|");
+	printHex( *tail );
+	print("@");
+	printHex( newTail );
+	print("@");
+*/
+
+	// If buffer is clean, return 1, otherwise 2
+	reTurn = buffer->head == buffer->tail ? 1 : 2;
+
+	// Add to buffer, already know there is enough room (simplifies adding logic)
+	uint8_t bufferHeaderPos = 0;
+	for ( uint16_t c = 0; c < sendLen; c++ )
+	{
+		// Add data to buffer
+		switch ( bufferHeaderPos )
+		{
+		case 0:
+			buffer->buffer[ buffer->tail ] = recvLen;
+			bufferHeaderPos++;
+			c--;
+			break;
+
+		case 1:
+			buffer->buffer[ buffer->tail ] = sendLen;
+			bufferHeaderPos++;
+			c--;
+			break;
+
+		default:
+			buffer->buffer[ buffer->tail ] = data[ c ];
+			break;
+		}
+
+		// Check for wrap-around case
+		if ( buffer->tail + 1 >= buffer->size )
+		{
+			buffer->tail = 0;
+		}
+		// Normal case
+		else
+		{
+			buffer->tail++;
+		}
+	}
+
+	return reTurn;
+}
+
+
+inline uint16_t I2C_BufferLen( I2C_Buffer *buffer )
+{
+	// Tail >= Head
+	if ( buffer->tail >= buffer->head )
+		return buffer->head + buffer->size - buffer->tail;
+
+	// Head > Tail
+	return buffer->head - buffer->tail;
+}
+
+
+void I2C_BufferPush( uint8_t byte, I2C_Buffer *buffer )
+{
+	// Make sure buffer isn't full
+	if ( buffer->tail + 1 == buffer->head || ( buffer->head > buffer->tail && buffer->tail + 1 - buffer->size == buffer->head ) )
+	{
+		warn_msg("I2C_BufferPush failed, buffer full: ");
+		printHex( byte );
+		print( NL );
+		return;
+	}
+
+	// Check for wrap-around case
+	if ( buffer->tail + 1 >= buffer->size )
+	{
+		buffer->tail = 0;
+	}
+	// Normal case
+	else
+	{
+		buffer->tail++;
+	}
+
+	// Add byte to buffer
+	buffer->buffer[ buffer->tail ] = byte;
+}
+
+
+uint8_t I2C_TxBufferPop()
+{
+	// Return 0xFF if no buffer left (do not rely on this)
+	if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) >= I2C_TxBuffer.size )
+	{
+		erro_msg("No buffer to pop an entry from... ");
+		printHex( I2C_TxBuffer.head );
+		print(" ");
+		printHex( I2C_TxBuffer.tail );
+		print(" ");
+		printHex( I2C_TxBuffer.sequencePos );
+		print(NL);
+		return 0xFF;
+	}
+
+	// If there is currently no sequence being sent, the first entry in the RingBuffer is the length
+	if ( I2C_TxBuffer.sequencePos == 0 )
+	{
+		I2C_TxBuffer.sequencePos = 0xFF; // So this doesn't become an infinite loop
+		I2C_RxBuffer.sequencePos = I2C_TxBufferPop();
+		I2C_TxBuffer.sequencePos = I2C_TxBufferPop();
+	}
+
+	uint8_t data = I2C_TxBuffer.buffer[ I2C_TxBuffer.head ];
+
+	// Prune head
+	I2C_TxBuffer.head++;
+
+	// Wrap-around case
+	if ( I2C_TxBuffer.head >= I2C_TxBuffer.size )
+		I2C_TxBuffer.head = 0;
+
+	// Decrement buffer sequence (until next stop will be sent)
+	I2C_TxBuffer.sequencePos--;
+
+	/*
+	dbug_msg("Popping: ");
+	printHex( data );
+	print(" ");
+	printHex( I2C_TxBuffer.head );
+	print(" ");
+	printHex( I2C_TxBuffer.tail );
+	print(" ");
+	printHex( I2C_TxBuffer.sequencePos );
+	print(NL);
+	*/
+	return data;
+}
+
+
+uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen )
+{
+	// Check head and tail pointers
+	// If full, return 0
+	// If empty, start up I2C Master Tx
+	// If buffer is non-empty and non-full, just append to the buffer
+	switch ( I2C_BufferCopy( data, sendLen, recvLen, (I2C_Buffer*)&I2C_TxBuffer ) )
+	{
+	// Not enough buffer space...
+	case 0:
+		/*
+		erro_msg("Not enough Tx buffer space... ");
+		printHex( I2C_TxBuffer.head );
+		print(":");
+		printHex( I2C_TxBuffer.tail );
+		print("+");
+		printHex( sendLen );
+		print("|");
+		printHex( I2C_TxBuffer.size );
+		print( NL );
+		*/
+		return 0;
+
+	// Empty buffer, initialize I2C
+	case 1:
+		// Clear status flags
+		I2C0_S = I2C_S_IICIF | I2C_S_ARBL;
+
+		// Check to see if we already have control of the bus
+		if ( I2C0_C1 & I2C_C1_MST )
+		{
+			// Already the master (ah yeah), send a repeated start
+			I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX;
+		}
+		// Otherwise, seize control
+		else
+		{
+			// Wait...till the master dies
+			while ( I2C0_S & I2C_S_BUSY );
+
+			// Now we're the master (ah yisss), get ready to send stuffs
+			I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
+		}
+
+		// Enable I2C interrupt
+		I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX;
+
+		// Depending on what type of transfer, the first byte is configured for R or W
+		I2C0_D = I2C_TxBufferPop();
+
+		return 1;
+	}
+
+	// Dirty buffer, I2C already initialized
+	return 2;
+}
+
+
+
+// LED State processing loop
+inline uint8_t LED_loop()
+{
+
+	// I2C Busy
+	// S & I2C_S_BUSY
+	//I2C_S_BUSY
+}
+
+
+
+// Setup
+inline void Scan_setup()
+{
+	// Register Scan CLI dictionary
+	CLI_registerDictionary( scanCLIDict, scanCLIDictName );
+
+	// Setup GPIO pins for matrix scanning
+	//Matrix_setup();
+
+	// Reset scan count
+	Scan_scanCount = 0;
+
+	// Setup LED Drivers
+	LED_setup();
+}
+
+
+// Main Detection Loop
+inline uint8_t Scan_loop()
+{
+	//Matrix_scan( Scan_scanCount++ );
+	//LED_scan();
+
+	return 0;
+}
+
+
+// Signal from Macro Module that all keys have been processed (that it knows about)
+inline void Scan_finishedWithMacro( uint8_t sentKeys )
+{
+}
+
+
+// Signal from Output Module that all keys have been processed (that it knows about)
+inline void Scan_finishedWithOutput( uint8_t sentKeys )
+{
+	// Reset scan loop indicator (resets each key debounce state)
+	// TODO should this occur after USB send or Macro processing?
+	Scan_scanCount = 0;
+}
+
+
+// ----- CLI Command Functions -----
+
+// XXX Just an example command showing how to parse arguments (more complex than generally needed)
+void cliFunc_echo( char* args )
+{
+	char* curArgs;
+	char* arg1Ptr;
+	char* arg2Ptr = args;
+
+	// Parse args until a \0 is found
+	while ( 1 )
+	{
+		print( NL ); // No \r\n by default after the command is entered
+
+		curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
+		CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
+
+		// Stop processing args if no more are found
+		if ( *arg1Ptr == '\0' )
+			break;
+
+		// Print out the arg
+		dPrint( arg1Ptr );
+	}
+}
+
+void cliFunc_i2cSend( char* args )
+{
+	char* curArgs;
+	char* arg1Ptr;
+	char* arg2Ptr = args;
+
+	// Buffer used after interpretting the args, will be sent to I2C functions
+	// NOTE: Limited to 8 bytes currently (can be increased if necessary
+	#define i2cSend_BuffLenMax 8
+	uint8_t buffer[ i2cSend_BuffLenMax ];
+	uint8_t bufferLen = 0;
+
+	// No \r\n by default after the command is entered
+	print( NL );
+	info_msg("Sending: ");
+
+	// Parse args until a \0 is found
+	while ( bufferLen < i2cSend_BuffLenMax )
+	{
+		curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
+		CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
+
+		// Stop processing args if no more are found
+		if ( *arg1Ptr == '\0' )
+			break;
+
+		// If | is found, end sequence and start new one
+		if ( *arg1Ptr == '|' )
+		{
+			print("| ");
+			I2C_Send( buffer, bufferLen, 0 );
+			bufferLen = 0;
+			continue;
+		}
+
+		// Interpret the argument
+		buffer[ bufferLen++ ] = (uint8_t)numToInt( arg1Ptr );
+
+		// Print out the arg
+		dPrint( arg1Ptr );
+		print(" ");
+	}
+
+	print( NL );
+
+	I2C_Send( buffer, bufferLen, 0 );
+}
+
+void cliFunc_i2cRecv( char* args )
+{
+	char* curArgs;
+	char* arg1Ptr;
+	char* arg2Ptr = args;
+
+	// Buffer used after interpretting the args, will be sent to I2C functions
+	// NOTE: Limited to 8 bytes currently (can be increased if necessary
+	#define i2cSend_BuffLenMax 8
+	uint8_t buffer[ i2cSend_BuffLenMax ];
+	uint8_t bufferLen = 0;
+
+	// No \r\n by default after the command is entered
+	print( NL );
+	info_msg("Sending: ");
+
+	// Parse args until a \0 is found
+	while ( bufferLen < i2cSend_BuffLenMax )
+	{
+		curArgs = arg2Ptr; // Use the previous 2nd arg pointer to separate the next arg from the list
+		CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr );
+
+		// Stop processing args if no more are found
+		if ( *arg1Ptr == '\0' )
+			break;
+
+		// If | is found, end sequence and start new one
+		if ( *arg1Ptr == '|' )
+		{
+			print("| ");
+			I2C_Send( buffer, bufferLen, 0 );
+			bufferLen = 0;
+			continue;
+		}
+
+		// Interpret the argument
+		buffer[ bufferLen++ ] = (uint8_t)numToInt( arg1Ptr );
+
+		// Print out the arg
+		dPrint( arg1Ptr );
+		print(" ");
+	}
+
+	print( NL );
+
+	I2C_Send( buffer, bufferLen, 1 ); // Only 1 byte is ever read at a time with the ISSI chip
+}
+
+void cliFunc_ledZero( char* args )
+{
+	print( NL ); // No \r\n by default after the command is entered
+	LED_zeroPages( 0x00, 8, 0xB3 );
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/scan_loop.h	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,44 @@
+/* Copyright (C) 2014 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
+ * 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 __SCAN_LOOP_H
+#define __SCAN_LOOP_H
+
+// ----- Includes -----
+
+// Compiler Includes
+#include <stdint.h>
+
+
+
+// ----- Functions -----
+
+// Functions to be called by main.c
+void Scan_setup( void );
+uint8_t Scan_loop( void );
+
+// Call-backs
+void Scan_finishedWithMacro( uint8_t sentKeys );  // Called by Macro Module
+void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module
+
+
+#endif // __SCAN_LOOP_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MD2/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,31 @@
+###| CMake Kiibohd Controller Scan Module |###
+#
+# Written by Jacob Alexander in 2014-2015 for the Kiibohd Controller
+#
+# Released into the Public Domain
+#
+###
+
+
+###
+# Required Sub-modules
+#
+AddModule ( Scan ISSILed )
+AddModule ( Scan MatrixARM )
+
+
+###
+# Module C files
+#
+set( Module_SRCS
+	scan_loop.c
+)
+
+
+###
+# Compiler Family Compatibility
+#
+set( ModuleCompatibility
+	arm
+)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Scan/MatrixARM/matrix_setup.h	Thu Feb 12 19:37:19 2015 -0800
@@ -0,0 +1,35 @@
+/* Copyright (C) 2014 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
+ * 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 __MATRIX_SETUP_H
+#define __MATRIX_SETUP_H
+
+// ----- Macros -----
+
+// Convenience Macros
+#define gpio( port, pin ) { Port_##port, Pin_##pin }
+#define Matrix_colsNum sizeof( Matrix_cols ) / sizeof( GPIO_Pin )
+#define Matrix_rowsNum sizeof( Matrix_rows ) / sizeof( GPIO_Pin )
+#define Matrix_maxKeys sizeof( Matrix_scanArray ) / sizeof( KeyState )
+
+
+#endif // __MATRIX_SETUP_H
+
--- a/Scan/MatrixARM/setup.cmake	Mon Dec 22 20:27:33 2014 -0600
+++ b/Scan/MatrixARM/setup.cmake	Thu Feb 12 19:37:19 2015 -0800
@@ -1,36 +1,30 @@
 ###| CMake Kiibohd Controller Scan Module |###
 #
-# 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
 #
 ###
 
+
 ###
-# Warning, that this module is not meant to be built stand-alone
+# Sub-module flag, cannot be included stand-alone
 #
-message( FATAL_ERROR
-"The 'MatrixARM' module is not a stand-alone module, and requires further setup."
-)
+set ( SubModule 1 )
+
 
 ###
 # Module C files
 #
-
-set( SCAN_SRCS
+set ( Module_SRCS
 	matrix_scan.c
 )
 
 
 ###
-# Module Specific Options
-#
-
-
-###
 # Compiler Family Compatibility
 #
-set( ScanModuleCompatibility
+set ( ModuleCompatibility
 	arm
 )