X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=backends%2Fkiibohd.py;h=8419ee85e6e06e0c63f6b99afce5def7c26bf098;hb=b7a897986418b83d5037ebc14f659ec046457c45;hp=e25c64c8b2058398fd093d1c1fd7b8912f1acd55;hpb=ff6ba9198bf6e450988b00c73ae7e6fe074a1081;p=kiibohd-kll.git diff --git a/backends/kiibohd.py b/backends/kiibohd.py index e25c64c..8419ee8 100644 --- a/backends/kiibohd.py +++ b/backends/kiibohd.py @@ -3,7 +3,7 @@ # # Backend code generator for the Kiibohd Controller firmware. # -# 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 @@ -24,6 +24,8 @@ import os import sys import re +from datetime import date + # Modifying Python Path, which is dumb, but the only way to import up one directory... sys.path.append( os.path.expanduser('..') ) @@ -34,6 +36,7 @@ from kll_lib.containers import * ## Print Decorator Variables ERROR = '\033[5;1;31mERROR\033[0m:' +WARNING = '\033[5;1;33mWARNING\033[0m:' @@ -42,12 +45,13 @@ ERROR = '\033[5;1;31mERROR\033[0m:' class Backend: # Initializes backend # Looks for template file and builds list of fill tags - def __init__( self, templatePath ): + def __init__( self, templatePath, definesTemplatePath ): # Does template exist? if not os.path.isfile( templatePath ): print ( "{0} '{1}' does not exist...".format( ERROR, templatePath ) ) sys.exit( 1 ) + self.definesTemplatePath = definesTemplatePath self.templatePath = templatePath self.fill_dict = dict() @@ -58,6 +62,11 @@ class Backend: match = re.findall( '<\|([^|>]+)\|>', line ) for item in match: self.tagList.append( item ) + with open( definesTemplatePath, 'r' ) as openFile: + for line in openFile: + match = re.findall( '<\|([^|>]+)\|>', line ) + for item in match: + self.tagList.append( item ) # USB Code Capability Name @@ -65,8 +74,81 @@ class Backend: return "usbKeyOut"; + # TODO + def layerInformation( self, name, date, author ): + self.fill_dict['Information'] += "// Name: {0}\n".format( "TODO" ) + self.fill_dict['Information'] += "// Version: {0}\n".format( "TODO" ) + self.fill_dict['Information'] += "// Date: {0}\n".format( "TODO" ) + self.fill_dict['Information'] += "// Author: {0}\n".format( "TODO" ) + + # Processes content for fill tags and does any needed dataset calculations - def process( self, capabilities, macros ): + def process( self, capabilities, macros, variables, gitRev, gitChanges ): + # Build string list of compiler arguments + compilerArgs = "" + for arg in sys.argv: + if "--" in arg or ".py" in arg: + compilerArgs += "// {0}\n".format( arg ) + else: + compilerArgs += "// {0}\n".format( arg ) + + # Build a string of modified files, if any + gitChangesStr = "\n" + if len( gitChanges ) > 0: + for gitFile in gitChanges: + gitChangesStr += "// {0}\n".format( gitFile ) + else: + gitChangesStr = " None\n" + + # Prepare BaseLayout and Layer Info + baseLayoutInfo = "" + defaultLayerInfo = "" + partialLayersInfo = "" + for file, name in zip( variables.baseLayout['*LayerFiles'], variables.baseLayout['*NameStack'] ): + baseLayoutInfo += "// {0}\n// {1}\n".format( name, file ) + if '*LayerFiles' in variables.layerVariables[0].keys(): + for file, name in zip( variables.layerVariables[0]['*LayerFiles'], variables.layerVariables[0]['*NameStack'] ): + defaultLayerInfo += "// {0}\n// {1}\n".format( name, file ) + if '*LayerFiles' in variables.layerVariables[1].keys(): + for layer in range( 1, len( variables.layerVariables ) ): + partialLayersInfo += "// Layer {0}\n".format( layer ) + if len( variables.layerVariables[ layer ]['*LayerFiles'] ) > 0: + for file, name in zip( variables.layerVariables[ layer ]['*LayerFiles'], variables.layerVariables[ layer ]['*NameStack'] ): + partialLayersInfo += "// {0}\n// {1}\n".format( name, file ) + + + ## Information ## + self.fill_dict['Information'] = "// This file was generated by the kll compiler, DO NOT EDIT.\n" + self.fill_dict['Information'] += "// Generation Date: {0}\n".format( date.today() ) + self.fill_dict['Information'] += "// KLL Backend: {0}\n".format( "kiibohd" ) + self.fill_dict['Information'] += "// KLL Git Rev: {0}\n".format( gitRev ) + self.fill_dict['Information'] += "// KLL Git Changes:{0}".format( gitChangesStr ) + self.fill_dict['Information'] += "// Compiler arguments:\n{0}".format( compilerArgs ) + self.fill_dict['Information'] += "//\n" + self.fill_dict['Information'] += "// - Base Layer -\n{0}".format( baseLayoutInfo ) + self.fill_dict['Information'] += "// - Default Layer -\n{0}".format( defaultLayerInfo ) + self.fill_dict['Information'] += "// - Partial Layers -\n{0}".format( partialLayersInfo ) + + + ## Variable Information ## + self.fill_dict['VariableInformation'] = "" + + # Iterate through the variables, output, and indicate the last file that modified it's value + # Output separate tables per file, per table and overall + # TODO + + + ## Defines ## + self.fill_dict['Defines'] = "" + + # Iterate through defines and lookup the variables + for define in variables.defines.keys(): + if define in variables.overallVariables.keys(): + self.fill_dict['Defines'] += "\n#define {0} {1}".format( variables.defines[ define ], variables.overallVariables[ define ] ) + else: + print( "{0} '{1}' not defined...".format( WARNING, define ) ) + + ## Capabilities ## self.fill_dict['CapabilitiesList'] = "const Capability CapabilitiesList[] = {\n" @@ -89,6 +171,12 @@ class Backend: # Add the result macro capability index guide (including capability arguments) # See kiibohd controller Macros/PartialMap/kll.h for exact formatting details for sequence in range( 0, len( macros.resultsIndexSorted[ result ] ) ): + # If the sequence is longer than 1, prepend a sequence spacer + # Needed for USB behaviour, otherwise, repeated keys will not work + if sequence > 0: + # , , + self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.usbCodeCapability() ) ) + # For each combo in the sequence, add the length of the combo self.fill_dict['ResultMacros'] += "{0}, ".format( len( macros.resultsIndexSorted[ result ][ sequence ] ) ) @@ -101,7 +189,13 @@ class Backend: # Add each of the arguments of the capability for arg in range( 0, len( resultItem[1] ) ): - self.fill_dict['ResultMacros'] += "0x{0:02X}, ".format( resultItem[1][ arg ] ) + self.fill_dict['ResultMacros'] += "{0}, ".format( resultItem[1][ arg ] ) + + # If sequence is longer than 1, append a sequence spacer at the end of the sequence + # Required by USB to end at sequence without holding the key down + if len( macros.resultsIndexSorted[ result ] ) > 1: + # , , + self.fill_dict['ResultMacros'] += "1, {0}, 0x00, ".format( capabilities.getIndex( self.usbCodeCapability() ) ) # Add list ending 0 and end of list self.fill_dict['ResultMacros'] += "0 };\n" @@ -109,7 +203,7 @@ class Backend: ## Result Macro List ## - self.fill_dict['ResultMacroList'] = "ResultMacro ResultMacroList[] = {\n" + self.fill_dict['ResultMacroList'] = "const ResultMacro ResultMacroList[] = {\n" # Iterate through each of the result macros for result in range( 0, len( macros.resultsIndexSorted ) ): @@ -117,6 +211,10 @@ class Backend: self.fill_dict['ResultMacroList'] += "};" + ## Result Macro Record ## + self.fill_dict['ResultMacroRecord'] = "ResultMacroRecord ResultMacroRecordList[ ResultMacroNum ];" + + ## Trigger Macros ## self.fill_dict['TriggerMacros'] = "" @@ -144,7 +242,7 @@ class Backend: ## Trigger Macro List ## - self.fill_dict['TriggerMacroList'] = "TriggerMacro TriggerMacroList[] = {\n" + self.fill_dict['TriggerMacroList'] = "const TriggerMacro TriggerMacroList[] = {\n" # Iterate through each of the trigger macros for trigger in range( 0, len( macros.triggersIndexSorted ) ): @@ -153,16 +251,20 @@ class Backend: self.fill_dict['TriggerMacroList'] += "};" + ## Trigger Macro Record ## + self.fill_dict['TriggerMacroRecord'] = "TriggerMacroRecord TriggerMacroRecordList[ TriggerMacroNum ];" + + ## Max Scan Code ## self.fill_dict['MaxScanCode'] = "#define MaxScanCode 0x{0:X}".format( macros.overallMaxScanCode ) ## Default Layer and Default Layer Scan Map ## self.fill_dict['DefaultLayerTriggerList'] = "" - self.fill_dict['DefaultLayerScanMap'] = "const unsigned int *default_scanMap[] = {\n" + self.fill_dict['DefaultLayerScanMap'] = "const nat_ptr_t *default_scanMap[] = {\n" # Iterate over triggerList and generate a C trigger array for the default map and default map array - for triggerList in range( 0, len( macros.triggerList[ 0 ] ) ): + for triggerList in range( macros.firstScanCode[ 0 ], len( macros.triggerList[ 0 ] ) ): # Generate ScanCode index and triggerList length self.fill_dict['DefaultLayerTriggerList'] += "Define_TL( default, 0x{0:02X} ) = {{ {1}".format( triggerList, len( macros.triggerList[ 0 ][ triggerList ] ) ) @@ -187,19 +289,19 @@ class Backend: for layer in range( 1, len( macros.triggerList ) ): # Prepare each layer self.fill_dict['PartialLayerScanMaps'] += "// Partial Layer {0}\n".format( layer ) - self.fill_dict['PartialLayerScanMaps'] += "const unsigned int *layer{0}_scanMap[] = {{\n".format( layer ) + self.fill_dict['PartialLayerScanMaps'] += "const nat_ptr_t *layer{0}_scanMap[] = {{\n".format( layer ) self.fill_dict['PartialLayerTriggerLists'] += "// Partial Layer {0}\n".format( layer ) # Iterate over triggerList and generate a C trigger array for the layer - for triggerList in range( 0, len( macros.triggerList[ layer ] ) ): + for triggerList in range( macros.firstScanCode[ layer ], len( macros.triggerList[ layer ] ) ): # Generate ScanCode index and triggerList length - self.fill_dict['PartialLayerTriggerLists'] += "Define_TL( layer{0}, 0x{1:02X} ) = {{ {2}".format( layer, triggerList, len( macros.triggerList[ 0 ][ triggerList ] ) ) + self.fill_dict['PartialLayerTriggerLists'] += "Define_TL( layer{0}, 0x{1:02X} ) = {{ {2}".format( layer, triggerList, len( macros.triggerList[ layer ][ triggerList ] ) ) # Add scanCode trigger list to Default Layer Scan Map self.fill_dict['PartialLayerScanMaps'] += "layer{0}_tl_0x{1:02X}, ".format( layer, triggerList ) # Add each item of the trigger list - for trigger in macros.triggerList[ 0 ][ triggerList ]: + for trigger in macros.triggerList[ layer ][ triggerList ]: self.fill_dict['PartialLayerTriggerLists'] += ", {0}".format( trigger ) self.fill_dict['PartialLayerTriggerLists'] += " };\n" @@ -211,23 +313,36 @@ class Backend: ## Layer Index List ## - self.fill_dict['LayerIndexList'] = "Layer LayerIndex[] = {\n" + self.fill_dict['LayerIndexList'] = "const Layer LayerIndex[] = {\n" # Iterate over each layer, adding it to the list for layer in range( 0, len( macros.triggerList ) ): + # Lookup first scancode in map + firstScanCode = macros.firstScanCode[ layer ] + + # Generate stacked name + stackName = "" + if '*NameStack' in variables.layerVariables[ layer ].keys(): + for name in range( 0, len( variables.layerVariables[ layer ]['*NameStack'] ) ): + stackName += "{0} + ".format( variables.layerVariables[ layer ]['*NameStack'][ name ] ) + stackName = stackName[:-3] + # Default map is a special case, always the first index - # TODO Fix names if layer == 0: - self.fill_dict['LayerIndexList'] += '\tLayer_IN( default_scanMap, "DefaultMap" ),\n' + self.fill_dict['LayerIndexList'] += '\tLayer_IN( default_scanMap, "D: {1}", 0x{0:02X} ),\n'.format( firstScanCode, stackName ) else: - self.fill_dict['LayerIndexList'] += '\tLayer_IN( layer{0}_scanMap, "Layer {0}" ),\n'.format( layer ) + self.fill_dict['LayerIndexList'] += '\tLayer_IN( layer{0}_scanMap, "{0}: {2}", 0x{1:02X} ),\n'.format( layer, firstScanCode, stackName ) self.fill_dict['LayerIndexList'] += "};" + ## Layer State ## + self.fill_dict['LayerState'] = "uint8_t LayerState[ LayerNum ];" + + # Generates the output keymap with fill tags filled - def generate( self, filepath ): + def generate( self, outputPath, definesOutputPath ): # Process each line of the template, outputting to the target path - with open( filepath, 'w' ) as outputFile: + with open( outputPath, 'w' ) as outputFile: with open( self.templatePath, 'r' ) as templateFile: for line in templateFile: # TODO Support multiple replacements per line @@ -243,3 +358,20 @@ class Backend: else: outputFile.write( line ) + # Process each line of the defines template, outputting to the target path + with open( definesOutputPath, 'w' ) as outputFile: + with open( self.definesTemplatePath, 'r' ) as templateFile: + for line in templateFile: + # TODO Support multiple replacements per line + # TODO Support replacement with other text inline + match = re.findall( '<\|([^|>]+)\|>', line ) + + # If match, replace with processed variable + if match: + outputFile.write( self.fill_dict[ match[ 0 ] ] ) + outputFile.write("\n") + + # Otherwise, just append template to output file + else: + outputFile.write( line ) +