Procházet zdrojové kódy

Merge remote-tracking branch 'upstream/master'

bringup
Rowan Decker před 9 roky
rodič
revize
2922fce0f7

+ 2
- 2
Debug/cli/cli.c Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2014 by Jacob Alexander
/* Copyright (C) 2014-2015 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -422,7 +422,7 @@ void cliFunc_version( char* args )
print( NL );
print( " \033[1mRevision:\033[0m " CLI_Revision NL );
print( " \033[1mBranch:\033[0m " CLI_Branch NL );
print( " \033[1mTree Status:\033[0m " CLI_ModifiedStatus NL );
print( " \033[1mTree Status:\033[0m " CLI_ModifiedStatus CLI_ModifiedFiles NL );
print( " \033[1mRepo Origin:\033[0m " CLI_RepoOrigin NL );
print( " \033[1mCommit Date:\033[0m " CLI_CommitDate NL );
print( " \033[1mCommit Author:\033[0m " CLI_CommitAuthor NL );

+ 40
- 0
Lib/CMake/FindDFUSuffix.cmake Zobrazit soubor

@@ -0,0 +1,40 @@
# The module defines the following variables:
# DFU_SUFFIX_EXECUTABLE - path to ctags command line client
# DFU_SUFFIX_FOUND - true if the command line client was found
# DFU_SUFFIX_VERSION_STRING - the version of dfu-suffix found (since CMake 2.8.8)
# Example usage:
# find_package( DFUSuffix )
# if( DFU_SUFFIX_FOUND )
# message("ctags found: ${DFU_SUFFIX_EXECUTABLE}")
# endif()

find_program ( DFU_SUFFIX_EXECUTABLE
NAMES dfu-suffix
DOC "dfu-suffix executable"
)
mark_as_advanced ( DFU_SUFFIX_EXECUTABLE )

if ( DFU_SUFFIX_EXECUTABLE )
execute_process ( COMMAND ${DFU_SUFFIX_EXECUTABLE} --version
OUTPUT_VARIABLE dfu_suffix_version
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)

if ( dfu_suffix_version MATCHES "^dfu-suffix \\(dfu-util\\)" )
string ( REPLACE "\n" "" DFU_SUFFIX_VERSION_STRING ${dfu_suffix_version} )
string ( REPLACE "dfu-suffix (dfu-util) " "" DFU_SUFFIX_VERSION_STRING ${DFU_SUFFIX_VERSION_STRING} )
string ( REGEX REPLACE "Copyright .*$" "" DFU_SUFFIX_VERSION_STRING ${DFU_SUFFIX_VERSION_STRING} )
endif ()
unset ( dfu_suffix_version )
endif ()

# Handle the QUIETLY and REQUIRED arguments and set DFU_SUFFIX_FOUND to TRUE if
# all listed variables are TRUE

include ( FindPackageHandleStandardArgs )
find_package_handle_standard_args ( DFU_SUFFIX
REQUIRED_VARS DFU_SUFFIX_EXECUTABLE
VERSION_VAR DFU_SUFFIX_VERSION_STRING
)


+ 18
- 5
Lib/CMake/build.cmake Zobrazit soubor

@@ -1,6 +1,6 @@
###| CMAKE Kiibohd Controller Source Configurator |###
#
# Written by Jacob Alexander in 2011-2014 for the Kiibohd Controller
# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller
#
# Released into the Public Domain
#
@@ -46,12 +46,25 @@ endif ()


#| Convert the .ELF into a .bin to load onto the McHCK
#| Then sign using dfu-suffix (requries dfu-util)
if ( DEFINED DFU )
# dfu-suffix is required to sign the dfu binary
find_package ( DFUSuffix )

set( TARGET_BIN ${TARGET}.dfu.bin )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
COMMENT "Creating dfu binary file: ${TARGET_BIN}"
)
if ( DFU_SUFFIX_FOUND )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
COMMAND ${DFU_SUFFIX_EXECUTABLE} --add ${TARGET_BIN} --vid ${BOOT_VENDOR_ID} --pid ${BOOT_PRODUCT_ID} 1> /dev/null
COMMENT "Create and sign dfu bin file: ${TARGET_BIN}"
)
else ()
message ( WARNING "DFU Binary has not been signed, requires dfu-suffix..." )
add_custom_command( TARGET ${TARGET_ELF} POST_BUILD
COMMAND ${OBJ_COPY} ${BIN_FLAGS} ${TARGET_ELF} ${TARGET_BIN}
COMMENT "Creating dfu binary file: ${TARGET_BIN}"
)
endif ()
endif ()



+ 16
- 16
Lib/CMake/kll.cmake Zobrazit soubor

@@ -1,6 +1,6 @@
###| CMAKE Kiibohd Controller KLL Configurator |###
#
# Written by Jacob Alexander in 2014 for the Kiibohd Controller
# Written by Jacob Alexander in 2014-2015 for the Kiibohd Controller
#
# Released into the Public Domain
#
@@ -46,14 +46,10 @@ endif () # kll/kll.py exists

#| KLL_DEPENDS is used to build a dependency tree for kll.py, this way when files are changed, kll.py gets re-run

#| Search for capabilities.kll in each module directory
foreach ( DIR ${ScanModulePath} ${MacroModulePath} ${OutputModulePath} ${DebugModulePath} )
# capabilities.kll exists, add to BaseMap
set ( filename "${PROJECT_SOURCE_DIR}/${DIR}/capabilities.kll" )
if ( EXISTS ${filename} )
set ( BaseMap_Args ${BaseMap_Args} ${filename} )
set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} )
endif ()
#| Add each of the detected capabilities.kll
foreach ( filename ${ScanModule_KLL} ${MacroModule_KLL} ${OutputModule_KLL} ${DebugModule_KLL} )
set ( BaseMap_Args ${BaseMap_Args} ${filename} )
set ( KLL_DEPENDS ${KLL_DEPENDS} ${filename} )
endforeach ()

#| If set BaseMap cannot be found, use default map
@@ -118,21 +114,25 @@ endforeach ()
#

#| KLL Options
set ( kll_backend -b kiibohd )
set ( kll_template -t ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdKeymap.h )
set ( kll_outputname generatedKeymap.h )
set ( kll_output -o ${kll_outputname} )
set ( kll_define_output --defines-output kll_defs.h )
set ( kll_define_template --defines-template ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdDefs.h )
set ( kll_backend --backend kiibohd )
set ( kll_template --templates ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdKeymap.h ${PROJECT_SOURCE_DIR}/kll/templates/kiibohdDefs.h )
set ( kll_outputname generatedKeymap.h kll_defs.h )
set ( kll_output --outputs ${kll_outputname} )

#| KLL Cmd
set ( kll_cmd ${PROJECT_SOURCE_DIR}/kll/kll.py ${BaseMap_Args} ${DefaultMap_Args} ${PartialMap_Args} ${kll_backend} ${kll_template} ${kll_output} ${kll_define_template} ${kll_define_output} )
set ( kll_cmd ${PROJECT_SOURCE_DIR}/kll/kll.py ${BaseMap_Args} ${DefaultMap_Args} ${PartialMap_Args} ${kll_backend} ${kll_template} ${kll_output} )
add_custom_command ( OUTPUT ${kll_outputname}
COMMAND ${kll_cmd}
DEPENDS ${KLL_DEPENDS}
COMMENT "Generating KLL Layout"
)

#| KLL Regen Convenience Target
add_custom_target ( kll_regen
COMMAND ${kll_cmd}
COMMENT "Re-generating KLL Layout"
)

#| Append generated file to required sources so it becomes a dependency in the main build
set ( SRCS ${SRCS} ${kll_outputname} )


+ 47
- 30
Lib/CMake/modules.cmake Zobrazit soubor

@@ -1,6 +1,6 @@
###| CMAKE Kiibohd Controller Source Configurator |###
#
# Written by Jacob Alexander in 2011-2014 for the Kiibohd Controller
# Written by Jacob Alexander in 2011-2015 for the Kiibohd Controller
#
# Released into the Public Domain
#
@@ -104,10 +104,8 @@ function ( AddModule ModuleType ModuleName )
PathPrepend ( Module_SRCS ${ModulePath} ${Module_SRCS} )

# Check the current scope to see if a sub-module added some source files
set ( Module_SRCS ${${ModuleType}_SRCS} ${Module_SRCS} )

# Append each of the sources to each type of module srcs list
set ( ${ModuleType}_SRCS ${Module_SRCS} )
set ( ${ModuleType}_SRCS ${${ModuleType}_SRCS} ${Module_SRCS} )

# Add .h files
add_definitions ( -I${ModuleFullPath} )
@@ -124,8 +122,17 @@ function ( AddModule ModuleType ModuleName )
endif ()
endforeach ()

# Finally, add the sources to the parent scope (i.e. return)
# Check for any capabilities.kll files in the Module
set ( kll_capabilities_file "${ModuleFullPath}/capabilities.kll" )
if ( EXISTS ${kll_capabilities_file} )
# Add the kll file and any submodule kll files to the running list
set ( ${ModuleType}Module_KLL ${${ModuleType}Module_KLL} ${kll_capabilities_file} )
endif ()


# Finally, add the sources and kll files to the parent scope (i.e. return)
set ( ${ModuleType}_SRCS ${${ModuleType}_SRCS} PARENT_SCOPE )
set ( ${ModuleType}Module_KLL ${${ModuleType}Module_KLL} PARENT_SCOPE )
endfunction ()


@@ -150,7 +157,7 @@ find_package ( Ctags ) # Optional
#

#| Manufacturer name
set( MANUFACTURER "Kiibohd" )
set ( MANUFACTURER "Kiibohd" )


#| Serial Number
@@ -158,19 +165,29 @@ set( MANUFACTURER "Kiibohd" )

#| Modified
#| Takes a bit of work to extract the "M " using CMake, and not using it if there are no modifications
execute_process( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain
execute_process ( COMMAND ${GIT_EXECUTABLE} status -s -uno --porcelain
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Modified_INFO
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH )
set( Git_Modified_Status "Clean" )
string ( LENGTH "${Git_Modified_INFO}" Git_Modified_LENGTH )
set ( Git_Modified_Status "Clean" )
if ( ${Git_Modified_LENGTH} GREATER 2 )
string( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO )
set( Git_Modified_Status "Dirty" )
string ( SUBSTRING "${Git_Modified_INFO}" 1 2 Git_Modified_Flag_INFO )
set ( Git_Modified_Status "Dirty" )
endif ()

#| List of modified files
execute_process ( COMMAND ${GIT_EXECUTABLE} diff-index --name-only HEAD --
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Modified_Files
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string ( REGEX REPLACE "\n" "\\\\r\\\\n\\\\t" Git_Modified_Files "${Git_Modified_Files}" )
set ( Git_Modified_Files "\\r\\n\\t${Git_Modified_Files}" )

#| Branch
execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
@@ -180,7 +197,7 @@ execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD
)

#| Date
execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Date_INFO
ERROR_QUIET
@@ -188,7 +205,7 @@ execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%ci
)

#| Commit Author and Email
execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>"
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>"
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Commit_Author
ERROR_QUIET
@@ -196,7 +213,7 @@ execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format="%cn <%ce>"
)

#| Commit Revision
execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%H
execute_process ( COMMAND ${GIT_EXECUTABLE} show -s --format=%H
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Commit_Revision
ERROR_QUIET
@@ -204,7 +221,7 @@ execute_process( COMMAND ${GIT_EXECUTABLE} show -s --format=%H
)

#| Origin URL
execute_process( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
execute_process ( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
OUTPUT_VARIABLE Git_Origin_URL
ERROR_QUIET
@@ -212,25 +229,25 @@ execute_process( COMMAND ${GIT_EXECUTABLE} config --get remote.origin.url
)

#| Build Date
execute_process( COMMAND "date" "+%Y-%m-%d %T %z"
execute_process ( COMMAND "date" "+%Y-%m-%d %T %z"
OUTPUT_VARIABLE Build_Date
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)

#| Last Commit Date
set( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" )
set ( GitLastCommitDate "${Git_Modified_Status} ${Git_Branch_INFO} - ${Git_Date_INFO}" )

#| Uses CMake variables to include as defines
#| Primarily for USB configuration
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/Lib/_buildvars.h buildvars.h )
configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/Lib/_buildvars.h buildvars.h )



###
# Source Defines
#
set( SRCS
set ( SRCS
${MAIN_SRCS}
${COMPILER_SRCS}
${Scan_SRCS}
@@ -240,7 +257,7 @@ set( SRCS
)

#| Directories to include by default
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )



@@ -248,20 +265,20 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} )
# ctag Generation
#

if( CTAGS_EXECUTABLE )
if ( CTAGS_EXECUTABLE )
# Populate list of directories for ctags to parse
# NOTE: Doesn't support dots in the folder names...
foreach( filename ${SRCS} )
string( REGEX REPLACE "/[a-zA-Z0-9_-]+.c$" "" pathglob ${filename} )
file( GLOB filenames "${pathglob}/*.c" )
set( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
file( GLOB filenames "${pathglob}/*.h" )
set( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
endforeach()
foreach ( filename ${SRCS} )
string ( REGEX REPLACE "/[a-zA-Z0-9_-]+.c$" "" pathglob ${filename} )
file ( GLOB filenames "${pathglob}/*.c" )
set ( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
file ( GLOB filenames "${pathglob}/*.h" )
set ( CTAG_PATHS ${CTAG_PATHS} ${filenames} )
endforeach ()

# Generate the ctags
execute_process( COMMAND ctags ${CTAG_PATHS}
execute_process ( COMMAND ctags ${CTAG_PATHS}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
endif()
endif ()


+ 2
- 1
Lib/_buildvars.h Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2013-2014 by Jacob Alexander
/* Copyright (C) 2013-2015 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -38,6 +38,7 @@
#define CLI_Revision "@Git_Commit_Revision@"
#define CLI_Branch "@Git_Branch_INFO@"
#define CLI_ModifiedStatus "@Git_Modified_Status@"
#define CLI_ModifiedFiles "@Git_Modified_Files@"
#define CLI_RepoOrigin "@Git_Origin_URL@"
#define CLI_CommitDate "@Git_Date_INFO@"
#define CLI_CommitAuthor @Git_Commit_Author@

+ 1
- 1
LoadFile/load.dfu Zobrazit soubor

@@ -49,7 +49,7 @@ done
if [[ "$SERIAL_PORT" != "" ]] && [[ -e "$SERIAL_PORT" ]]; then
echo "NOTE: This may fail if the uC is in a bad state or does not support remote flashing"
printf "reload\r" > $SERIAL_PORT
sleep 1
sleep 2
fi

# Load via dfu-util

+ 28
- 4
Macro/PartialMap/macro.c Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2014 by Jacob Alexander
/* Copyright (C) 2014-2015 by Jacob Alexander
*
* This file is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -121,9 +121,11 @@ uint8_t macroPauseMode = 0;
uint16_t macroStepCounter = 0;


// Key Trigger List Buffer
// Key Trigger List Buffer and Layer Cache
// The layer cache is set on press only, hold and release events refer to the value set on press
TriggerGuide macroTriggerListBuffer[ MaxScanCode ];
uint8_t macroTriggerListBufferSize = 0;
var_uint_t macroTriggerListLayerCache[ MaxScanCode ];

// Pending Trigger Macro Index List
// * Any trigger macros that need processing from a previous macro processing loop
@@ -311,8 +313,24 @@ void Macro_layerShift_capability( uint8_t state, uint8_t stateType, uint8_t *arg

// Looks up the trigger list for the given scan code (from the active layer)
// NOTE: Calling function must handle the NULL pointer case
nat_ptr_t *Macro_layerLookup( uint8_t scanCode, uint8_t latch_expire )
nat_ptr_t *Macro_layerLookup( TriggerGuide *guide, uint8_t latch_expire )
{
uint8_t scanCode = guide->scanCode;

// TODO Analog
// If a normal key, and not pressed, do a layer cache lookup
if ( guide->type == 0x00 && guide->state != 0x01 )
{
// Cached layer
var_uint_t cachedLayer = macroTriggerListLayerCache[ scanCode ];

// Lookup map, then layer
nat_ptr_t **map = (nat_ptr_t**)LayerIndex[ cachedLayer ].triggerMap;
const Layer *layer = &LayerIndex[ cachedLayer ];

return map[ scanCode - layer->first ];
}

// If no trigger macro is defined at the given layer, fallthrough to the next layer
for ( uint16_t layerIndex = 0; layerIndex < macroLayerIndexStackSize; layerIndex++ )
{
@@ -342,6 +360,9 @@ nat_ptr_t *Macro_layerLookup( uint8_t scanCode, uint8_t latch_expire )
&& scanCode >= layer->first
&& *map[ scanCode - layer->first ] != 0 )
{
// Set the layer cache
macroTriggerListLayerCache[ scanCode ] = macroLayerIndexStack[ layerIndex ];

return map[ scanCode - layer->first ];
}
}
@@ -359,6 +380,9 @@ nat_ptr_t *Macro_layerLookup( uint8_t scanCode, uint8_t latch_expire )
&& scanCode >= layer->first
&& *map[ scanCode - layer->first ] != 0 )
{
// Set the layer cache to default map
macroTriggerListLayerCache[ scanCode ] = 0;

return map[ scanCode - layer->first ];
}

@@ -836,7 +860,7 @@ inline void Macro_updateTriggerMacroPendingList()
uint8_t latch_expire = macroTriggerListBuffer[ key ].state == 0x03;

// Lookup Trigger List
nat_ptr_t *triggerList = Macro_layerLookup( macroTriggerListBuffer[ key ].scanCode, latch_expire );
nat_ptr_t *triggerList = Macro_layerLookup( &macroTriggerListBuffer[ key ], latch_expire );

// Number of Triggers in list
nat_ptr_t triggerListSize = triggerList[0];

+ 2
- 2
Macro/PartialMap/usb_hid.h Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2011-2014 by Jacob Alexander
/* Copyright (C) 2011-2015 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -113,7 +113,7 @@
#define KEY_UP 0x52
#define KEY_NUM_LOCK 0x53
#define KEYPAD_SLASH 0x54
#define KEYPAD_ASTERIX 0x55
#define KEYPAD_ASTERISK 0x55
#define KEYPAD_MINUS 0x56
#define KEYPAD_PLUS 0x57
#define KEYPAD_ENTER 0x58

+ 19
- 5
Output/pjrcUSB/arm/usb_dev.c Zobrazit soubor

@@ -300,7 +300,7 @@ static void usb_setup()
data = reply_buffer;
break;
case 0x0082: // GET_STATUS (endpoint)
if (setup.wIndex > NUM_ENDPOINTS)
if ( setup.wIndex > NUM_ENDPOINTS )
{
// TODO: do we need to handle IN vs OUT here?
endpoint0_stall();
@@ -313,17 +313,31 @@ static void usb_setup()
data = reply_buffer;
datalen = 2;
break;
case 0x0102: // CLEAR_FEATURE (endpoint)
case 0x0100: // CLEAR_FEATURE (device)
case 0x0101: // CLEAR_FEATURE (interface)
// TODO: Currently ignoring, perhaps useful? -HaaTa
endpoint0_stall();
return;
case 0x0102: // CLEAR_FEATURE (interface)
i = setup.wIndex & 0x7F;
if ( i > NUM_ENDPOINTS || setup.wValue != 0 )
{
// TODO: do we need to handle IN vs OUT here?
endpoint0_stall();
return;
}
(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02;
//(*(uint8_t *)(&USB0_ENDPT0 + setup.wIndex * 4)) &= ~0x02;
// TODO: do we need to clear the data toggle here?
break;
//break;

// FIXME: Clearing causes keyboard to freeze, likely an invalid clear
// XXX: Ignoring seems to work, though this may not be the ideal behaviour -HaaTa
endpoint0_stall();
return;
case 0x0300: // SET_FEATURE (device)
case 0x0301: // SET_FEATURE (interface)
// TODO: Currently ignoring, perhaps useful? -HaaTa
endpoint0_stall();
return;
case 0x0302: // SET_FEATURE (endpoint)
i = setup.wIndex & 0x7F;
if ( i > NUM_ENDPOINTS || setup.wValue != 0 )

+ 55
- 1
Output/pjrcUSB/arm/usb_keyboard.c Zobrazit soubor

@@ -1,7 +1,7 @@
/* Teensyduino Core Library
* http://www.pjrc.com/teensy/
* Copyright (c) 2013 PJRC.COM, LLC.
* Modifications by Jacob Alexander 2013-2014
* Modifications by Jacob Alexander 2013-2015
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -120,6 +120,23 @@ void usb_keyboard_send()
{
// Send boot keyboard interrupt packet(s)
case 0:
// USB Boot Mode debug output
if ( Output_DebugMode )
{
dbug_msg("Boot USB: ");
printHex_op( USBKeys_Modifiers, 2 );
print(" ");
printHex( 0 );
print(" ");
printHex_op( USBKeys_Keys[0], 2 );
printHex_op( USBKeys_Keys[1], 2 );
printHex_op( USBKeys_Keys[2], 2 );
printHex_op( USBKeys_Keys[3], 2 );
printHex_op( USBKeys_Keys[4], 2 );
printHex_op( USBKeys_Keys[5], 2 );
print( NL );
}

// Boot Mode
*tx_buf++ = USBKeys_Modifiers;
*tx_buf++ = 0;
@@ -133,9 +150,21 @@ void usb_keyboard_send()

// Send NKRO keyboard interrupts packet(s)
case 1:
if ( Output_DebugMode )
{
dbug_msg("NKRO USB: ");
}

// Check system control keys
if ( USBKeys_Changed & USBKeyChangeState_System )
{
if ( Output_DebugMode )
{
print("SysCtrl[");
printHex_op( USBKeys_SysCtrl, 2 );
print( "] " NL );
}

*tx_buf++ = 0x02; // ID
*tx_buf = USBKeys_SysCtrl;
tx_packet->len = 2;
@@ -148,6 +177,13 @@ void usb_keyboard_send()
// Check consumer control keys
if ( USBKeys_Changed & USBKeyChangeState_Consumer )
{
if ( Output_DebugMode )
{
print("ConsCtrl[");
printHex_op( USBKeys_ConsCtrl, 2 );
print( "] " NL );
}

*tx_buf++ = 0x03; // ID
*tx_buf++ = (uint8_t)(USBKeys_ConsCtrl & 0x00FF);
*tx_buf = (uint8_t)(USBKeys_ConsCtrl >> 8);
@@ -161,6 +197,24 @@ void usb_keyboard_send()
// Standard HID Keyboard
if ( USBKeys_Changed )
{
// USB NKRO Debug output
if ( Output_DebugMode )
{
printHex_op( USBKeys_Modifiers, 2 );
print(" ");
for ( uint8_t c = 0; c < 6; c++ )
printHex_op( USBKeys_Keys[ c ], 2 );
print(" ");
for ( uint8_t c = 6; c < 20; c++ )
printHex_op( USBKeys_Keys[ c ], 2 );
print(" ");
printHex_op( USBKeys_Keys[20], 2 );
print(" ");
for ( uint8_t c = 21; c < 27; c++ )
printHex_op( USBKeys_Keys[ c ], 2 );
print( NL );
}

tx_packet->len = 0;

// Modifiers

+ 32
- 0
Output/pjrcUSB/output_com.c Zobrazit soubor

@@ -61,6 +61,7 @@
// ----- Function Declarations -----

void cliFunc_kbdProtocol( char* args );
void cliFunc_outputDebug( char* args );
void cliFunc_readLEDs ( char* args );
void cliFunc_sendKeys ( char* args );
void cliFunc_setKeys ( char* args );
@@ -72,6 +73,7 @@ void cliFunc_setMod ( char* args );

// Output Module command dictionary
CLIDict_Entry( kbdProtocol, "Keyboard Protocol Mode: 0 - Boot, 1 - OS/NKRO Mode" );
CLIDict_Entry( outputDebug, "Toggle Output Debug mode." );
CLIDict_Entry( readLEDs, "Read LED byte:" NL "\t\t1 NumLck, 2 CapsLck, 4 ScrlLck, 16 Kana, etc." );
CLIDict_Entry( sendKeys, "Send the prepared list of USB codes and modifier byte." );
CLIDict_Entry( setKeys, "Prepare a space separated list of USB codes (decimal). Waits until \033[35msendKeys\033[0m." );
@@ -79,6 +81,7 @@ CLIDict_Entry( setMod, "Set the modfier byte:" NL "\t\t1 LCtrl, 2 LShft, 4

CLIDict_Def( outputCLIDict, "USB Module Commands" ) = {
CLIDict_Item( kbdProtocol ),
CLIDict_Item( outputDebug ),
CLIDict_Item( readLEDs ),
CLIDict_Item( sendKeys ),
CLIDict_Item( setKeys ),
@@ -129,6 +132,11 @@ USBKeyChangeState USBKeys_Changed = USBKeyChangeState_None;
// 0 is often used to show that a USB cable is not plugged in (but has power)
uint8_t Output_Available = 0;

// Debug control variable for Output modules
// 0 - Debug disabled (default)
// 1 - Debug enabled
uint8_t Output_DebugMode = 0;



// ----- Capabilities -----
@@ -211,7 +219,10 @@ void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *

// Only send keypresses if press or hold state
if ( stateType == 0x00 && state == 0x03 ) // Release state
{
USBKeys_ConsCtrl = 0;
return;
}

// Set consumer control code
USBKeys_ConsCtrl = *(uint16_t*)(&args[0]);
@@ -242,7 +253,10 @@ void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *a

// Only send keypresses if press or hold state
if ( stateType == 0x00 && state == 0x03 ) // Release state
{
USBKeys_SysCtrl = 0;
return;
}

// Set system control code
USBKeys_SysCtrl = args[0];
@@ -584,6 +598,24 @@ void cliFunc_kbdProtocol( char* args )
}


void cliFunc_outputDebug( char* args )
{
// Parse number from argument
// NOTE: Only first argument is used
char* arg1Ptr;
char* arg2Ptr;
CLI_argumentIsolation( args, &arg1Ptr, &arg2Ptr );

// Default to 1 if no argument is given
Output_DebugMode = 1;

if ( arg1Ptr[0] != '\0' )
{
Output_DebugMode = (uint16_t)numToInt( arg1Ptr );
}
}


void cliFunc_readLEDs( char* args )
{
print( NL );

+ 2
- 0
Output/pjrcUSB/output_com.h Zobrazit soubor

@@ -81,6 +81,8 @@ extern USBKeyChangeState USBKeys_Changed;

extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working

extern uint8_t Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled



// ----- Capabilities -----

+ 0
- 14
Output/usbMuxUart/capabilities.kll Zobrazit soubor

@@ -1,14 +0,0 @@
Name = usbMuxUartCapabilities;
Version = 0.1;
Author = "HaaTa (Jacob Alexander) 2014";
KLL = 0.3;

# Modified Date
Date = 2014-09-28;


# Capabilties available to the usbMuxUart output module
consCtrlOut => Output_consCtrlSend_capability( consCode : 2 );
sysCtrlOut => Output_sysCtrlSend_capability( sysCode : 1 );
usbKeyOut => Output_usbCodeSend_capability( usbCode : 1 );


+ 77
- 4
Output/usbMuxUart/output_com.c Zobrazit soubor

@@ -33,10 +33,10 @@
// USB Includes
#if defined(_at90usb162_) || defined(_atmega32u4_) || defined(_at90usb646_) || defined(_at90usb1286_)
#elif defined(_mk20dx128_) || defined(_mk20dx128vlf5_) || defined(_mk20dx256_) || defined(_mk20dx256vlh7_)
#include <uartOut/arm/uart_serial.h>
#include <pjrcUSB/arm/usb_dev.h>
#include <pjrcUSB/arm/usb_keyboard.h>
#include <pjrcUSB/arm/usb_serial.h>
#include <arm/uart_serial.h>
#include <arm/usb_dev.h>
#include <arm/usb_keyboard.h>
#include <arm/usb_serial.h>
#endif

// Local Includes
@@ -135,10 +135,69 @@ USBKeyChangeState USBKeys_Changed = USBKeyChangeState_None;
// 0 is often used to show that a USB cable is not plugged in (but has power)
uint8_t Output_Available = 0;

// Debug control variable for Output modules
// 0 - Debug disabled (default)
// 1 - Debug enabled
uint8_t Output_DebugMode = 0;



// ----- Capabilities -----

// Set Boot Keyboard Protocol
void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args )
{
// Display capability name
if ( stateType == 0xFF && state == 0xFF )
{
print("Output_kbdProtocolBoot()");
return;
}

// Only set if necessary
if ( USBKeys_Protocol == 0 )
return;

// TODO Analog inputs
// Only set on key press
if ( stateType != 0x01 )
return;

// Flush the key buffers
Output_flushBuffers();

// Set the keyboard protocol to Boot Mode
USBKeys_Protocol = 0;
}


// Set NKRO Keyboard Protocol
void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args )
{
// Display capability name
if ( stateType == 0xFF && state == 0xFF )
{
print("Output_kbdProtocolNKRO()");
return;
}

// Only set if necessary
if ( USBKeys_Protocol == 1 )
return;

// TODO Analog inputs
// Only set on key press
if ( stateType != 0x01 )
return;

// Flush the key buffers
Output_flushBuffers();

// Set the keyboard protocol to NKRO Mode
USBKeys_Protocol = 1;
}


// Sends a Consumer Control code to the USB Output buffer
void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args )
{
@@ -374,6 +433,20 @@ void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *a

// ----- Functions -----

// Flush Key buffers
void Output_flushBuffers()
{
// Zero out USBKeys_Keys array
for ( uint8_t c = 0; c < USB_NKRO_BITFIELD_SIZE_KEYS; c++ )
USBKeys_Keys[ c ] = 0;

// Zero out other key buffers
USBKeys_ConsCtrl = 0;
USBKeys_Modifiers = 0;
USBKeys_SysCtrl = 0;
}


// USB Module Setup
inline void Output_setup()
{

+ 8
- 0
Output/usbMuxUart/output_com.h Zobrazit soubor

@@ -80,6 +80,8 @@ extern USBKeyChangeState USBKeys_Changed;

extern uint8_t Output_Available; // 0 - Output module not fully functional, 1 - Output module working

extern uint8_t Output_DebugMode; // 0 - Debug disabled, 1 - Debug enabled



// ----- Capabilities -----
@@ -88,6 +90,10 @@ void Output_consCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *
void Output_sysCtrlSend_capability( uint8_t state, uint8_t stateType, uint8_t *args );
void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *args );

// Configuration capabilities
void Output_kbdProtocolBoot_capability( uint8_t state, uint8_t stateType, uint8_t *args );
void Output_kbdProtocolNKRO_capability( uint8_t state, uint8_t stateType, uint8_t *args );



// ----- Functions -----
@@ -95,6 +101,8 @@ void Output_usbCodeSend_capability( uint8_t state, uint8_t stateType, uint8_t *a
void Output_setup();
void Output_send();

void Output_flushBuffers();

void Output_firmwareReload();
void Output_softReset();


+ 6
- 0
Output/usbMuxUart/setup.cmake Zobrazit soubor

@@ -23,6 +23,12 @@ set( Module_SRCS
output_com.c
)

# Remove duplicate output_com.c files from pjrcUSB and uartOut
list ( REMOVE_ITEM Output_SRCS
Output/pjrcUSB/output_com.c
Output/uartOut/output_com.c
)


###
# Compiler Family Compatibility

+ 110
- 3
README.markdown Zobrazit soubor

@@ -9,8 +9,9 @@ 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
Building on Mac should be ok for 99% of users with Macports or Homebrew. For
Homebrew, use `brew tap PX4/homebrew-px4` to get the arm-none-eabi-gcc installer.
The dfu Bootloader will not build correctly with the old version of
arm-none-eabi-gcc that Macports currently has (4.7.3). This is due to a bug
with lto (link time optimizations) which makes the resulting binary too big to
fit on the chip (must be less than 4096 Bytes).
@@ -58,7 +59,7 @@ ARM Specific (Teensy 3.0/3.1, Infinity Keyboard, McHCK)

- Arch Linux / Mac Ports
- arm-none-eabi-gcc
- arm-none-eaby-binutils
- arm-none-eabi-binutils

- Windows (https://launchpad.net/gcc-arm-embedded/+download)
- gcc-arm-none-eabi (win32.zip)
@@ -262,6 +263,112 @@ There are also CMake options for temporarily selecting modules. But it's
easier to just edit the file. e.g. `cmake -DScanModuleOverride=<module name>`.


Keymap Configuration
--------------------

This is where you define the layout for your keyboard.
Currently, the only way to define kebyoard layouts is using [KLL](https://www.overleaf.com/read/zzqbdwqjfwwf).

KLL is built up of 3 different kinds of keymaps in total.
The BaseMap, DefaultMap and PartialMaps.

For each type of keymap, it is possible to combine multiple .kll files together to create new ones using
the compiler. The order of the files matter, as the right-most file will overwrite any setting in the
previous files.

> NOTE: Each keymap is done after the entire file is processed. This means that within the file the order
> of assignment doesa *not* matter (if you assign the same thing twice, then yes the most recent one
> takes priority).


BaseMap defines what the keyboard can do. This includes specific capabilities of the keyboard (such as USB),
the mapping of Scan Codes to USB Codes and any specific configurations for the keyboard.
In general, the BaseMap rarely needs to be changed. Usually only when adding a new keyboard to the firmware
does the Basemap need any modification.
The BaseMap is what both DefaultMap and PartialMaps are based upon. This allows for a common reference
when defining custom keymappings.

> NOTE: Don't use defaultMap.kll to change your layouts. This will work, but they will not be portable.


The DefaultMap is the normal state of the keyboard, i.e. your default layer.
Using the BaseMap as a base, the DefaultMap is a modification of the BaseMap to what the keyboard should do.
Since the DefaultMap uses USB Code to USB Code translations, this means that keymaps used for one keyboard
will work with another keyboard.
For example, I use Colemak, so this means I only have to define Colemak once for every keyboard that supports
the kiibohd firmware. This is possible because every BaseMap defines the keyboard as a US ANSI like keyboard
layout.
The DefaultMap can also be thought of as Layer 0.


PartialMaps are optional keymaps that can be "stacked" on top of the DefaultMap.
They can be dynamically swapped out using the layer control capabilities:

- layerLatch( `<layer number>` )
- layerLock( `<layer number>` )
- layerShift( `<layer number>` )

layerShift is usually what you want as it works just like a standard shift key.
layerLock is similar to the CapsLock key. While layerLatch is a latch, where only the next key you press
will use that layer (e.g. stickykeys).

A unique aspect of KLL layers is that it's a true stack of layers.
When a layer is activated, only the keys that are specified by the layer will change.
This means, if you define a layer that only sets `CapsLock -> LCtrl` and `LCtrl->Capslock` only those keys
will change when you active the layer. All the other keys will use the layer that is "underneath" to
lookup the keypress (usually the DefaultMap).

This means that you can combine .kll files statically using the compiler or dynamically using the firmware.

You can set the max number of layers by changing the `stateWordSize` define in one of your kll files.
By default it is set to 8 in Macro/PartialMap/capabilities.kll. This means you can have up to 256 layers
total (this includes the DefaultMap).
You can increase this number to either 16 or 32 (this will use more Flash and RAM btw) which will give you
2^16 and 2^32 possible layers respectively (65 535 and 4 294 967 295).


```cmake
###
# Keymap Configuration (do not include the .kll extension)
#

#| Do not include the .kll extension
#| * BaseMap maps the native keyboard scan codes to USB Codes so the layout is compatible with all other layouts
#| * DefaultMap allows the default keymap to be modified from the BaseMap
#| * PartialMaps is a set of dynamically set layers (there is no limit, but too many may use up too much RAM...)
#| BaseMap generally does not need to be changed from "defaultMap"
#|
#| Syntax:
#| myMap
#| * defines a single .kll layout file, double-quotes are needed to distinguish between layers
#| "myMap specialLayer"
#| * defines myMap to be the main layout, then replace specialLayers on top of it
#|
#| - Only for PartialMaps -
#| "myMap specialLayer" "myMap colemak" dvorak
#| * As before, but also generates a second layer at index 2 and third at index 3
#|
#| NOTE: Remember to add key(s) to enable each Partial Layer
#| NOTE2: Layers are always based up the BaseMap (which should be an ANSI-like mapping)
#| NOTE3: Compiler looks in kll/layouts and the build directory for layout files (precedence on build directory)

##| Set the base keyboard .kll map, defaults to "defaultMap" if not found
##| Looks in Scan/<Module Name> for the available BaseMaps
set( BaseMap "defaultMap"
CACHE STRING "KLL BaseMap/Scancode Keymapping" )

##| Layer additonal .kll maps on the BaseMap, layers are in order from 1st to nth
##| Can be set to ""
set( DefaultMap "md1Overlay stdFuncMap"
CACHE STRING "KLL DefaultMap" )

##| ParitalMaps available on top of the BaseMap. See above for syntax on specifying multiple layers vs. layering
##| Can be set to ""
set( PartialMaps "hhkbpro2"
CACHE STRING "KLL PartialMaps/Layer Definitions" )
```


Linux Building
--------------


+ 34
- 0
Scan/MatrixARM/capabilities.kll Zobrazit soubor

@@ -0,0 +1,34 @@
Name = MatrixArmCapabilities;
Version = 0.1;
Author = "HaaTa (Jacob Alexander) 2015";
KLL = 0.3a;

# Modified Date
Date = 2015-02-28;

# Defines available to the MatrixArm sub-module
# This debounce scheme uses a rolling counter for press/unpress on each key
# Each counter is incremented if pressed/unpressed and the opposite counter is divided by 2
# Using the default division threshold (0xFFFF), there are approximately 13 cycles in a perfect cycle
# If debounce is actually necessary, this will increase (better switches will debounce faster)
#
# The maximum threshold is 0xFFFFFFFF, which will give around ~32 -> 36 cycles per perfect cycle
# Using a threshold higher than 0xFFFF will require 32 bit variables, and double the ram usage.
DebounceDivThreshold => DebounceDivThreshold_define;
DebounceDivThreshold = 0xFFFF; # Default debounce
#DebounceDivThreshold = 0xFFFFFFFF; # Max debounce

# This defines how often the matrix is scanned
# By, default the key matrix is scanned once per macro processing loop
# For fast uCs and bouncy switches, this can be non-ideal
# 0 - Bit-shift of 0
# 1 - Bit-shift of 1 (i.e. divide by 2)
# 2 - Bit-shift of 2 (i.e. divide by 4)
# 3 - Bit-shift of 3 (i.e. divide by 8)
# etc.
# Depending on the architecture, this is either a maximum of 16 or 32
# Increasing this value will increase switch latency
DebounceThrottleDiv => DebounceThrottleDiv_define;
DebounceThrottleDiv = 0; # Default
#DebounceThrottleDiv = 2; # /4 divider


+ 22
- 4
Scan/MatrixARM/matrix_scan.c Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2014 by Jacob Alexander
/* Copyright (C) 2014-2015 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -26,6 +26,7 @@

// Project Includes
#include <cli.h>
#include <kll.h>
#include <led.h>
#include <print.h>
#include <macro.h>
@@ -38,6 +39,14 @@



// ----- Defines -----

#if ( DebounceThrottleDiv_define > 0 )
nat_ptr_t Matrix_divCounter = 0;
#endif



// ----- Function Declarations -----

// CLI Functions
@@ -191,7 +200,7 @@ void Matrix_setup()
Matrix_scanArray[ item ].prevState = KeyState_Off;
Matrix_scanArray[ item ].curState = KeyState_Off;
Matrix_scanArray[ item ].activeCount = 0;
Matrix_scanArray[ item ].inactiveCount = 0xFFFF; // Start at 'off' steady state
Matrix_scanArray[ item ].inactiveCount = DebounceDivThreshold_define; // Start at 'off' steady state
}

// Clear scan stats counters
@@ -232,6 +241,15 @@ void Matrix_keyPositionDebug( KeyPosition pos )
// NOTE: scanNum should be reset to 0 after a USB send (to reset all the counters)
void Matrix_scan( uint16_t scanNum )
{
#if ( DebounceThrottleDiv_define > 0 )
// Scan-rate throttling
// By scanning using a divider, the scan rate slowed down
// DebounceThrottleDiv_define == 1 means -> /2 or half scan rate
// This helps with bouncy switches on fast uCs
if ( !( Matrix_divCounter++ & (1 << ( DebounceThrottleDiv_define - 1 )) ) )
return;
#endif

// Increment stats counters
if ( scanNum > matrixMaxScans ) matrixMaxScans = scanNum;
if ( scanNum == 0 )
@@ -275,14 +293,14 @@ void Matrix_scan( uint16_t scanNum )
if ( Matrix_pin( Matrix_rows[ sense ], Type_Sense ) )
{
// Only update if not going to wrap around
if ( state->activeCount < 0xFFFF ) state->activeCount += 1;
if ( state->activeCount < DebounceDivThreshold_define ) state->activeCount += 1;
state->inactiveCount >>= 1;
}
// Signal Not Detected
else
{
// Only update if not going to wrap around
if ( state->inactiveCount < 0xFFFF ) state->inactiveCount += 1;
if ( state->inactiveCount < DebounceDivThreshold_define ) state->inactiveCount += 1;
state->activeCount >>= 1;
}


+ 22
- 5
Scan/MatrixARM/matrix_scan.h Zobrazit soubor

@@ -1,4 +1,4 @@
/* Copyright (C) 2014 by Jacob Alexander
/* Copyright (C) 2014-2015 by Jacob Alexander
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,6 +24,23 @@

// ----- Includes -----

// KLL Generated Defines
#include <kll_defs.h>



// ----- Defines -----

#if ( DebounceDivThreshold_define < 0xFF + 1 )
#define DebounceCounter uint8_t
#elif ( DebounceDivThreshold_define < 0xFFFF + 1 )
#define DebounceCounter uint16_t
#elif ( DebounceDivThreshold_define < 0xFFFFFFFF + 1 )
#define DebounceCounter uint32_t
#else
#error "Debounce threshold is too high... 32 bit max. Check .kll defines."
#endif



// ----- Enums -----
@@ -110,10 +127,10 @@ typedef struct GPIO_Pin {

// Debounce Element
typedef struct KeyState {
KeyPosition prevState;
KeyPosition curState;
uint16_t activeCount;
uint16_t inactiveCount;
KeyPosition prevState;
KeyPosition curState;
DebounceCounter activeCount;
DebounceCounter inactiveCount;
} KeyState;