コード例 #1
0
ファイル: matrix_scan.c プロジェクト: nlf/controller
// Setup GPIO pins for matrix scanning
void Matrix_setup()
{
	// Register Matrix CLI dictionary
	CLI_registerDictionary( matrixCLIDict, matrixCLIDictName );

	info_msg("Columns:  ");
	printHex( Matrix_colsNum );

	// Setup Strobe Pins
	for ( uint8_t pin = 0; pin < Matrix_colsNum; pin++ )
	{
		Matrix_pin( Matrix_cols[ pin ], Type_StrobeSetup );
	}

	print( NL );
	info_msg("Rows:     ");
	printHex( Matrix_rowsNum );

	// Setup Sense Pins
	for ( uint8_t pin = 0; pin < Matrix_rowsNum; pin++ )
	{
		Matrix_pin( Matrix_rows[ pin ], Type_SenseSetup );
	}

	print( NL );
	info_msg("Max Keys: ");
	printHex( Matrix_maxKeys );
	print( NL );

	// Clear out Debounce Array
	for ( uint8_t item = 0; item < Matrix_maxKeys; item++ )
	{
		Matrix_scanArray[ item ].prevState        = KeyState_Off;
		Matrix_scanArray[ item ].curState         = KeyState_Off;
		Matrix_scanArray[ item ].activeCount      = 0;
		Matrix_scanArray[ item ].inactiveCount    = DebounceDivThreshold_define; // Start at 'off' steady state
		Matrix_scanArray[ item ].prevDecisionTime = 0;
		#ifdef GHOSTING_MATRIX
		Matrix_ghostArray[ item ].prev            = KeyState_Off;
		Matrix_ghostArray[ item ].cur             = KeyState_Off;
		Matrix_ghostArray[ item ].saved           = KeyState_Off;
		#endif
	}

	// Clear scan stats counters
	matrixMaxScans  = 0;
	matrixPrevScans = 0;
}
コード例 #2
0
void CustomAction_gameLayer_capability( uint8_t state, uint8_t stateType, uint8_t *args )
{
	// Only use capability on press
	// TODO Analog
	// XXX Could also be on release, but that's sorta dumb -HaaTa
	if ( stateType == 0x00 && state != 0x01 ) // All normal key conditions except press
		return;

	gameLed ^= 1;
	Matrix_pin(ledFn, gameLed ? Type_StrobeOff : Type_StrobeOn);
	Macro_layerState( state, stateType, 2, 0x04 );
}
コード例 #3
0
// Setup
inline void Scan_setup()
{
	// Register Scan CLI dictionary
	CLI_registerDictionary( scanCLIDict, scanCLIDictName );

	// Setup GPIO pins for matrix scanning
	Matrix_setup();

	Matrix_pin(ledCaps, Type_StrobeSetup);
	Matrix_pin(ledCaps, Type_StrobeOn);
	Matrix_pin(ledFn, Type_StrobeSetup);
	Matrix_pin(ledFn, Type_StrobeOn);
	Matrix_pin(ledNum, Type_StrobeSetup);
	Matrix_pin(ledNum, Type_StrobeOn);

	// Reset scan count
	Scan_scanCount = 0;
}
コード例 #4
0
// Scan the matrix for keypresses
// 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 )
	{
		matrixPrevScans = matrixCurScans;
		matrixCurScans = 0;
	}
	else
	{
		matrixCurScans++;
	}

	// Read systick for event scheduling
	uint8_t currentTime = (uint8_t)systick_millis_count;

	// For each strobe, scan each of the sense pins
	for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ )
	{
		#ifdef STROBE_DELAY
		uint32_t start = micros();
		while ((micros() - start) < STROBE_DELAY);
		#endif

		// Strobe Pin
		Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOn );

		#ifdef STROBE_DELAY
		start = micros();
		while ((micros() - start) < STROBE_DELAY);
		#endif

		// Scan each of the sense pins
		for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
		{
			// Key position
			uint8_t key = Matrix_colsNum * sense + strobe;
			KeyState *state = &Matrix_scanArray[ key ];

			// If first scan, reset state
			if ( scanNum == 0 )
			{
				// Set previous state, and reset current state
				state->prevState = state->curState;
				state->curState  = KeyState_Invalid;
			}

			// Handle USB LEDs
			int ledOn = 0;
			if ( sense == 11 )
			{
				switch ( strobe )
				{
				case 0:
					ledOn = USBKeys_LEDs & 0x1;
					break;

				case 1:
					ledOn = USBKeys_LEDs & 0x2;
					break;

				case 2:
					ledOn = USBKeys_LEDs & 0x4;
					break;

				default:
					break;
				}
			}

			// 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
			if ( Matrix_pin( Matrix_rows[ sense ], Type_Sense ) || ledOn)
			{
				// Only update if not going to wrap around
				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 < DebounceDivThreshold_define ) state->inactiveCount += 1;
				state->activeCount >>= 1;
			}

			// Check for state change if it hasn't been set
			// But only if enough time has passed since last state change
			// Only check if the minimum number of scans has been met
			//   the current state is invalid
			//   and either active or inactive count is over the debounce threshold
			if ( state->curState == KeyState_Invalid )
			{
				// Determine time since last decision
				uint8_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 < MinDebounceTime_define )
						{
							//warn_print("FAST Release stopped");
							state->curState = state->prevState;
							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 < MinDebounceTime_define )
						{
							//warn_print("FAST Press stopped");
							state->curState = state->prevState;
							continue;
						}

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

				case KeyState_Invalid:
				default:
					erro_print("Matrix scan bug!! Report me!");
					break;
				}

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

				// Send keystate to macro module
				#ifndef GHOSTING_MATRIX
				Macro_keyState( key, state->curState );
				#endif

				// 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 )
					{
						printHex( key );
						print(" ");
					}
					// State transition debug output
					else if ( matrixDebugMode == 2 )
					{
						printHex( key );
						Matrix_keyPositionDebug( state->curState );
						print(" ");
					}
				}
			}
		}

		// Unstrobe Pin
		Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOff );
	}