#| 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
+#!/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
+#!/bin/bash
+
+printf "led\r" > /dev/ttyACM0
+
+exit 0
+
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;
/* 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
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-// ----- Local Includes -----
+// ----- Includes -----
+// Local Includes
#include "mchck.h"
#include "dfu.desc.h"
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 );
# "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
#
###| 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
#
# 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
)
###| 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
#
###
-# 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
)
// 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
// 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
}
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
}
###| 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
#
# 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
)
+++ /dev/null
-/* 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
-
+++ /dev/null
-/* 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
-
+++ /dev/null
-###| 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
-)
-
###| 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
#
# 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
)
#| 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 ()
#| 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:" )
#| 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 )
#| 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 ()
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()
#| 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 ()
message( "${MCU}" )
-#| Indicate to later build step that this is a Teensy
-set( Teensy )
-
-
#| Chip Size Database
#| Teensy 1.0
if ( "${CHIP}" MATCHES "at90usb162" )
endif ()
-#| Only Teensy based AVRs supported
-set ( TEENSY 1 )
-
-
#| Extra Compiler Sources
#| Mostly for convenience functions like interrupt handlers
set( COMPILER_SRCS
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
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()
#
if ( NOT EXISTS "${PROJECT_SOURCE_DIR}/kll/kll.py" )
+ message ( STATUS "Downloading latest kll version:" )
+
# Make sure git is available
find_package ( Git REQUIRED )
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
+
###
# Path Setup
#
# 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 ()
#| 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} )
-#| Macro Module
-include ( "${MacroModulePath}/setup.cmake" )
-PathPrepend( MACRO_SRCS ${MacroModulePath} ${MACRO_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} )
+
+ # 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 ()
+
+ # 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} )
-#| Output Module
-include ( "${OutputModulePath}/setup.cmake" )
-PathPrepend( OUTPUT_SRCS ${OutputModulePath} ${OUTPUT_SRCS} )
+ # Add .h files
+ add_definitions ( -I${ModuleFullPath} )
+
+ # 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 ()
-#| Debugging Module
-include ( "${DebugModulePath}/setup.cmake" )
-PathPrepend( DEBUG_SRCS ${DebugModulePath} ${DEBUG_SRCS} )
+ # 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
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
-###
-# 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
#
#define __INTERRUPTS_H
// ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
#include <Lib/mk20dx.h>
// ----- 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()
// 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>
// ARM
-#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_)
+#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
#include <Lib/mk20dx.h>
// ----- 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>
// 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>
/* 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
* SOFTWARE.
*/
+// ----- Includes -----
+
// Local Includes
#include "mk20dx.h"
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
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 )
{
// NOTREACHED
__builtin_unreachable();
}
+#endif
void *memset( void *addr, int val, unsigned int len )
{
__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) );
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
}
// 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++ )
// 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 );
}
#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
+/* 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
+/* 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);
+}
+
-// 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
// 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
#!/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=$?
+
+# Load Screen Session if specified
+if (( "$EXIT_STATUS" == "0" )) && [[ "$AUTO_SCREEN_SESSION" != "" ]]; then
+ sleep 0.1
+ screen $AUTO_SCREEN_SESSION
+fi
-exit $?
+exit $EXIT_STATUS
#!/bin/bash
+# Convenience script for loading firmware onto a teensy type device
+# By default, initiates teensy-load-cli
-#| First check to see teensy-loader-cli has been compiled
+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.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
cd -
fi
-#| Loads the hex file onto the teensy
+# 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
+
+# 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 $EXIT_STATUS
#!/bin/bash
+# Convenience script for loading firmware onto a teensy type device
+# By default, initiates teensy-load-cli
-#| First check to see teensy-loader-cli has been compiled
+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 "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
cd -
fi
-#| Loads the hex file onto the teensy
+# 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
+
+# Loads the hex file onto the teensy
teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@
+EXIT_STATUS=$?
-exit $?
+exit $EXIT_STATUS
// 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;
// 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 ];
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
###| 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
#
# Module C files
#
-set( MACRO_SRCS
+set ( Module_SRCS
macro.c
)
-###
-# Module Specific Options
-#
-
-
###
# Compiler Family Compatibility
#
-set( MacroModuleCompatibility
+set ( ModuleCompatibility
arm
avr
)
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}
};
-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++ )
{
// enable d+ pullup
USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG;
+
+ return 1;
}
// return 0 if the USB is not configured, or the configuration
// ----- 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 );
// 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
// 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
// ----- 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
-/* 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
// 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"
// 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 -----
{
// 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 );
{
#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
-/* 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
extern USBKeyChangeState USBKeys_Changed;
+extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
// ----- Capabilities -----
###| 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
#
# Module C files
#
-
#| AVR Compiler
if ( ${COMPILER_FAMILY} MATCHES "avr" )
- set( OUTPUT_SRCS
+ set ( Module_SRCS
output_com.c
avr/usb_keyboard_serial.c
)
#| ARM Compiler
elseif ( ${COMPILER_FAMILY} MATCHES "arm" )
- set( OUTPUT_SRCS
+ set ( Module_SRCS
output_com.c
arm/usb_desc.c
arm/usb_dev.c
endif ( ${COMPILER_FAMILY} MATCHES "avr" )
-###
-# Module Specific Options
-#
-
###
# Compiler Family Compatibility
#
-set( OutputModuleCompatibility
+set( ModuleCompatibility
arm
avr
)
-/* 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
* 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;
// ----- 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;
}
// 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;
}
}
}
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
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;
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;
}
}
// 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;
}
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;
}
// 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;
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
}
-/* 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
// 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
// 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 -----
{
#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
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
}
-/* 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
extern USBKeyChangeState USBKeys_Changed;
+extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
// ----- Capabilities -----
###| 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
#
# Module C files
#
-
#| AVR Compiler
if ( ${COMPILER_FAMILY} MATCHES "avr" )
- set( OUTPUT_SRCS
+ set ( Module_SRCS
output_com.c
avr/uart_serial.c
)
#| ARM Compiler
elseif ( ${COMPILER_FAMILY} MATCHES "arm" )
- set( OUTPUT_SRCS
+ set ( Module_SRCS
output_com.c
arm/uart_serial.c
)
endif ()
-###
-# Module Specific Options
-#
-
###
# Compiler Family Compatibility
#
-set( OutputModuleCompatibility
+set( ModuleCompatibility
arm
# avr # TODO
)
-/* 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
// 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
// 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 -----
{
#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
-/* 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
extern USBKeyChangeState USBKeys_Changed;
+extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working
+
// ----- Capabilities -----
###| 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
#
###
-# Module C files
+# Required Submodules
#
-
-#| 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 ()
-
+AddModule ( Output pjrcUSB )
+AddModule ( Output uartOut )
###
-# Module Specific Options
+# Module C files
#
+set( Module_SRCS
+ output_com.c
+)
###
# Compiler Family Compatibility
#
-set( OutputModuleCompatibility
+set( ModuleCompatibility
arm
# avr # TODO
)
+++ /dev/null
-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
+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>
+```
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
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
}
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
}
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
}
//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;
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
}
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
}
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,
// 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
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
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
yield();
}
-#if defined(_mk20dx256_)
+#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
beginADC1:
__disable_irq();
startADC1:
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
// 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>"
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
// 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 );
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
#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
#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
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;
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;
###| 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
#
###
# Module C files
#
-
-set( SCAN_SRCS
+set ( Module_SRCS
scan_loop.c
)
-###
-# Module Specific Options
-#
-
-
###
# Compiler Family Compatibility
#
-set( ScanModuleCompatibility
+set ( ModuleCompatibility
avr
)
// 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
{
#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 )
{
// 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
#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
#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
+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";
+
###
-# Module C files
+# Required Submodules
#
-set( SCAN_SRCS
- scan_loop.c
- ../MatrixARM/matrix_scan.c
-)
+AddModule ( Scan MatrixARM )
###
-# Module Specific Options
+# Module C files
#
-add_definitions(
- -I${HEAD_DIR}/Scan/MatrixARM
+
+set ( Module_SRCS
+ scan_loop.c
)
###
# Compiler Family Compatibility
#
-set( ScanModuleCompatibility
+set ( ModuleCompatibility
arm
)
--- /dev/null
+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
+/* 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
+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
+/* 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
+/* 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
+###| 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
+/* 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
+
###| 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
)