changeset 47:a92bdf81be01

Adding support for Interconnect Nodes - Required changing the ScanCode node datastructure - Interconnect Id's must be stored until the end as it's not possible to calculate the max per node ScanCode until after all the assignments are complete - Should make future additions more straight-forward (that require per ScanCode information to be stored)
author Jacob Alexander <haata@kiibohd.com>
date Sat, 15 Aug 2015 21:29:18 -0700
parents 32046b29c58c
children c566d281b169
files backends/kiibohd.py kll.py kll_lib/containers.py templates/kiibohdDefs.h templates/kiibohdKeymap.h
diffstat 5 files changed, 157 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/backends/kiibohd.py	Sun Aug 02 13:42:38 2015 -0700
+++ b/backends/kiibohd.py	Sat Aug 15 21:29:18 2015 -0700
@@ -219,13 +219,17 @@
 
 			# Add the trigger macro scan code guide
 			# See kiibohd controller Macros/PartialMap/kll.h for exact formatting details
-			for sequence in range( 0, len( macros.triggersIndexSorted[ trigger ][ 0 ] ) ):
+			for sequence in range( 0, len( macros.triggersIndexSorted[ trigger ][0] ) ):
 				# For each combo in the sequence, add the length of the combo
 				self.fill_dict['TriggerMacros'] += "{0}, ".format( len( macros.triggersIndexSorted[ trigger ][0][ sequence ] ) )
 
 				# For each combo, add the key type, key state and scan code
-				for combo in range( 0, len( macros.triggersIndexSorted[ trigger ][ 0 ][ sequence ] ) ):
-					triggerItem = macros.triggersIndexSorted[ trigger ][ 0 ][ sequence ][ combo ]
+				for combo in range( 0, len( macros.triggersIndexSorted[ trigger ][0][ sequence ] ) ):
+					triggerItemId = macros.triggersIndexSorted[ trigger ][0][ sequence ][ combo ]
+
+					# Lookup triggerItem in ScanCodeStore
+					triggerItemObj = macros.scanCodeStore[ triggerItemId ]
+					triggerItem = triggerItemObj.offset( macros.interconnectOffset )
 
 					# TODO Add support for Analog keys
 					# TODO Add support for LED states
@@ -254,21 +258,32 @@
 		self.fill_dict['MaxScanCode'] = "#define MaxScanCode 0x{0:X}".format( macros.overallMaxScanCode )
 
 
+		## Interconnect ScanCode Offset List ##
+		self.fill_dict['ScanCodeInterconnectOffsetList'] = "const uint8_t InterconnectOffsetList[] = {\n"
+		for offset in range( 0, len( macros.interconnectOffset ) ):
+			self.fill_dict['ScanCodeInterconnectOffsetList'] += "\t0x{0:02X},\n".format( macros.interconnectOffset[ offset ] )
+		self.fill_dict['ScanCodeInterconnectOffsetList'] += "};"
+
+
+		## Max Interconnect Nodes ##
+		self.fill_dict['InterconnectNodeMax'] = "#define InterconnectNodeMax 0x{0:X}\n".format( len( macros.interconnectOffset ) )
+
+
 		## Default Layer and Default Layer Scan Map ##
 		self.fill_dict['DefaultLayerTriggerList'] = ""
 		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( macros.firstScanCode[ 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 ] ) )
+			self.fill_dict['DefaultLayerTriggerList'] += "Define_TL( default, 0x{0:02X} ) = {{ {1}".format( triggerList, len( macros.triggerList[0][ triggerList ] ) )
 
 			# Add scanCode trigger list to Default Layer Scan Map
 			self.fill_dict['DefaultLayerScanMap'] += "default_tl_0x{0:02X}, ".format( triggerList )
 
 			# Add each item of the trigger list
-			for trigger in macros.triggerList[ 0 ][ triggerList ]:
-				self.fill_dict['DefaultLayerTriggerList'] += ", {0}".format( trigger )
+			for triggerItem in macros.triggerList[0][ triggerList ]:
+				self.fill_dict['DefaultLayerTriggerList'] += ", {0}".format( triggerItem )
 
 			self.fill_dict['DefaultLayerTriggerList'] += " };\n"
 		self.fill_dict['DefaultLayerTriggerList'] = self.fill_dict['DefaultLayerTriggerList'][:-1] # Remove last newline
--- a/kll.py	Sun Aug 02 13:42:38 2015 -0700
+++ b/kll.py	Sat Aug 15 21:29:18 2015 -0700
@@ -478,6 +478,15 @@
 	return items
 
 
+# Convert tuple of tuples to list of lists
+def listit( t ):
+	return list( map( listit, t ) ) if isinstance( t, ( list, tuple ) ) else t
+
+# Convert list of lists to tuple of tuples
+def tupleit( t ):
+	return tuple( map( tupleit, t ) ) if isinstance( t, ( tuple, list ) ) else t
+
+
  ## Evaluation Rules
 
 def eval_scanCode( triggers, operator, results ):
@@ -486,8 +495,26 @@
 	triggers = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in triggers )
 	results  = tuple( tuple( tuple( sequence ) for sequence in variant ) for variant in results )
 
+	# Lookup interconnect id (Current file scope)
+	# Default to 0 if not specified
+	if 'ConnectId' not in variables_dict.overallVariables.keys():
+		id_num = 0
+	else:
+		id_num = int( variables_dict.overallVariables['ConnectId'] )
+
 	# Iterate over all combinations of triggers and results
-	for trigger in triggers:
+	for sequence in triggers:
+		# Convert tuple of tuples to list of lists so each element can be modified
+		trigger = listit( sequence )
+
+		# Create ScanCode entries for trigger
+		for seq_index, combo in enumerate( sequence ):
+			for com_index, scancode in enumerate( combo ):
+				trigger[ seq_index ][ com_index ] = macros_map.scanCodeStore.append( ScanCode( scancode, id_num ) )
+
+		# Convert back to a tuple of tuples
+		trigger = tupleit( trigger )
+
 		for result in results:
 			# Append Case
 			if operator == ":+":
--- a/kll_lib/containers.py	Sun Aug 02 13:42:38 2015 -0700
+++ b/kll_lib/containers.py	Sat Aug 15 21:29:18 2015 -0700
@@ -34,6 +34,67 @@
 
  ## Containers
 
+class ScanCode:
+	# Container for ScanCodes
+	#
+	# scancode        - Non-interconnect adjusted scan code
+	# interconnect_id - Unique id for the interconnect node
+	def __init__( self, scancode, interconnect_id ):
+		self.scancode = scancode
+		self.interconnect_id = interconnect_id
+
+	def __eq__( self, other ):
+		return self.dict() == other.dict()
+
+	def __repr__( self ):
+		return repr( self.dict() )
+
+	def dict( self ):
+		return {
+			'ScanCode' : self.scancode,
+			'Id'       : self.interconnect_id,
+		}
+
+	# Calculate the actual scancode using the offset list
+	def offset( self, offsetList ):
+		if self.interconnect_id > 0:
+			return self.scancode + offsetList[ self.interconnect_id - 1 ]
+		else:
+			return self.scancode
+
+
+class ScanCodeStore:
+	# Unique lookup for ScanCodes
+	def __init__( self ):
+		self.scancodes = []
+
+	def __getitem__( self, name ):
+		# First check if this is a ScanCode object
+		if isinstance( name, ScanCode ):
+			# Do a reverse lookup
+			for idx, scancode in enumerate( self.scancodes ):
+				if scancode == name:
+					return idx
+
+			# Could not find scancode
+			return None
+
+		# Return scancode using unique id
+		return self.scancodes[ name ]
+
+	# Attempt add ScanCode to list, return unique id
+	def append( self, new_scancode ):
+		# Iterate through list to make sure this is a unique ScanCode
+		for idx, scancode in enumerate( self.scancodes ):
+			if new_scancode == scancode:
+				return idx
+
+		# Unique entry, add to the list
+		self.scancodes.append( new_scancode )
+
+		return len( self.scancodes ) - 1
+
+
 class Capabilities:
 	# Container for capabilities dictionary and convenience functions
 	def __init__( self ):
@@ -87,6 +148,9 @@
 		# Default layer (0)
 		self.layer = 0
 
+		# Unique ScanCode Hash Id Lookup
+		self.scanCodeStore = ScanCodeStore()
+
 		# Macro Storage
 		self.macros = [ dict() ]
 
@@ -102,6 +166,7 @@
 		self.triggerList = []
 		self.maxScanCode = []
 		self.firstScanCode = []
+		self.interconnectOffset = []
 
 		# USBCode Assignment Cache
 		self.assignmentCache = []
@@ -199,6 +264,7 @@
 	def generate( self ):
 		self.generateIndices()
 		self.sortIndexLists()
+		self.generateOffsetTable()
 		self.generateTriggerLists()
 
 	# Generates Index of Results and Triggers
@@ -229,6 +295,34 @@
 		for trigger in self.triggersIndex.keys():
 			self.triggersIndexSorted[ self.triggersIndex[ trigger ] ] = trigger
 
+	# Generates list of offsets for each of the interconnect ids
+	def generateOffsetTable( self ):
+		idMaxScanCode = [ 0 ]
+
+		# Iterate over each layer to get list of max scancodes associated with each interconnect id
+		for layer in range( 0, len( self.macros ) ):
+			# Iterate through each trigger/sequence in the layer
+			for sequence in self.macros[ layer ].keys():
+				# Iterate over the trigger to locate the ScanCodes
+				for combo in sequence:
+					# Iterate over each scancode id in the combo
+					for scancode_id in combo:
+						# Lookup ScanCode
+						scancode_obj = self.scanCodeStore[ scancode_id ]
+
+						# Extend list if not large enough
+						if scancode_obj.interconnect_id >= len( idMaxScanCode ):
+							idMaxScanCode.extend( [ 0 ] * ( scancode_obj.interconnect_id - len( idMaxScanCode ) + 1 ) )
+
+						# Determine if the max seen id for this interconnect id
+						if scancode_obj.scancode > idMaxScanCode[ scancode_obj.interconnect_id ]:
+							idMaxScanCode[ scancode_obj.interconnect_id ] = scancode_obj.scancode
+
+		# Generate interconnect offsets
+		self.interconnectOffset = [ idMaxScanCode[0] + 1 ]
+		for index in range( 1, len( idMaxScanCode ) ):
+			self.interconnectOffset.append( self.interconnectOffset[ index - 1 ] + idMaxScanCode[ index ] )
+
 	# Generates Trigger Lists per layer using index lists
 	def generateTriggerLists( self ):
 		for layer in range( 0, len( self.macros ) ):
@@ -248,7 +342,8 @@
 
 					# Iterate over the trigger to locate the ScanCodes
 					for sequence in trigger:
-						for combo in sequence:
+						for combo_id in sequence:
+							combo = self.scanCodeStore[ combo_id ].offset( self.interconnectOffset )
 							# Append triggerIndex for each found scanCode of the Trigger List
 							# Do not re-add if triggerIndex is already in the Trigger List
 							if not triggerIndex in self.triggerList[ layer ][ combo ]:
--- a/templates/kiibohdDefs.h	Sun Aug 02 13:42:38 2015 -0700
+++ b/templates/kiibohdDefs.h	Sat Aug 15 21:29:18 2015 -0700
@@ -25,5 +25,9 @@
 
 
 // ----- Defines -----
+
+// -- Interconnect Node Maximum --
+<|InterconnectNodeMax|>
+
 <|Defines|>
 
--- a/templates/kiibohdKeymap.h	Sun Aug 02 13:42:38 2015 -0700
+++ b/templates/kiibohdKeymap.h	Sat Aug 15 21:29:18 2015 -0700
@@ -91,6 +91,13 @@
 <|PartialLayerTriggerLists|>
 
 
+// -- ScanCode Offset Map
+// Maps interconnect ids to scancode offsets
+//
+// Only used for keyboards with an interconnect
+<|ScanCodeInterconnectOffsetList|>
+
+
 // -- ScanCode Indexed Maps
 // Maps to a trigger list of macro pointers
 //                 _