Ejemplo n.º 1
0
void cliFunc_current( char* args )
{
	print( NL );
	info_msg("Current available: ");
	printInt16( Output_current_available() );
	print(" mA");
}
Ejemplo n.º 2
0
void cliFunc_macroList( char* args )
{
	// Show pending key events
	print( NL );
	info_msg("Pending Key Events: ");
	printInt16( (uint16_t)macroTriggerEventBufferSize );
	print(" : ");
	for ( var_uint_t key = 0; key < macroTriggerEventBufferSize; key++ )
	{
		printHex( macroTriggerEventBuffer[ key ].index );
		print(" ");
	}

	// Show pending trigger macros
	print( NL );
	info_msg("Pending Trigger Macros: ");
	printInt16( (uint16_t)macroTriggerMacroPendingListSize );
	print(" : ");
	for ( var_uint_t macro = 0; macro < macroTriggerMacroPendingListSize; macro++ )
	{
		printHex( macroTriggerMacroPendingList[ macro ] );
		print(" ");
	}

	// Show pending result macros
	print( NL );
	info_msg("Pending Result Macros: ");
	printInt16( (uint16_t)macroResultMacroPendingList.size );
	print(" : ");
	for ( var_uint_t macro = 0; macro < macroResultMacroPendingList.size; macro++ )
	{
		printHex( macroResultMacroPendingList.data[ macro ].index );
		print(" ");
	}

	// Show available trigger macro indices
	print( NL );
	info_msg("Trigger Macros Range: T0 -> T");
	printInt16( (uint16_t)TriggerMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)

	// Show available result macro indices
	print( NL );
	info_msg("Result  Macros Range: R0 -> R");
	printInt16( (uint16_t)ResultMacroNum - 1 ); // Hopefully large enough :P (can't assume 32-bit)

	// Show Trigger to Result Macro Links
	print( NL );
	info_msg("Trigger : Result Macro Pairs");
	for ( var_uint_t macro = 0; macro < TriggerMacroNum; macro++ )
	{
		print( NL );
		print("\tT");
		printInt16( (uint16_t)macro ); // Hopefully large enough :P (can't assume 32-bit)
		print(" : R");
		printInt16( (uint16_t)TriggerMacroList[ macro ].result ); // Hopefully large enough :P (can't assume 32-bit)
	}
}
Ejemplo n.º 3
0
void cliFunc_usbInitTime( char* args )
{
	// Calculate overall USB initialization time
	// XXX A protocol analyzer will be more accurate, however, this is built-in and easier to collect data
	print(NL);
	info_msg("USB Init Time: ");
	printInt32( USBInit_TimeEnd - USBInit_TimeStart );
	print(" ms - ");
	printInt16( USBInit_Ticks );
	print(" ticks");
}
Ejemplo n.º 4
0
// Update layer state
// States:
//   * 0x00 - Off
//   * 0x01 - Activate
//   * 0x02 - On
//   * 0x03 - Deactivate
void Macro_layerState( uint16_t layerIndex, uint8_t state )
{
	// Lookup done based on size of layerIndex
	uint8_t index = 0;
	TriggerType type = TriggerType_Layer1;

	// Only add to macro trigger list if one of three states
	// Mask around Shift/Latch/Lock state
	switch ( state & ScheduleType_D )
	{
	case ScheduleType_A:  // Activate
	case ScheduleType_On: // On
	case ScheduleType_D:  // Deactivate
		// Check if layer is out of range
		if ( layerIndex > LayerNum_KLL )
		{
			warn_msg("LayerIndex is out of range/not defined: ");
			printInt16( layerIndex );
			print( NL );
			return;
		}

		// Determine which type
		if ( layerIndex < 256 )
		{
			index = layerIndex;
		}
		else if ( layerIndex < 512 )
		{
			index = layerIndex - 256;
			type = TriggerType_Layer2;
		}
		else if ( layerIndex < 768 )
		{
			index = layerIndex - 512;
			type = TriggerType_Layer3;
		}
		else if ( layerIndex < 1024 )
		{
			index = layerIndex - 768;
			type = TriggerType_Layer4;
		}

		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].index = index;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].state = state;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].type  = type;
		macroTriggerEventBufferSize++;
		break;
	}
}
Ejemplo n.º 5
0
// Update animation state
// States:
//   * 0x00 - Off
//   * 0x06 - Done
//   * 0x07 - Repeat
void Macro_animationState( uint16_t animationIndex, uint8_t state )
{
	// Lookup done based on size of layerIndex
	uint8_t index = 0;
	TriggerType type = TriggerType_Animation1;

	// Only add to macro trigger list if one of three states
	switch ( state )
	{
	case ScheduleType_Done:   // Activate
	case ScheduleType_Repeat: // On
		// Check if animation index is out of range
		if ( animationIndex > AnimationNum_KLL )
		{
			warn_msg("AnimationIndex is out of range/not defined: ");
			printInt16( animationIndex );
			print( NL );
			return;
		}

		// Determine which type
		if ( animationIndex < 256 )
		{
			index = animationIndex;
		}
		else if ( animationIndex < 512 )
		{
			index = animationIndex - 256;
			type = TriggerType_Animation2;
		}
		else if ( animationIndex < 768 )
		{
			index = animationIndex - 512;
			type = TriggerType_Animation3;
		}
		else if ( animationIndex < 1024 )
		{
			index = animationIndex - 768;
			type = TriggerType_Animation4;
		}

		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].index = index;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].state = state;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].type  = type;
		macroTriggerEventBufferSize++;
		break;
	}
}
Ejemplo n.º 6
0
// Update Time State trigger
// Only valid with Sleep/Resume and Inactive/Active triggers
// States:
//   * 0x00 - Off
//   * 0x01 - Activate
//   * 0x02 - On
//   * 0x03 - Deactivate
void Macro_timeState( uint8_t type, uint16_t cur_time, uint8_t state )
{
	// Make sure this is a valid trigger type
	switch ( type )
	{
	case TriggerType_Sleep1:
	case TriggerType_Resume1:
	case TriggerType_Inactive1:
	case TriggerType_Active1:
		break;

	// Ignore if not the correct type
	default:
		warn_msg("Invalid time state trigger update: ");
		printHex( type );
		print(NL);
		return;
	}

	// cur_time is controlled by the caller
	// When this function called the trigger is active
	if ( cur_time > 0xFF )
	{
		warn_msg("Only 255 time instances are accepted for a time state trigger: ");
		printInt16( cur_time );
		print(NL);
		return;
	}
	uint8_t index = cur_time;

	// Only add to macro trigger list if one of three states
	switch ( state )
	{
	case ScheduleType_A:  // Activate
	case ScheduleType_On: // On
	case ScheduleType_D:  // Deactivate
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].index = index;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].state = state;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].type  = type;
		macroTriggerEventBufferSize++;
		break;
	}
}
Ejemplo n.º 7
0
void cliFunc_idle( char* args )
{
	print( NL );

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

	// Set Idle count
	if ( arg1Ptr[0] != '\0' )
	{
		uint8_t idle = (uint8_t)numToInt( arg1Ptr );
		USBKeys_Idle_Config = idle;
	}

	// Show Idle count
	info_msg("USB Idle Config: ");
	printInt16( 4 * USBKeys_Idle_Config );
	print(" ms - ");
	printInt8( USBKeys_Idle_Config );
}
Ejemplo n.º 8
0
// Macro Processing Loop, called from the periodic execution thread
// Called once per USB buffer send
void Macro_periodic()
{
	// Latency measurement
	Latency_start_time( macroLatencyResource );

#if defined(ConnectEnabled_define)
	// Only compile in if a Connect node module is available
	// If this is a interconnect slave node, send all scancodes to master node
	if ( !Connect_master )
	{
		if ( macroTriggerEventBufferSize > 0 )
		{
			Connect_send_ScanCode( Connect_id, macroTriggerEventBuffer, macroTriggerEventBufferSize );
			macroTriggerEventBufferSize = 0;
		}
		return;
	}
#endif

#if defined(ConnectEnabled_define) || defined(PressReleaseCache_define)
#if defined(ConnectEnabled_define)
	// Check if there are any ScanCodes in the interconnect cache to process
	if ( Connect_master && macroInterconnectCacheSize > 0 )
#endif
	{
		// Iterate over all the cache ScanCodes
		uint8_t currentInterconnectCacheSize = macroInterconnectCacheSize;
		macroInterconnectCacheSize = 0;
		for ( uint8_t c = 0; c < currentInterconnectCacheSize; c++ )
		{
			// Add to the trigger list
			macroTriggerEventBuffer[ macroTriggerEventBufferSize++ ] = macroInterconnectCache[ c ];

			// TODO Handle other TriggerGuide types (e.g. analog)
			switch ( macroInterconnectCache[ c ].type )
			{
			// Normal (Press/Hold/Release)
			case TriggerType_Switch1:
			case TriggerType_Switch2:
			case TriggerType_Switch3:
			case TriggerType_Switch4:
			case TriggerType_LED1:
				// Decide what to do based on the current state
				switch ( macroInterconnectCache[ c ].state )
				{
				// Re-add to interconnect cache in hold state
				case ScheduleType_P: // Press
				//case ScheduleType_H: // Hold // XXX Why does this not work? -HaaTa
					macroInterconnectCache[ c ].state = ScheduleType_H;
					macroInterconnectCache[ macroInterconnectCacheSize++ ] = macroInterconnectCache[ c ];
					break;

				case ScheduleType_R: // Release
					break;

				// Otherwise, do not re-add
				default:
					break;
				}
				break;

			// Not implemented
			default:
				erro_msg("Interconnect Trigger Event Type - Not Implemented ");
				printInt8( macroInterconnectCache[ c ].type );
				print( NL );
				break;
			}
		}
	}
#endif
	// Macro incoming state debug
	switch ( macroDebugMode )
	{
	case 1:
	case 2:
		// Iterate over incoming triggers
		for ( uint16_t trigger = 0; trigger < macroTriggerEventBufferSize; trigger++ )
		{
			// Show debug info about incoming trigger
			Macro_showTriggerEvent( &macroTriggerEventBuffer[trigger] );
			print( NL );
		}

	case 3:
	default:
		break;
	}

	// Check macroTriggerEventBufferSize to make sure no overflow
	if ( macroTriggerEventBufferSize >= MaxScanCode_KLL )
	{
		// No scancodes defined
		if ( MaxScanCode_KLL == 0 )
		{
			warn_print("No scancodes defined! Check your BaseMap!");
		}
		// Bug!
		else
		{
			erro_msg("Macro Trigger Event Overflow! Serious Bug! ");
			printInt16( macroTriggerEventBufferSize );
			print( NL );
			macroTriggerEventBufferSize = 0;
		}
	}

	// If the pause flag is set, only process if the step counter is non-zero
	if ( macroPauseMode )
	{
		if ( macroStepCounter == 0 )
			return;

		// Proceed, decrementing the step counter
		macroStepCounter--;
		dbug_print("Macro Step");
	}

	// Process Trigger Macros
	Trigger_process();


	// Store events processed
	var_uint_t macroTriggerEventBufferSize_processed = macroTriggerEventBufferSize;

	// Reset TriggerList buffer
	macroTriggerEventBufferSize = 0;


	// Process result macros
	Result_process();

	// Signal buffer that we've used it
	Scan_finishedWithMacro( macroTriggerEventBufferSize_processed );

#if defined(_host_)
	// Signal host to read layer state
	Output_callback( "layerState", "" );
#endif

	// Latency measurement
	Latency_end_time( macroLatencyResource );

	// If Macro debug mode is set, clear the USB Buffer
#if defined(Output_USBEnabled_define)
	if ( macroDebugMode == 1 || macroDebugMode == 3 )
	{
		USBKeys_primary.changed = 0;
	}
#endif
}
Ejemplo n.º 9
0
// Update the scancode key state
// States:
//   * 0x00 - Off
//   * 0x01 - Pressed
//   * 0x02 - Held
//   * 0x03 - Released
//   * 0x04 - Unpressed (this is currently ignored)
void Macro_keyState( uint16_t scanCode, uint8_t state )
{
#if defined(ConnectEnabled_define)
	// Only compile in if a Connect node module is available
	if ( !Connect_master )
	{
		// ScanCodes are only added if there was a state change (on/off)
		switch ( state )
		{
		case ScheduleType_O: // Off
		case ScheduleType_H: // Held
			return;
		}
	}
#endif

	// Lookup done based on size of scanCode
	uint8_t index = 0;
	TriggerType type = TriggerType_Switch1;

	// Only add to macro trigger list if one of three states
	switch ( state )
	{
	case ScheduleType_P: // Pressed
	case ScheduleType_H: // Held
	case ScheduleType_R: // Released
		// Check if ScanCode is out of range
		if ( scanCode > MaxScanCode_KLL )
		{
			warn_msg("ScanCode is out of range/not defined: ");
			printInt16( scanCode );
			print( NL );
			return;
		}

		// Determine which type
		if ( scanCode < 256 )
		{
			index = scanCode;
		}
		else if ( scanCode < 512 )
		{
			index = scanCode - 256;
			type = TriggerType_Switch2;
		}
		else if ( scanCode < 768 )
		{
			index = scanCode - 512;
			type = TriggerType_Switch3;
		}
		else if ( scanCode < 1024 )
		{
			index = scanCode - 768;
			type = TriggerType_Switch4;
		}

		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].index = index;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].state = state;
		macroTriggerEventBuffer[ macroTriggerEventBufferSize ].type  = type;
		macroTriggerEventBufferSize++;
		break;
	}
}
Ejemplo n.º 10
0
void macroDebugShowResult( var_uint_t index )
{
	// Only proceed if the macro exists
	if ( index >= ResultMacroNum )
		return;

	// Trigger Macro Show
	const ResultMacro *macro = &ResultMacroList[ index ];

	print( NL );
	info_msg("Result Macro Index: ");
	printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
	print( NL );

	// Read the comboLength for combo in the sequence (sequence of combos)
	var_uint_t pos = 0;
	uint8_t comboLength = macro->guide[ pos++ ];

	// Iterate through and interpret the guide
	while ( comboLength != 0 )
	{
		// Function Counter, used to keep track of the combos processed
		var_uint_t funcCount = 0;

		// Iterate through the combo
		while ( funcCount < comboLength )
		{
			// Assign TriggerGuide element (key type, state and scancode)
			ResultGuide *guide = (ResultGuide*)(&macro->guide[ pos ]);

			// Display Function Index
			printHex( guide->index );
			print("|");

			// Display Function Ptr Address
			printHex( (nat_ptr_t)CapabilitiesList[ guide->index ].func );
			print("|");

			// Display/Lookup Capability Name (utilize debug mode of capability)
			void (*capability)(TriggerMacro*, uint8_t, uint8_t, uint8_t*) = \
				(void(*)(TriggerMacro*, uint8_t, uint8_t, uint8_t*))(CapabilitiesList[ guide->index ].func);
			capability( 0, 0xFF, 0xFF, 0 );

			// Display Argument(s)
			print("(");
			for ( var_uint_t arg = 0; arg < CapabilitiesList[ guide->index ].argCount; arg++ )
			{
				// Arguments are only 8 bit values
				printHex( (&guide->args)[ arg ] );

				// Only show arg separator if there are args left
				if ( arg + 1 < CapabilitiesList[ guide->index ].argCount )
					print(",");
			}
			print(")");

			// Increment position
			pos += ResultGuideSize( guide );

			// Increment function count
			funcCount++;

			// Only show combo separator if there are combos left in the sequence element
			if ( funcCount < comboLength )
				print("+");
		}

		// Read the next comboLength
		comboLength = macro->guide[ pos++ ];

		// Only show sequence separator if there is another combo to process
		if ( comboLength != 0 )
			print(";");
	}

	/* XXX (HaaTa) Fix for ring-buffer record list
	ResultMacroRecord *record = &ResultMacroRecordList[ index ];

	// Display current position
	print( NL "Position: " );
	printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
	print(" ");
	printInt16( (uint16_t)record->prevPos );

	// Display final trigger state/type
	print( NL "Final Trigger State (State/Type): " );
	printHex( record->state );
	print("/");
	printHex( record->stateType );
	*/
}
Ejemplo n.º 11
0
void macroDebugShowTrigger( var_uint_t index )
{
	// Only proceed if the macro exists
	if ( index >= TriggerMacroNum )
		return;

	// Trigger Macro Show
	const TriggerMacro *macro = &TriggerMacroList[ index ];
	TriggerMacroRecord *record = &TriggerMacroRecordList[ index ];

	print( NL );
	info_msg("Trigger Macro Index: ");
	printInt16( (uint16_t)index ); // Hopefully large enough :P (can't assume 32-bit)
	print( NL );

	// Read the comboLength for combo in the sequence (sequence of combos)
	var_uint_t pos = 0;
	uint8_t comboLength = macro->guide[ pos ];

	// Iterate through and interpret the guide
	while ( comboLength != 0 )
	{
		// Initial position of the combo
		var_uint_t comboPos = ++pos;

		// Iterate through the combo
		while ( pos < comboLength * TriggerGuideSize + comboPos )
		{
			// Assign TriggerGuide element (key type, state and scancode)
			TriggerGuide *guide = (TriggerGuide*)(&macro->guide[ pos ]);

			// Display guide information about trigger key
			printHex( guide->scanCode );
			print("|");
			printHex( guide->type );
			print("|");
			printHex( guide->state );

			// Increment position
			pos += TriggerGuideSize;

			// Only show combo separator if there are combos left in the sequence element
			if ( pos < comboLength * TriggerGuideSize + comboPos )
				print("+");
		}

		// Read the next comboLength
		comboLength = macro->guide[ pos ];

		// Only show sequence separator if there is another combo to process
		if ( comboLength != 0 )
			print(";");
	}

	// Display current position
	print( NL "Position: " );
	printInt16( (uint16_t)record->pos ); // Hopefully large enough :P (can't assume 32-bit)
	print(" ");
	printInt16( (uint16_t)record->prevPos );

	// Display result macro index
	print( NL "Result Macro Index: " );
	printInt16( (uint16_t)macro->result ); // Hopefully large enough :P (can't assume 32-bit)

	// Display trigger macro state
	print( NL "Trigger Macro State: " );
	switch ( record->state )
	{
	case TriggerMacro_Press:        print("Press");   break;
	case TriggerMacro_Release:      print("Release"); break;
	case TriggerMacro_PressRelease: print("Press|Release"); break;
	case TriggerMacro_Waiting:      print("Waiting"); break;
	}
}
Ejemplo n.º 12
0
// Evaluate/Update TriggerMacro
TriggerMacroEval Trigger_evalTriggerMacro( var_uint_t triggerMacroIndex )
{
	// Lookup TriggerMacro
	const TriggerMacro *macro = &TriggerMacroList[ triggerMacroIndex ];
	TriggerMacroRecord *record = &TriggerMacroRecordList[ triggerMacroIndex ];

	// Check if this is a long Trigger Macro
	uint8_t long_trigger_macro = Trigger_isLongTriggerMacro( macro );

	// Long Macro
	if ( long_trigger_macro )
	{
		// Check if macro has finished and should be incremented sequence elements
		if ( record->state != TriggerMacro_Waiting )
		{
			record->prevPos = record->pos;
			record->pos = record->pos + macro->guide[ record->pos ] * TriggerGuideSize + 1;
		}

		// Current Macro position
		var_uint_t pos = record->pos;

		// Length of the combo being processed
		uint8_t comboLength = macro->guide[ pos ] * TriggerGuideSize;

		TriggerMacroVote overallVote = TriggerMacroVote_Invalid;
		// Iterate through the items in the combo, voting the on the key state
		// If any of the pressed keys do not match, fail the macro
		if ( comboLength != 0 )
		{
			overallVote |= Trigger_overallVote( macro, record, long_trigger_macro, pos );
		}

		// If this is a sequence, and have processed at least one vote already
		// then we need to keep track of releases
		if ( pos != 0 )
		{
			overallVote |= Trigger_overallVote( macro, record, long_trigger_macro, record->prevPos );
		}

		// If no pass vote was found after scanning the entire combo
		// And this is the first position in the combo, just remove it (nothing important happened)
		if ( overallVote & TriggerMacroVote_DoNothingRelease && pos == 0 )
		{
			overallVote |= TriggerMacroVote_Fail;
		}

		// Vote Debug
		switch ( voteDebugMode )
		{
		case 1:
			Trigger_showTriggerMacroVote( overallVote, long_trigger_macro );
			print(" TriggerMacroList[");
			printInt16( triggerMacroIndex );
			print("]");
			break;
		}

		// Decide new state of macro after voting
		// Fail macro, remove from pending list
		if ( overallVote & TriggerMacroVote_Fail )
		{
			return TriggerMacroEval_Remove;
		}
		// Do nothing, incorrect key is being held or released
		else if ( overallVote & TriggerMacroVote_DoNothing )
		{
			record->state = TriggerMacro_Waiting;

			// Just doing nothing :)
		}
		// If ready for release state but we get both release and the next press at the same time
		// This is unlikely, but possible
		else if ( ( overallVote & TriggerMacroVote_PassRelease ) == TriggerMacroVote_PassRelease )
		{
			record->state = TriggerMacro_PressRelease;

			// If this is the last combo in the sequence, trigger result
			if ( macro->guide[ pos + comboLength + 1 ] == 0 )
			{
				return TriggerMacroEval_DoResultAndRemove;
			}
		}
		// If ready for transition and in Press state, increment combo position
		else if ( overallVote & TriggerMacroVote_Release && record->state & TriggerMacro_Press )
		{
			record->state = TriggerMacro_Release;

			// If this is the last combo in the sequence, trigger result
			// Or, the final release of a sequence
			if ( comboLength == 0 || macro->guide[ pos + comboLength + 1 ] == 0 )
			{
				return TriggerMacroEval_DoResultAndRemove;
			}
		}
		// If passing and in Waiting state, set macro state to Press
		else if ( overallVote & TriggerMacroVote_Pass
			&& ( record->state == TriggerMacro_Waiting || record->state & TriggerMacro_Press ) )
		{
			record->state = TriggerMacro_Press;

			// If this is the last combo in the sequence, trigger result
			if ( macro->guide[ pos + comboLength + 1 ] == 0 )
			{
				return TriggerMacroEval_DoResultAndRemove;
			}
		}
	}
	// Short Macro
	else
	{
		// Current Macro position
		var_uint_t pos = record->pos;

		// Iterate through the items in the combo, voting the on the key state
		// If any of the pressed keys do not match, fail the macro
		TriggerMacroVote overallVote = Trigger_overallVote( macro, record, long_trigger_macro, pos );

		// Vote Debug
		switch ( voteDebugMode )
		{
		case 1:
			Trigger_showTriggerMacroVote( overallVote, long_trigger_macro );
			print(" TriggerMacroList[");
			printInt16( triggerMacroIndex );
			print("]");
			break;
		}

		// Decide new state of macro after voting
		// Fail macro, remove from pending list
		if ( overallVote & TriggerMacroVote_Fail )
		{
			return TriggerMacroEval_Remove;
		}
		// If passing and in Waiting state, set macro state to Press
		// And trigger result
		else if ( overallVote & TriggerMacroVote_Pass
			&& ( record->state == TriggerMacro_Waiting || record->state == TriggerMacro_Press )
		)
		{
			record->state = TriggerMacro_Press;

			// Long result macro (more than 1 combo)
			if ( Trigger_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
			{
				// Only ever trigger result once, on press
				if ( overallVote == TriggerMacroVote_Pass )
				{
					return TriggerMacroEval_DoResultAndRemove;
				}
			}
			// Short result macro
			else
			{
				// Trigger result continuously
				return TriggerMacroEval_DoResult;
			}
		}
		// Otherwise, just remove the macro on key release
		else if ( overallVote & TriggerMacroVote_Release )
		{
			// Long result macro (more than 1 combo) are ignored (only on press)
			if ( !Trigger_isLongResultMacro( &ResultMacroList[ macro->result ] ) )
			{
				record->state = TriggerMacro_Release;

				return TriggerMacroEval_DoResultAndRemove;
			}
		}

		// This is a short macro, just remove it
		// The state can be rebuilt on the next iteration
		return TriggerMacroEval_Remove;
	}

	return TriggerMacroEval_DoNothing;
}
Ejemplo n.º 13
0
// Single strobe matrix scan
// Only goes through a single strobe
// This module keeps track of the next strobe to scan
uint8_t Matrix_single_scan()
{
	// Start latency measurement
	Latency_start_time( matrixLatencyResource );


	// Read systick for event scheduling
	uint32_t currentTime = systick_millis_count;

	// Current strobe
	uint8_t strobe = matrixCurrentStrobe;

	// XXX (HaaTa)
	// Before strobing drain each sense line
	// This helps with faulty pull-up resistors (particularily with SAM4S)
	for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
	{
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveSetup, Matrix_type );
#if ScanCodeMatrixInvert_define == 2 // GPIO_Config_Pulldown
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveLow, Matrix_type );
#elif ScanCodeMatrixInvert_define == 1 // GPIO_Config_Pullup
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveHigh, Matrix_type );
#endif
		GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_ReadSetup, Matrix_type );
	}

	// Strobe Pin
	GPIO_Ctrl( Matrix_cols[ strobe ], GPIO_Type_DriveHigh, Matrix_type );

	// Used to allow the strobe signal to propagate, generally not required
	if ( strobeDelayTime > 0 )
	{
		delay_us( strobeDelayTime );
	}

	// Scan each of the sense pins
	for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
	{
		// Key position
		uint16_t key = Matrix_colsNum * sense + strobe;
#if ScanCodeRemapping_define == 1
		uint16_t key_disp = matrixScanCodeRemappingMatrix[key];
#else
		uint16_t key_disp = key + 1; // 1-indexed for reporting purposes
#endif

		// Check bounds, before attempting to scan
		// 1-indexed as ScanCode 0 is not used
		if ( key_disp > MaxScanCode_KLL || key_disp == 0 )
		{
			continue;
		}
		volatile KeyState *state = &Matrix_scanArray[ key ];

		// Signal Detected
		// Increment count and right shift opposing count
		// This means there is a maximum of scan 13 cycles on a perfect off to on transition
		//  (coming from a steady state 0xFFFF off scans)
		// Somewhat longer with switch bounciness
		// The advantage of this is that the count is ongoing and never needs to be reset
		// State still needs to be kept track of to deal with what to send to the Macro module
		// Compared against the default state value (ScanCodeMatrixInvert_define), usually 0
		if ( GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_Read, Matrix_type ) != ScanCodeMatrixInvert_define )
		{
			// Only update if not going to wrap around
			if ( state->activeCount < DebounceDivThreshold ) state->activeCount += 1;
			state->inactiveCount >>= 1;
		}
		// Signal Not Detected
		else
		{
			// Only update if not going to wrap around
			if ( state->inactiveCount < DebounceDivThreshold ) state->inactiveCount += 1;
			state->activeCount >>= 1;
		}

		// Check for state change
		// But only if:
		// 1) Enough time has passed since last state change
		// 2) Either active or inactive count is over the debounce threshold

		// Update previous state
		state->prevState = state->curState;

		// Determine time since last decision
		uint32_t lastTransition = currentTime - state->prevDecisionTime;

		// Attempt state transition
		switch ( state->prevState )
		{
		case KeyState_Press:
		case KeyState_Hold:
			if ( state->activeCount > state->inactiveCount )
			{
				state->curState = KeyState_Hold;
			}
			else
			{
				// If not enough time has passed since Hold
				// Keep previous state
				if ( lastTransition < debounceExpiryTime )
				{
					state->curState = state->prevState;
					Macro_keyState( key_disp, state->curState );
					continue;
				}

				state->curState = KeyState_Release;
			}
			break;

		case KeyState_Release:
		case KeyState_Off:
			if ( state->activeCount > state->inactiveCount )
			{
				// If not enough time has passed since Hold
				// Keep previous state
				if ( lastTransition < debounceExpiryTime )
				{
					state->curState = state->prevState;
					Macro_keyState( key_disp, state->curState );
					continue;
				}

				state->curState = KeyState_Press;
			}
			else
			{
				state->curState = KeyState_Off;
			}
			break;

		case KeyState_Invalid:
		default:
			erro_msg("Matrix scan bug!! Report me! - ");
			printHex( state->prevState );
			print(" Col: ");
			printHex( strobe );
			print(" Row: ");
			printHex( sense );
			print(" Key: ");
			printHex( key_disp );
			print( NL );
			break;
		}

		// Update decision time
		state->prevDecisionTime = currentTime;

		// Send keystate to macro module
		Macro_keyState( key_disp, state->curState );

		// Check for activity and inactivity
		if ( state->curState != KeyState_Off )
		{
			matrixStateActiveCount++;
		}
		switch ( state->curState )
		{
		case KeyState_Press:
			matrixStatePressCount++;
			break;

		case KeyState_Release:
			matrixStateReleaseCount++;
			break;

		default:
			break;
		}

		// Matrix Debug, only if there is a state change
		if ( matrixDebugMode && state->curState != state->prevState )
		{
			// Basic debug output
			if ( matrixDebugMode == 1 && state->curState == KeyState_Press )
			{
				printInt16( key_disp );
				print(":");
				printHex( key_disp );
				print(" ");
			}
			// State transition debug output
			else if ( matrixDebugMode == 2 )
			{
				printInt16( key_disp );
				Matrix_keyPositionDebug( state->curState );
				print(" ");
			}
			else if ( matrixDebugMode == 3 )
			{
				print("\033[1m");
				printInt16( key_disp );
				print("\033[0m");
				print(":");
				Matrix_keyPositionDebug( Matrix_scanArray[ key ].prevState );
				Matrix_keyPositionDebug( Matrix_scanArray[ key ].curState );
				print(" 0x");
				printHex_op( state->activeCount, 2 );
				print(" 0x");
				printHex_op( state->inactiveCount, 2 );
				print(" ");
				printInt32( lastTransition );
				print( NL );
			}

		}
	}