#| You _MUST_ clean the build directory if you change this value | #| You _MUST_ clean the build directory if you change this value | ||||
#| | #| | ||||
set( CHIP | 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 | # Bootloader Configuration | ||||
# | # |
#!/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 | |||||
#!/bin/bash | |||||
printf "led\r" > /dev/ttyACM0 | |||||
exit 0 | |||||
int flash_program_section(uintptr_t addr, size_t num_words) | 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.fcmd = FTFL_FCMD_PROGRAM_SECTION; | ||||
FTFL.fccob.program_section.addr = addr; | FTFL.fccob.program_section.addr = addr; | ||||
FTFL.fccob.program_section.num_words = num_words; | FTFL.fccob.program_section.num_words = num_words; |
/* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | /* Copyright (c) 2011,2012 Simon Schubert <[email protected]>. | ||||
* Modifications by Jacob Alexander 2014 <[email protected]> | |||||
* Modifications by Jacob Alexander 2014-2015 <[email protected]> | |||||
* | * | ||||
* This program is free software: you can redistribute it and/or modify | * 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 | * 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/>. | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||||
*/ | */ | ||||
// ----- Local Includes ----- | |||||
// ----- Includes ----- | |||||
// Local Includes | |||||
#include "mchck.h" | #include "mchck.h" | ||||
#include "dfu.desc.h" | #include "dfu.desc.h" | ||||
void main() | void main() | ||||
{ | { | ||||
#if defined(_mk20dx128vlf5_) // Kiibohd-dfu / Infinity | |||||
// XXX McHCK uses B16 instead of A19 | |||||
// Enabling LED to indicate we are in the bootloader | // Enabling LED to indicate we are in the bootloader | ||||
GPIOA_PDDR |= (1<<19); | GPIOA_PDDR |= (1<<19); | ||||
// Setup pin - A19 - See Lib/pin_map.mchck for more details on pins | // 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); | PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | ||||
GPIOA_PSOR |= (1<<19); | 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(); | flash_prepare_flashing(); | ||||
usb_init( &dfu_device ); | usb_init( &dfu_device ); |
# "at90usb646" # Teensy++ 1.0 (avr) | # "at90usb646" # Teensy++ 1.0 (avr) | ||||
# "at90usb1286" # Teensy++ 2.0 (avr) | # "at90usb1286" # Teensy++ 2.0 (avr) | ||||
# "mk20dx128" # Teensy 3.0 (arm) | # "mk20dx128" # Teensy 3.0 (arm) | ||||
"mk20dx128vlf5" # McHCK mk20dx128vlf5 | |||||
"mk20dx128vlf5" # McHCK mk20dx128vlf5 | |||||
# "mk20dx256" # Teensy 3.1 (arm) | # "mk20dx256" # Teensy 3.1 (arm) | ||||
# "mk20dx256vlh7" # Kiibohd-dfu mk20dx256vlh7 | |||||
CACHE STRING "Microcontroller Chip" ) | 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 | # Compiler Intialization | ||||
# | # |
###| CMake Kiibohd Controller Debug Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
set( DEBUG_SRCS | |||||
set ( Module_SRCS | |||||
cli.c | 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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( DebugModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
avr | avr | ||||
) | ) |
###| CMake Kiibohd Controller Debug Module |### | ###| 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 | # 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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( DebugModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
avr | avr | ||||
) | ) |
// Setup pin - Pin 13 -> C5 - See Lib/pin_map.teensy3 for more details on pins | // 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); | PORTC_PCR5 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); | ||||
// MCHCK | |||||
// MCHCK / Kiibohd-dfu | |||||
#elif defined(_mk20dx128vlf5_) | #elif defined(_mk20dx128vlf5_) | ||||
/* Actual MCHCK | /* Actual MCHCK | ||||
// Setup pin - A19 - See Lib/pin_map.mchck for more details on pins | // 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); | 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 | #endif | ||||
} | } | ||||
GPIOA_PCOR |= (1<<19); | 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 | #endif | ||||
} | } | ||||
###| CMake Kiibohd Controller Debug Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
set( DEBUG_SRCS | |||||
set ( Module_SRCS | |||||
led.c | 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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( DebugModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
avr | avr | ||||
) | ) |
###| 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 |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
set( DEBUG_SRCS | |||||
set ( Module_SRCS | |||||
print.c | 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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( DebugModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
avr | avr | ||||
) | ) |
#| Set the Compilers (must be set first) | #| Set the Compilers (must be set first) | ||||
include( CMakeForceCompiler ) | 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) | #| 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 | #| "mk20dx256" # Teensy 3.1 | ||||
message( STATUS "Chip Selected:" ) | message( STATUS "Chip Selected:" ) | ||||
#| Chip Size Database | #| Chip Size Database | ||||
#| MCHCK Based | |||||
#| MCHCK Based / Kiibohd-dfu | |||||
if ( "${CHIP}" MATCHES "mk20dx128vlf5" ) | if ( "${CHIP}" MATCHES "mk20dx128vlf5" ) | ||||
set( SIZE_RAM 16384 ) | set( SIZE_RAM 16384 ) | ||||
set( SIZE_FLASH 126976 ) | set( SIZE_FLASH 126976 ) | ||||
#| Kiibohd-dfu | |||||
elseif ( "${CHIP}" MATCHES "mk20dx256vlh7" ) | |||||
set( SIZE_RAM 65536 ) | |||||
set( SIZE_FLASH 253952 ) | |||||
#| Teensy 3.0 | #| Teensy 3.0 | ||||
elseif ( "${CHIP}" MATCHES "mk20dx128" ) | elseif ( "${CHIP}" MATCHES "mk20dx128" ) | ||||
set( SIZE_RAM 16384 ) | set( SIZE_RAM 16384 ) | ||||
#| USB Defines, this is how the loader programs detect which type of chip base is used | #| 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( VENDOR_ID "0x1C11" ) | ||||
set( PRODUCT_ID "0xB04D" ) | set( PRODUCT_ID "0xB04D" ) | ||||
set( BOOT_VENDOR_ID "0x1C11" ) | set( BOOT_VENDOR_ID "0x1C11" ) | ||||
set( BOOT_PRODUCT_ID "0xB007" ) | set( BOOT_PRODUCT_ID "0xB007" ) | ||||
set( DFU 1 ) | set( DFU 1 ) | ||||
message( "dfu" ) | |||||
elseif ( "${CHIP}" MATCHES "mk20dx128" OR "${CHIP}" MATCHES "mk20dx256" ) | elseif ( "${CHIP}" MATCHES "mk20dx128" OR "${CHIP}" MATCHES "mk20dx256" ) | ||||
set( VENDOR_ID "0x1C11" ) | set( VENDOR_ID "0x1C11" ) | ||||
set( PRODUCT_ID "0xB04D" ) | set( PRODUCT_ID "0xB04D" ) | ||||
set( BOOT_VENDOR_ID "0x16c0" ) # TODO Double check, this is likely incorrect | set( BOOT_VENDOR_ID "0x16c0" ) # TODO Double check, this is likely incorrect | ||||
set( BOOT_PRODUCT_ID "0x0487" ) | set( BOOT_PRODUCT_ID "0x0487" ) | ||||
set( TEENSY 1 ) | set( TEENSY 1 ) | ||||
message( "Teensy" ) | |||||
endif () | endif () | ||||
if( BOOTLOADER ) | 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 "-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_" ) | #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() | else() | ||||
set( TUNING "-mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin -nostartfiles" ) | set( TUNING "-mthumb -nostdlib -fdata-sections -ffunction-sections -fshort-wchar -fno-builtin -nostartfiles" ) | ||||
endif() | endif() | ||||
#| Lss Flags | #| 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}" ) | message( "${MCU}" ) | ||||
#| Indicate to later build step that this is a Teensy | |||||
set( Teensy ) | |||||
#| Chip Size Database | #| Chip Size Database | ||||
#| Teensy 1.0 | #| Teensy 1.0 | ||||
if ( "${CHIP}" MATCHES "at90usb162" ) | if ( "${CHIP}" MATCHES "at90usb162" ) | ||||
endif () | endif () | ||||
#| Only Teensy based AVRs supported | |||||
set ( TEENSY 1 ) | |||||
#| Extra Compiler Sources | #| Extra Compiler Sources | ||||
#| Mostly for convenience functions like interrupt handlers | #| Mostly for convenience functions like interrupt handlers | ||||
set( COMPILER_SRCS | set( COMPILER_SRCS | ||||
set( BOOT_PRODUCT_ID "0x047D" ) | 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. | #| Compiler flag to set the C Standard level. | ||||
#| c89 = "ANSI" C | #| c89 = "ANSI" C | ||||
#| gnu89 = c89 plus GCC extensions | #| gnu89 = c89 plus GCC extensions |
SUFFIX "" # XXX Force Windows to keep the .exe off | 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 | #| Convert the .ELF into a .bin to load onto the McHCK | ||||
if( DEFINED DFU ) | |||||
if ( DEFINED DFU ) | |||||
set( TARGET_BIN ${TARGET}.dfu.bin ) | set( TARGET_BIN ${TARGET}.dfu.bin ) | ||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | 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}" | COMMENT "Creating dfu binary file: ${TARGET_BIN}" | ||||
) | ) | ||||
endif() | |||||
endif () | |||||
#| Convert the .ELF into a .HEX to load onto the Teensy | #| Convert the .ELF into a .HEX to load onto the Teensy | ||||
if ( DEFINED TEENSY ) | if ( DEFINED TEENSY ) | ||||
set( TARGET_HEX ${TARGET}.teensy.hex ) | set( TARGET_HEX ${TARGET}.teensy.hex ) | ||||
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD | 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}" | COMMENT "Creating iHex file to load: ${TARGET_HEX}" | ||||
) | ) | ||||
endif() | endif() |
# | # | ||||
if ( NOT EXISTS "${PROJECT_SOURCE_DIR}/kll/kll.py" ) | if ( NOT EXISTS "${PROJECT_SOURCE_DIR}/kll/kll.py" ) | ||||
message ( STATUS "Downloading latest kll version:" ) | |||||
# Make sure git is available | # Make sure git is available | ||||
find_package ( Git REQUIRED ) | find_package ( Git REQUIRED ) | ||||
execute_process ( COMMAND ${GIT_EXECUTABLE} clone https://github.com/kiibohd/kll.git | execute_process ( COMMAND ${GIT_EXECUTABLE} clone https://github.com/kiibohd/kll.git | ||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} | 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 | # Clone kll git repo | ||||
execute_process ( COMMAND ${GIT_EXECUTABLE} pull --rebase | execute_process ( COMMAND ${GIT_EXECUTABLE} pull --rebase | ||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/kll | WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/kll |
### | ### | ||||
# Path Setup | # Path Setup | ||||
# | # | ||||
# Module Check Function | # 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} ) | if ( ${mod_var} STREQUAL ${COMPILER_FAMILY} ) | ||||
# Module found, no need to scan further | # Module found, no need to scan further | ||||
return() | return() | ||||
endif () | 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 | #| Go through lists of sources and append paths | ||||
#| Usage: | #| Usage: | ||||
#| PathPrepend( OutputListOfSources <Prepend Path> <InputListOfSources> ) | #| PathPrepend( OutputListOfSources <Prepend Path> <InputListOfSources> ) | ||||
macro( PathPrepend Output SourcesPath ) | |||||
unset( tmpSource ) | |||||
macro ( PathPrepend Output SourcesPath ) | |||||
unset ( tmpSource ) | |||||
# Loop through items | # Loop through items | ||||
foreach( item ${ARGN} ) | |||||
foreach ( item ${ARGN} ) | |||||
# Set the path | # 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 | # 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 | # CMake Module Checking | ||||
# | # | ||||
find_package( Git REQUIRED ) | |||||
find_package( Ctags ) # Optional | |||||
find_package ( Git REQUIRED ) | |||||
find_package ( Ctags ) # Optional | |||||
set( SRCS | set( SRCS | ||||
${MAIN_SRCS} | ${MAIN_SRCS} | ||||
${COMPILER_SRCS} | ${COMPILER_SRCS} | ||||
${SCAN_SRCS} | |||||
${MACRO_SRCS} | |||||
${OUTPUT_SRCS} | |||||
${DEBUG_SRCS} | |||||
${Scan_SRCS} | |||||
${Macro_SRCS} | |||||
${Output_SRCS} | |||||
${Debug_SRCS} | |||||
) | ) | ||||
#| Directories to include by default | #| 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 | # ctag Generation | ||||
# | # |
#define __INTERRUPTS_H | #define __INTERRUPTS_H | ||||
// ARM | // ARM | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#include <Lib/mk20dx.h> | #include <Lib/mk20dx.h> | ||||
// ----- Defines ----- | // ----- Defines ----- | ||||
// ARM | // 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 | // Map the Interrupt Enable/Disable to the AVR names | ||||
#define cli() __disable_irq() | #define cli() __disable_irq() |
// ARM | // ARM | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#include <Lib/mk20dx.h> | #include <Lib/mk20dx.h> | ||||
#include <Lib/delay.h> | #include <Lib/delay.h> |
// ARM | // ARM | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#include <Lib/mk20dx.h> | #include <Lib/mk20dx.h> | ||||
// ----- Includes ----- | // ----- Includes ----- | ||||
// ARM | // ARM | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#include <Lib/mk20dx.h> | #include <Lib/mk20dx.h> | ||||
#include <Lib/delay.h> | #include <Lib/delay.h> |
// ARM | // ARM | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) | |||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#include <Lib/mk20dx.h> | #include <Lib/mk20dx.h> | ||||
#include <Lib/delay.h> | #include <Lib/delay.h> |
/* Teensyduino Core Library | /* Teensyduino Core Library | ||||
* http://www.pjrc.com/teensy/ | * http://www.pjrc.com/teensy/ | ||||
* Copyright (c) 2013 PJRC.COM, LLC. | * 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 | * Permission is hereby granted, free of charge, to any person obtaining | ||||
* a copy of this software and associated documentation files (the | * a copy of this software and associated documentation files (the | ||||
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
// ----- Includes ----- | |||||
// Local Includes | // Local Includes | ||||
#include "mk20dx.h" | #include "mk20dx.h" | ||||
portd_isr, // 59 Pin detect (Port D) | portd_isr, // 59 Pin detect (Port D) | ||||
porte_isr, // 60 Pin detect (Port E) | porte_isr, // 60 Pin detect (Port E) | ||||
software_isr, // 61 Software interrupt | software_isr, // 61 Software interrupt | ||||
#elif defined(_mk20dx256_) | |||||
#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
dma_ch0_isr, // 16 DMA channel 0 transfer complete | dma_ch0_isr, // 16 DMA channel 0 transfer complete | ||||
dma_ch1_isr, // 17 DMA channel 1 transfer complete | dma_ch1_isr, // 17 DMA channel 1 transfer complete | ||||
dma_ch2_isr, // 18 DMA channel 2 transfer complete | dma_ch2_isr, // 18 DMA channel 2 transfer complete | ||||
0xFF, // EEPROM Protection Byte FEPROT | 0xFF, // EEPROM Protection Byte FEPROT | ||||
0xFF, // Data Flash Protection Byte FDPROT | 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 | #endif | ||||
// ----- Functions ----- | // ----- Functions ----- | ||||
#if ( defined(_mk20dx128vlf5_) || defined(_mk20dx256vlh7_) ) && defined(_bootloader_) // Bootloader Section | |||||
__attribute__((noreturn)) | __attribute__((noreturn)) | ||||
static inline void jump_to_app( uintptr_t addr ) | static inline void jump_to_app( uintptr_t addr ) | ||||
{ | { | ||||
// NOTREACHED | // NOTREACHED | ||||
__builtin_unreachable(); | __builtin_unreachable(); | ||||
} | } | ||||
#endif | |||||
void *memset( void *addr, int val, unsigned int len ) | void *memset( void *addr, int val, unsigned int len ) | ||||
{ | { | ||||
__attribute__ ((section(".startup"))) | __attribute__ ((section(".startup"))) | ||||
void ResetHandler() | 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; | extern uint32_t _app_rom; | ||||
// We treat _app_rom as pointer to directly read the stack | // We treat _app_rom as pointer to directly read the stack | ||||
// pointer and check for valid app code. This is no fool | // pointer and check for valid app code. This is no fool | ||||
// proof method, but it should help for the first flash. | // 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 | 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) ); | memset( (uint8_t*)&VBAT, 0, sizeof(VBAT) ); | ||||
jump_to_app( addr ); | jump_to_app( addr ); | ||||
} | } | ||||
#endif | #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 | // Enable clocks to always-used peripherals | ||||
SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO | SIM_SCGC5 = 0x00043F82; // Clocks active to all GPIO | ||||
} | } | ||||
// Prepare RAM | // 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_) | #if defined(_mk20dx128vlf5_) | ||||
// Default all interrupts to medium priority level | // Default all interrupts to medium priority level | ||||
for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) | for ( unsigned int i = 0; i < NVIC_NUM_INTERRUPTS; i++ ) | ||||
// USB Clock and FLL select | // USB Clock and FLL select | ||||
SIM_SOPT2 = SIM_SOPT2_USBSRC | SIM_SOPT2_TRACECLKSEL; | 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 | #else | ||||
unsigned int i; | |||||
SCB_VTOR = 0; // use vector table in flash | SCB_VTOR = 0; // use vector table in flash | ||||
// default all interrupts to medium priority level | // 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 ); | NVIC_SET_PRIORITY( i, 128 ); | ||||
} | } |
#define IRQ_SOFTWARE 45 | #define IRQ_SOFTWARE 45 | ||||
#define NVIC_NUM_INTERRUPTS 46 | #define NVIC_NUM_INTERRUPTS 46 | ||||
#elif defined(_mk20dx256_) | |||||
#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
#define IRQ_DMA_CH0 0 | #define IRQ_DMA_CH0 0 | ||||
#define IRQ_DMA_CH1 1 | #define IRQ_DMA_CH1 1 | ||||
#define IRQ_DMA_CH2 2 | #define IRQ_DMA_CH2 2 |
/* 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); | |||||
} | |||||
/* 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 | // 34 analog only | ||||
// 35 analog only | // 35 analog only | ||||
// 36 analog only | // 36 analog only | ||||
// 40 DAC/A14 | // 40 DAC/A14 | ||||
// not available to user: | // 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 | // Analog Channel Channel | ||||
// Pin Pin Name ADC0 ADC1 | // Pin Pin Name ADC0 ADC1 |
#!/bin/bash | #!/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 | # Load via dfu-util | ||||
# Used for McHCK based uCs | # Used for McHCK based uCs | ||||
dfu-util -D @TARGET_BIN@ | 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 | #!/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 | if [ ! -e teensy-loader-cli/teensy-loader-cli ]; then | ||||
# Compile teensy-loader-cli | # Compile teensy-loader-cli | ||||
mkdir -p teensy-loader-cli | mkdir -p teensy-loader-cli | ||||
cd - | cd - | ||||
fi | 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@ | 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 | #!/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 | if [ ! -e teensy-loader-cli/teensy-loader-cli ]; then | ||||
# Compile teensy-loader-cli | # Compile teensy-loader-cli | ||||
mkdir -p teensy-loader-cli | mkdir -p teensy-loader-cli | ||||
cd - | cd - | ||||
fi | 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@ | teensy-loader-cli/teensy-loader-cli -mmcu=@MCU@ -w @TARGET_HEX@ | ||||
EXIT_STATUS=$? | |||||
exit $? | |||||
exit $EXIT_STATUS | |||||
// This needs to be defined per microcontroller | // This needs to be defined per microcontroller | ||||
// e.g. mk20s -> 32 bit | // e.g. mk20s -> 32 bit | ||||
// atmega -> 16 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; | typedef uint32_t nat_ptr_t; | ||||
#elif defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #elif defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
typedef uint16_t nat_ptr_t; | typedef uint16_t nat_ptr_t; |
// Evaluate/Update TriggerMacro | // Evaluate/Update TriggerMacro | ||||
inline TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex ) | |||||
TriggerMacroEval Macro_evalTriggerMacro( var_uint_t triggerMacroIndex ) | |||||
{ | { | ||||
// Lookup TriggerMacro | // Lookup TriggerMacro | ||||
const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ]; | const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ]; | ||||
void cliFunc_capList( char* args ) | void cliFunc_capList( char* args ) | ||||
{ | { | ||||
print( NL ); | print( NL ); | ||||
info_msg("Capabilities List"); | |||||
info_msg("Capabilities List "); | |||||
printHex( CapabilitiesNum ); | printHex( CapabilitiesNum ); | ||||
// Iterate through all of the capabilities and display them | // Iterate through all of the capabilities and display them |
###| CMake Kiibohd Controller Macro Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
set( MACRO_SRCS | |||||
set ( Module_SRCS | |||||
macro.c | macro.c | ||||
) | ) | ||||
### | |||||
# Module Specific Options | |||||
# | |||||
### | ### | ||||
# Compiler Family Compatibility | # Compiler Family Compatibility | ||||
# | # | ||||
set( MacroModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
avr | avr | ||||
) | ) |
struct usb_string_descriptor_struct usb_string_manufacturer_name_default = { | struct usb_string_descriptor_struct usb_string_manufacturer_name_default = { | ||||
sizeof(STR_MANUFACTURER), | sizeof(STR_MANUFACTURER), | ||||
3, | 3, | ||||
STR_MANUFACTURER | |||||
{STR_MANUFACTURER} | |||||
}; | }; | ||||
struct usb_string_descriptor_struct usb_string_product_name_default = { | struct usb_string_descriptor_struct usb_string_product_name_default = { | ||||
sizeof(STR_PRODUCT), | sizeof(STR_PRODUCT), | ||||
3, | 3, | ||||
STR_PRODUCT | |||||
{STR_PRODUCT} | |||||
}; | }; | ||||
struct usb_string_descriptor_struct usb_string_serial_number_default = { | struct usb_string_descriptor_struct usb_string_serial_number_default = { | ||||
sizeof(STR_SERIAL), | sizeof(STR_SERIAL), | ||||
3, | 3, | ||||
STR_SERIAL | |||||
{STR_SERIAL} | |||||
}; | }; | ||||
void usb_init() | |||||
uint8_t usb_init() | |||||
{ | { | ||||
#ifdef UART_DEBUG | #ifdef UART_DEBUG | ||||
print("USB INIT"NL); | print("USB INIT"NL); | ||||
#endif | #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 | // Clear out endpoints table | ||||
for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | for ( int i = 0; i <= NUM_ENDPOINTS * 4; i++ ) | ||||
{ | { | ||||
// enable d+ pullup | // enable d+ pullup | ||||
USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | USB0_CONTROL = USB_CONTROL_DPPULLUPNONOTG; | ||||
return 1; | |||||
} | } | ||||
// return 0 if the USB is not configured, or the configuration | // return 0 if the USB is not configured, or the configuration |
// ----- Functions ----- | // ----- Functions ----- | ||||
uint8_t usb_configured(); // is the USB port configured | 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_isr(); | ||||
void usb_tx( uint32_t endpoint, usb_packet_t *packet ); | void usb_tx( uint32_t endpoint, usb_packet_t *packet ); | ||||
void usb_tx_isr( uint32_t endpoint, usb_packet_t *packet ); | void usb_tx_isr( uint32_t endpoint, usb_packet_t *packet ); |
// initialize USB | // 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(); | HW_CONFIG(); | ||||
USB_FREEZE(); // enable USB | USB_FREEZE(); // enable USB | ||||
PLL_CONFIG(); // config PLL | PLL_CONFIG(); // config PLL | ||||
// Disable watchdog timer after possible software reset | // Disable watchdog timer after possible software reset | ||||
//wdt_init(); // XXX Not working...seems to be ok without this, not sure though | //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 | // return 0 if the USB is not configured, or the configuration |
// ----- Function Declarations ----- | // ----- Function Declarations ----- | ||||
// Basic USB Configuration | // Basic USB Configuration | ||||
void usb_init(); // initialize everything | |||||
uint8_t usb_init(); // initialize everything | |||||
uint8_t usb_configured(); // is the USB port configured | uint8_t usb_configured(); // is the USB port configured | ||||
// Keyboard HID Functions | // 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// USB Includes | // USB Includes | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | ||||
#include "avr/usb_keyboard_serial.h" | #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_dev.h" | ||||
#include "arm/usb_keyboard.h" | #include "arm/usb_keyboard.h" | ||||
#include "arm/usb_serial.h" | #include "arm/usb_serial.h" | ||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | 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 ----- | // ----- Capabilities ----- | ||||
{ | { | ||||
// Initialize the USB, and then wait for the host to set configuration. | // Initialize the USB, and then wait for the host to set configuration. | ||||
// This will hang forever if USB does not initialize | // 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 | // Register USB Output CLI dictionary | ||||
CLI_registerDictionary( outputCLIDict, outputCLIDictName ); | CLI_registerDictionary( outputCLIDict, outputCLIDictName ); | ||||
{ | { | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
uint16_t count = 0; | 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; | uint32_t count = 0; | ||||
#endif | #endif | ||||
// Count characters until NULL character, then send the amount counted | // 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
extern USBKeyChangeState USBKeys_Changed; | extern USBKeyChangeState USBKeys_Changed; | ||||
extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- |
###| CMake Kiibohd Controller USB Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
#| AVR Compiler | #| AVR Compiler | ||||
if ( ${COMPILER_FAMILY} MATCHES "avr" ) | if ( ${COMPILER_FAMILY} MATCHES "avr" ) | ||||
set( OUTPUT_SRCS | |||||
set ( Module_SRCS | |||||
output_com.c | output_com.c | ||||
avr/usb_keyboard_serial.c | avr/usb_keyboard_serial.c | ||||
) | ) | ||||
#| ARM Compiler | #| ARM Compiler | ||||
elseif ( ${COMPILER_FAMILY} MATCHES "arm" ) | elseif ( ${COMPILER_FAMILY} MATCHES "arm" ) | ||||
set( OUTPUT_SRCS | |||||
set ( Module_SRCS | |||||
output_com.c | output_com.c | ||||
arm/usb_desc.c | arm/usb_desc.c | ||||
arm/usb_dev.c | arm/usb_dev.c | ||||
endif ( ${COMPILER_FAMILY} MATCHES "avr" ) | endif ( ${COMPILER_FAMILY} MATCHES "avr" ) | ||||
### | |||||
# Module Specific Options | |||||
# | |||||
### | ### | ||||
# Compiler Family Compatibility | # Compiler Family Compatibility | ||||
# | # | ||||
set( OutputModuleCompatibility | |||||
set( ModuleCompatibility | |||||
arm | arm | ||||
avr | 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
#include "uart_serial.h" | |||||
// ----- Includes ----- | |||||
// Compiler Includes | |||||
#include <string.h> // For memcpy | |||||
// Project Includes | |||||
#include <Lib/OutputLib.h> | #include <Lib/OutputLib.h> | ||||
#include <Lib/Interrupts.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 ----- | // ----- 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; | volatile uint8_t uart_configured = 0; | ||||
// ----- Interrupt Functions ----- | // ----- Interrupt Functions ----- | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug | |||||
void uart0_status_isr() | void uart0_status_isr() | ||||
#elif defined(_mk20dx256vlh7_) // UART2 Debug | |||||
void uart2_status_isr() | |||||
#endif | |||||
{ | { | ||||
cli(); // Disable Interrupts | cli(); // Disable Interrupts | ||||
// UART0_S1 must be read for the interrupt to be cleared | // 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 there was actually nothing | ||||
if ( available == 0 ) | if ( available == 0 ) | ||||
{ | { | ||||
// Cleanup | // Cleanup | ||||
available = UART0_D; | |||||
UART0_CFIFO = UART_CFIFO_RXFLUSH; | |||||
available = UART_D; | |||||
UART_CFIFO = UART_CFIFO_RXFLUSH; | |||||
sei(); | sei(); | ||||
return; | return; | ||||
} | } | ||||
// Read UART0 into buffer until FIFO is empty | // Read UART0 into buffer until FIFO is empty | ||||
while ( available-- > 0 ) | 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 | // 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 | // 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 | // 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; | uart_configured = 0; | ||||
// Setup the the UART interface for keyboard data input | // 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_) | #if defined(_mk20dx128vlf5_) | ||||
// Pin Setup for UART0 | // Pin Setup for UART0 | ||||
PORTA_PCR1 = PORT_PCR_PE | PORT_PCR_PS | PORT_PCR_PFE | PORT_PCR_MUX(2); // RX Pin | 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 | 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 | // Teensy | ||||
#else | #else | ||||
// Pin Setup for UART0 | // Pin Setup for UART0 | ||||
PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin | PORTB_PCR17 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(3); // TX Pin | ||||
#endif | #endif | ||||
#if defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) // UART0 Debug | |||||
// Setup baud rate - 115200 Baud | // Setup baud rate - 115200 Baud | ||||
// 48 MHz / ( 16 * Baud ) = BDH/L | // 48 MHz / ( 16 * Baud ) = BDH/L | ||||
// Baud: 115200 -> 48 MHz / ( 16 * 115200 ) = 26.0416667 | // Baud: 115200 -> 48 MHz / ( 16 * 115200 ) = 26.0416667 | ||||
// Thus baud setting = 26 | // Thus baud setting = 26 | ||||
// NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet | // NOTE: If finer baud adjustment is needed see UARTx_C4 -> BRFA in the datasheet | ||||
uint16_t baud = 26; // Max setting of 8191 | 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 | // 8 bit, No Parity, Idle Character bit after stop | ||||
UART0_C1 = UART_C1_ILT; | |||||
UART_C1 = UART_C1_ILT; | |||||
// Interrupt notification watermarks | // 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: | // TX/RX FIFO Size: | ||||
// 0x0 - 1 dataword | // 0x0 - 1 dataword | ||||
// 0x1 - 4 dataword | // 0x1 - 4 dataword | ||||
// 0x2 - 8 dataword | // 0x2 - 8 dataword | ||||
UART0_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE; | |||||
UART_PFIFO = UART_PFIFO_TXFE | UART_PFIFO_RXFE; | |||||
// Reciever Inversion Disabled, LSBF | // Reciever Inversion Disabled, LSBF | ||||
// UART_S2_RXINV UART_S2_MSBF | // UART_S2_RXINV UART_S2_MSBF | ||||
UART0_S2 |= 0x00; | |||||
UART_S2 |= 0x00; | |||||
// Transmit Inversion Disabled | // Transmit Inversion Disabled | ||||
// UART_C3_TXINV | // UART_C3_TXINV | ||||
UART0_C3 |= 0x00; | |||||
UART_C3 |= 0x00; | |||||
// TX Enabled, RX Enabled, RX Interrupt Enabled, Generate idles | // TX Enabled, RX Enabled, RX Interrupt Enabled, Generate idles | ||||
// UART_C2_TE UART_C2_RE UART_C2_RIE UART_C2_ILIE | // 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 | // 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 is now ready to use | ||||
uart_configured = 1; | uart_configured = 1; | ||||
unsigned int value = -1; | unsigned int value = -1; | ||||
// Check to see if the FIFO has characters | // 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 | // 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 | // Number of bytes available in the receive buffer | ||||
int uart_serial_available() | int uart_serial_available() | ||||
{ | { | ||||
return uart0_buffer_items; | |||||
return uart_buffer_items; | |||||
} | } | ||||
// Discard any buffered input | // Discard any buffered input | ||||
void uart_serial_flush_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 ) | if ( !uart_configured ) | ||||
return -1; | 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; | return 0; | ||||
} | } | ||||
// While buffer is not empty and transmit buffer is | // While buffer is not empty and transmit buffer is | ||||
while ( position < size ) | 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; | return 0; | ||||
void uart_serial_flush_output() | void uart_serial_flush_output() | ||||
{ | { | ||||
// Delay until buffer has been sent | // 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// USB Includes | // USB Includes | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | #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" | #include "arm/uart_serial.h" | ||||
#endif | #endif | ||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | 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 ----- | // ----- Capabilities ----- | ||||
{ | { | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
uint16_t count = 0; | 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; | uint32_t count = 0; | ||||
#endif | #endif | ||||
// Count characters until NULL character, then send the amount counted | // Count characters until NULL character, then send the amount counted | ||||
inline void Output_softReset() | inline void Output_softReset() | ||||
{ | { | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #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(); | SOFTWARE_RESET(); | ||||
#endif | #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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
extern USBKeyChangeState USBKeys_Changed; | extern USBKeyChangeState USBKeys_Changed; | ||||
extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- |
###| CMake Kiibohd Controller UART Output Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
# Module C files | # Module C files | ||||
# | # | ||||
#| AVR Compiler | #| AVR Compiler | ||||
if ( ${COMPILER_FAMILY} MATCHES "avr" ) | if ( ${COMPILER_FAMILY} MATCHES "avr" ) | ||||
set( OUTPUT_SRCS | |||||
set ( Module_SRCS | |||||
output_com.c | output_com.c | ||||
avr/uart_serial.c | avr/uart_serial.c | ||||
) | ) | ||||
#| ARM Compiler | #| ARM Compiler | ||||
elseif ( ${COMPILER_FAMILY} MATCHES "arm" ) | elseif ( ${COMPILER_FAMILY} MATCHES "arm" ) | ||||
set( OUTPUT_SRCS | |||||
set ( Module_SRCS | |||||
output_com.c | output_com.c | ||||
arm/uart_serial.c | arm/uart_serial.c | ||||
) | ) | ||||
endif () | endif () | ||||
### | |||||
# Module Specific Options | |||||
# | |||||
### | ### | ||||
# Compiler Family Compatibility | # Compiler Family Compatibility | ||||
# | # | ||||
set( OutputModuleCompatibility | |||||
set( ModuleCompatibility | |||||
arm | arm | ||||
# avr # TODO | # 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
// USB Includes | // USB Includes | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) | #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 | #endif | ||||
// Local Includes | // Local Includes | ||||
// count until idle timeout | // count until idle timeout | ||||
uint8_t USBKeys_Idle_Count = 0; | 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 ----- | // ----- Capabilities ----- | ||||
{ | { | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
uint16_t count = 0; | 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; | uint32_t count = 0; | ||||
#endif | #endif | ||||
// Count characters until NULL character, then send the amount counted | // 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 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
extern USBKeyChangeState USBKeys_Changed; | extern USBKeyChangeState USBKeys_Changed; | ||||
extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working | |||||
// ----- Capabilities ----- | // ----- Capabilities ----- |
###| CMake Kiibohd Controller Muxed UART and USB Output Module |### | ###| 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 | # 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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( OutputModuleCompatibility | |||||
set( ModuleCompatibility | |||||
arm | arm | ||||
# avr # TODO | # avr # TODO | ||||
) | ) |
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> |
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) { | if (analog_config_bits == 8) { | ||||
ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); | ADC0_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); | ||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | 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_CFG1 = ADC_CFG1_24MHZ + ADC_CFG1_MODE(0); | ||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | ||||
#endif | #endif | ||||
} else if (analog_config_bits == 10) { | } else if (analog_config_bits == 10) { | ||||
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; | ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; | ||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | 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_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(2) + ADC_CFG1_ADLSMP; | ||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(3); | ||||
#endif | #endif | ||||
} else if (analog_config_bits == 12) { | } else if (analog_config_bits == 12) { | ||||
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; | ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; | ||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | 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_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(1) + ADC_CFG1_ADLSMP; | ||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | ||||
#endif | #endif | ||||
} else { | } else { | ||||
ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; | ADC0_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; | ||||
ADC0_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | 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_CFG1 = ADC_CFG1_12MHZ + ADC_CFG1_MODE(3) + ADC_CFG1_ADLSMP; | ||||
ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | ADC1_CFG2 = ADC_CFG2_MUXSEL + ADC_CFG2_ADLSTS(2); | ||||
#endif | #endif | ||||
if (analog_reference_internal) { | if (analog_reference_internal) { | ||||
ADC0_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref | 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 | ADC1_SC2 = ADC_SC2_REFSEL(1); // 1.2V ref | ||||
#endif | #endif | ||||
} else { | } else { | ||||
ADC0_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref | 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 | ADC1_SC2 = ADC_SC2_REFSEL(0); // vcc/ext ref | ||||
#endif | #endif | ||||
} | } | ||||
num = analog_num_average; | num = analog_num_average; | ||||
if (num <= 1) { | if (num <= 1) { | ||||
ADC0_SC3 = ADC_SC3_CAL; // begin cal | ADC0_SC3 = ADC_SC3_CAL; // begin cal | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
ADC1_SC3 = ADC_SC3_CAL; // begin cal | ADC1_SC3 = ADC_SC3_CAL; // begin cal | ||||
#endif | #endif | ||||
} else if (num <= 4) { | } else if (num <= 4) { | ||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); | 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); | ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(0); | ||||
#endif | #endif | ||||
} else if (num <= 8) { | } else if (num <= 8) { | ||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); | 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); | ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(1); | ||||
#endif | #endif | ||||
} else if (num <= 16) { | } else if (num <= 16) { | ||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); | 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); | ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(2); | ||||
#endif | #endif | ||||
} else { | } else { | ||||
ADC0_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); | 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); | ADC1_SC3 = ADC_SC3_CAL + ADC_SC3_AVGE + ADC_SC3_AVGS(3); | ||||
#endif | #endif | ||||
} | } | ||||
while (ADC0_SC3 & ADC_SC3_CAL) { | while (ADC0_SC3 & ADC_SC3_CAL) { | ||||
// wait | // wait | ||||
} | } | ||||
#elif defined(_mk20dx256_) | |||||
#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) { | while ((ADC0_SC3 & ADC_SC3_CAL) || (ADC1_SC3 & ADC_SC3_CAL)) { | ||||
// wait | // wait | ||||
} | } | ||||
//serial_print("ADC0_MG = "); | //serial_print("ADC0_MG = "); | ||||
//serial_phex16(sum); | //serial_phex16(sum); | ||||
//serial_print("\n"); | //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 = ADC1_CLPS + ADC1_CLP4 + ADC1_CLP3 + ADC1_CLP2 + ADC1_CLP1 + ADC1_CLP0; | ||||
sum = (sum / 2) | 0x8000; | sum = (sum / 2) | 0x8000; | ||||
ADC1_PG = sum; | ADC1_PG = sum; | ||||
analog_reference_internal = 1; | analog_reference_internal = 1; | ||||
if (calibrating) { | if (calibrating) { | ||||
ADC0_SC3 = 0; // cancel cal | ADC0_SC3 = 0; // cancel cal | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
ADC1_SC3 = 0; // cancel cal | ADC1_SC3 = 0; // cancel cal | ||||
#endif | #endif | ||||
} | } | ||||
analog_reference_internal = 0; | analog_reference_internal = 0; | ||||
if (calibrating) { | if (calibrating) { | ||||
ADC0_SC3 = 0; // cancel cal | ADC0_SC3 = 0; // cancel cal | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
ADC1_SC3 = 0; // cancel cal | ADC1_SC3 = 0; // cancel cal | ||||
#endif | #endif | ||||
} | } | ||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, | 5, 14, 8, 9, 13, 12, 6, 7, 15, 4, | ||||
0, 19, 3, 21, 26, 22, 23 | 0, 19, 3, 21, 26, 22, 23 | ||||
}; | }; | ||||
#elif defined(_mk20dx256_) | |||||
#elif defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
static const uint8_t channel2sc1a[] = { | static const uint8_t channel2sc1a[] = { | ||||
5, 14, 8, 9, 13, 12, 6, 7, 15, 4, | 5, 14, 8, 9, 13, 12, 6, 7, 15, 4, | ||||
0, 19, 3, 19+128, 26, 22, 23, | 0, 19, 3, 19+128, 26, 22, 23, | ||||
// TODO: perhaps this should store the NVIC priority, so it works recursively? | // TODO: perhaps this should store the NVIC priority, so it works recursively? | ||||
static volatile uint8_t analogReadBusyADC0 = 0; | static volatile uint8_t analogReadBusyADC0 = 0; | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
static volatile uint8_t analogReadBusyADC1 = 0; | static volatile uint8_t analogReadBusyADC1 = 0; | ||||
#endif | #endif | ||||
index = pin; // 0-13 refer to A0-A13 | index = pin; // 0-13 refer to A0-A13 | ||||
} else if (pin <= 23) { | } else if (pin <= 23) { | ||||
index = pin - 14; // 14-23 are A0-A9 | index = pin - 14; // 14-23 are A0-A9 | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
} else if (pin >= 26 && pin <= 31) { | } else if (pin >= 26 && pin <= 31) { | ||||
index = pin - 9; // 26-31 are A15-A20 | index = pin - 9; // 26-31 are A15-A20 | ||||
#endif | #endif | ||||
if (calibrating) wait_for_cal(); | if (calibrating) wait_for_cal(); | ||||
//pin = 5; // PTD1/SE5b, pin 14, analog 0 | //pin = 5; // PTD1/SE5b, pin 14, analog 0 | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
if (channel & 0x80) goto beginADC1; | if (channel & 0x80) goto beginADC1; | ||||
#endif | #endif | ||||
yield(); | yield(); | ||||
} | } | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
beginADC1: | beginADC1: | ||||
__disable_irq(); | __disable_irq(); | ||||
startADC1: | startADC1: | ||||
void analogWriteDAC0(int val) | void analogWriteDAC0(int val) | ||||
{ | { | ||||
#if defined(_mk20dx256_) | |||||
#if defined(_mk20dx256_) || defined(_mk20dx256vlh7_) | |||||
SIM_SCGC2 |= SIM_SCGC2_DAC0; | SIM_SCGC2 |= SIM_SCGC2_DAC0; | ||||
if (analog_reference_internal) { | if (analog_reference_internal) { | ||||
DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1 | DAC0_C0 = DAC_C0_DACEN; // 1.2V ref is DACREF_1 |
// Scan Module command dictionary | // Scan Module command dictionary | ||||
char scanCLIDictName[] = "ADC Test Module Commands"; | char scanCLIDictName[] = "ADC Test Module Commands"; | ||||
const CLIDictItem scanCLIDict[] = { | 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]" | { "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 }, | 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>" | { "adcInit", "Intialize/calibrate ADC: <ADC Resolution> <Vref> <Hardware averaging samples>" | ||||
NL "\t\t Vref -> 0 (1.2 V), 1 (External)" | NL "\t\t Vref -> 0 (1.2 V), 1 (External)" | ||||
NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit }, | NL "\t\tHw Avg Samples -> 0 (disabled), 4, 8, 16, 32", cliFunc_adcInit }, | ||||
#endif | #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 }, | { "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 }, | { "dacVref", "Set DAC Vref. 0 is 1.2V. 1 is 3.3V.", cliFunc_dacVref }, | ||||
#endif | #endif | ||||
// Register Scan CLI dictionary | // Register Scan CLI dictionary | ||||
CLI_registerDictionary( scanCLIDict, scanCLIDictName ); | CLI_registerDictionary( scanCLIDict, scanCLIDictName ); | ||||
} | } | ||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM | |||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_) // ARM | |||||
{ | { | ||||
// Register Scan CLI dictionary | // Register Scan CLI dictionary | ||||
CLI_registerDictionary( scanCLIDict, scanCLIDictName ); | CLI_registerDictionary( scanCLIDict, scanCLIDictName ); | ||||
VREF_TRM = 0x60; | VREF_TRM = 0x60; | ||||
VREF_SC = 0xE1; // Enable 1.2V Vref | 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 | // DAC Setup | ||||
SIM_SCGC2 |= SIM_SCGC2_DAC0; | SIM_SCGC2 |= SIM_SCGC2_DAC0; | ||||
DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 | DAC0_C0 = DAC_C0_DACEN | DAC_C0_DACRFS; // 3.3V VDDA is DACREF_2 | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #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 | // Parse code from argument | ||||
// NOTE: Only first argument is used | // NOTE: Only first argument is used | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #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 | // Parse code from argument | ||||
// NOTE: Only first argument is used | // NOTE: Only first argument is used | ||||
void cliFunc_dac( char* args ) | 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 | // Parse code from argument | ||||
// NOTE: Only first argument is used | // NOTE: Only first argument is used | ||||
char* arg1Ptr; | char* arg1Ptr; | ||||
void cliFunc_dacVref( char* args ) | 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 | // Parse code from argument | ||||
// NOTE: Only first argument is used | // NOTE: Only first argument is used | ||||
char* arg1Ptr; | char* arg1Ptr; |
###| CMake Kiibohd Controller Scan Module |### | ###| 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 | # Released into the Public Domain | ||||
# | # | ||||
### | ### | ||||
# Module C files | # Module C files | ||||
# | # | ||||
set( SCAN_SRCS | |||||
set ( Module_SRCS | |||||
scan_loop.c | scan_loop.c | ||||
) | ) | ||||
### | |||||
# Module Specific Options | |||||
# | |||||
### | ### | ||||
# Compiler Family Compatibility | # Compiler Family Compatibility | ||||
# | # | ||||
set( ScanModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
avr | avr | ||||
) | ) | ||||
// UART Receive Buffer Full Interrupt | // UART Receive Buffer Full Interrupt | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
ISR(USART1_RX_vect) | ISR(USART1_RX_vect) | ||||
#elif defined(_mk20dx128_) // ARM | |||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM | |||||
void uart0_status_isr(void) | void uart0_status_isr(void) | ||||
#endif | #endif | ||||
{ | { | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
keyValue = UDR1; | keyValue = UDR1; | ||||
#elif defined(_mk20dx128_) // ARM | |||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM | |||||
// UART0_S1 must be read for the interrupt to be cleared | // UART0_S1 must be read for the interrupt to be cleared | ||||
if ( UART0_S1 & UART_S1_RDRF ) | if ( UART0_S1 & UART_S1_RDRF ) | ||||
{ | { | ||||
// Reset the keyboard before scanning, we might be in a wierd state | // Reset the keyboard before scanning, we might be in a wierd state | ||||
Scan_resetKeyboard(); | Scan_resetKeyboard(); | ||||
} | } | ||||
#elif defined(_mk20dx128_) // ARM | |||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM | |||||
{ | { | ||||
// Setup the the UART interface for keyboard data input | // Setup the the UART interface for keyboard data input | ||||
SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating | SIM_SCGC4 |= SIM_SCGC4_UART0; // Disable clock gating | ||||
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | #if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_) // AVR | ||||
UDR1 = dataPayload; | UDR1 = dataPayload; | ||||
#elif defined(_mk20dx128_) // ARM | |||||
#elif defined(_mk20dx128_) || defined(_mk20dx256_) // ARM | |||||
UART0_D = dataPayload; | UART0_D = dataPayload; | ||||
#endif | #endif | ||||
#ifndef __MATRIX_H | #ifndef __MATRIX_H | ||||
#define __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> | |||||
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 | # Compiler Family Compatibility | ||||
# | # | ||||
set( ScanModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
) | ) | ||||
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"; | |||||
/* 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 | |||||
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 | |||||
/* 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 ); | |||||
} | |||||
/* Copyright (C) 2011 by Jacob Alexander | |||||
* | |||||
/* Copyright (C) 2014 by Jacob Alexander | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* in the Software without restriction, including without limitation the rights | * in the Software without restriction, including without limitation the rights | ||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
* copies of the Software, and to permit persons to whom the Software is | * copies of the Software, and to permit persons to whom the Software is | ||||
* furnished to do so, subject to the following conditions: | * furnished to do so, subject to the following conditions: | ||||
* | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
#ifndef print_h__ | |||||
#define print_h__ | |||||
#ifndef __SCAN_LOOP_H | |||||
#define __SCAN_LOOP_H | |||||
// ----- Disabler Defines ----- | |||||
// ----- Includes ----- | |||||
#define dPrint(c) | |||||
#define dPrintStr(c) | |||||
#define dPrintStrs(...) | |||||
#define dPrintStrNL(c) | |||||
#define dPrintStrsNL(...) | |||||
// Compiler Includes | |||||
#include <stdint.h> | |||||
// 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) | |||||
// ----- Functions ----- | |||||
// Error Messages | |||||
#define erro_dPrint(...) | |||||
#define erro_print(str) | |||||
// Functions to be called by main.c | |||||
void Scan_setup( void ); | |||||
uint8_t Scan_loop( void ); | |||||
// Debug Messages | |||||
#define dbug_dPrint(...) | |||||
#define dbug_print(str) | |||||
// Call-backs | |||||
void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module | |||||
void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module | |||||
// 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 | |||||
#endif // __SCAN_LOOP_H | |||||
###| 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 | |||||
) | |||||
/* Copyright (C) 2011 by Jacob Alexander | |||||
* | |||||
/* Copyright (C) 2014 by Jacob Alexander | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
* of this software and associated documentation files (the "Software"), to deal | * of this software and associated documentation files (the "Software"), to deal | ||||
* in the Software without restriction, including without limitation the rights | * in the Software without restriction, including without limitation the rights | ||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
* copies of the Software, and to permit persons to whom the Software is | * copies of the Software, and to permit persons to whom the Software is | ||||
* furnished to do so, subject to the following conditions: | * furnished to do so, subject to the following conditions: | ||||
* | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | * The above copyright notice and this permission notice shall be included in | ||||
* all copies or substantial portions of the Software. | * all copies or substantial portions of the Software. | ||||
* | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
* THE SOFTWARE. | * THE SOFTWARE. | ||||
*/ | */ | ||||
#ifndef __led_h | |||||
#define __led_h | |||||
#ifndef __MATRIX_SETUP_H | |||||
#define __MATRIX_SETUP_H | |||||
// ----- Disabler Defines ----- | |||||
#define init_errorLED() | |||||
#define errorLED(on) | |||||
// ----- Macros ----- | |||||
#endif | |||||
// 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 |### | ###| 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 | # 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 | # Module C files | ||||
# | # | ||||
set( SCAN_SRCS | |||||
set ( Module_SRCS | |||||
matrix_scan.c | matrix_scan.c | ||||
) | ) | ||||
### | |||||
# Module Specific Options | |||||
# | |||||
### | ### | ||||
# Compiler Family Compatibility | # Compiler Family Compatibility | ||||
# | # | ||||
set( ScanModuleCompatibility | |||||
set ( ModuleCompatibility | |||||
arm | arm | ||||
) | ) | ||||