📄 keypad.c
字号:
// code is greater than ADC
SBYTE SB_Ret = 1;
BYTE diff;
if (B_TableCode > B_Value)
{
diff = B_TableCode - B_Value;
SB_Ret = -1;
}
else
diff = B_Value - B_TableCode;
if ( diff <= ADC_DELTA)
SB_Ret = 0;
return SB_Ret;
}
#endif //LBADC_USED
//******************************************************************************
//
// FUNCTION: static KEY_INDEX TranslateADCKey(BYTE B_KeyPort)
// USAGE: Comparing ADC value with table code by the method binary tree
//
// INPUT: B_KeyPort - ADC key port number
// ADC_KEY1,ADC_KEY2,ADC_KEY3
// OUTPUT: KEY_INDEX - id pushed key
// If none of the key is pressed, return value Key_None
// GLOBALS: NUMBER_OF_ADC_1Values - number of members in array ADC_1Values[]
// ADC_1Values - translating ADC code to id key.
// USED_REGS: None
//
//******************************************************************************
#if LBADC_USED
static gmt_KEY_INDEX __near TranslateADCKey(BYTE B_KeyPort)
{
BYTE B_Value;
SBYTE SB_Result;
SWORD B_Offset, B_Max, B_Min = 0;
ST_ADC ROM *ADC_Values;
#ifdef PORT_ADC_1_USED
if (B_KeyPort == ADC_KEY1)
{
B_Max = NUMBER_OF_ADC_1Values - 1;
B_Value = KeyFilter(0,ScanAdcKey(LBADC_IN1));
ADC_Values = ADC_1Values;
}
#endif
#ifdef PORT_ADC_2_USED
if (B_KeyPort == ADC_KEY2)
{
B_Max = NUMBER_OF_ADC_2Values - 1;
B_Value = KeyFilter(0,ScanAdcKey(LBADC_IN2));
ADC_Values = ADC_2Values;
}
#endif
#ifdef PORT_ADC_3_USED
if (B_KeyPort == ADC_KEY3)
{
B_Max = NUMBER_OF_ADC_3Values - 1;
B_Value = KeyFilter(0,ScanAdcKey(LBADC_IN3));
ADC_Values = ADC_3Values;
}
#endif
if (B_KeyPort >= MAX_ADC_KEY)
return Key_None;
// By comment out KeyDataPresent, which means:
// Always searching keys no matter whether key is pressed or not. By doing this way,
//then we don't have to assign any scancode for Key_None and any scancode can be used
//as a valid scancode (even 0 or 0xff, previous assumed for Key_None).
//
// if (KeyDataPresent(B_Value))
{
// Do a binary tree search of all the ADC1 values until we find the
// real key value where our read value falls into the range of and
// return this real value
// If B_Min goes past B_Max, then no corresponding code was found so
// we return Key_None.
//
while(B_Min <= B_Max)
{
B_Offset = ((WORD)B_Max + B_Min) / 2;
//
// Check if the value falls within the range of the current ADC
// value we are pointing at.
//
SB_Result = CheckADCCode(ADC_Values[B_Offset].Code, B_Value);
// Got a match, so we can return the value.
//
if (SB_Result == 0)
{
return(ADC_Values[B_Offset].KeyIndex);
}
else
{
if (SB_Result < 0)
B_Max = B_Offset - 1;
else
B_Min = B_Offset + 1;
}
}
}
return Key_None;
}
#endif //LBADC_USED
//******************************************************************************
//
// FUNCTION: static KEY_VALUE ReadKey (void)
// USAGE: Scan key state in each of the three LBADC channels (if used).
// Note that:
// KeyDataPresent(B_Key) should be redefined in cases where a
// pull-up scheme is used for key detection (ie. a key press
// brings the ADC return value closer to GND).
// For special (noise) filtering, KeyFilter should be redefined
// to reference the filtering function (eg. majority filter),
// which takes as parameters the ADC input channel and the raw
// ADC value.
// To customize key filtering, compile using CUSTOM_ADCKEYFILTERING
//
// INPUT: None
// OUTPUT: KEY_VALUE - Bit 15 to Bit 13 is input source and
// - the rest is the data value from IR.
// If none of the key is pressed, return value 0.
// GLOBALS: B_ScanCode,B_LastKeyType, NUMBER_OF_ADC_1Values,
// NUMBER_OF_ADC_2Values, NUMBER_OF_ADC_3Values,
// NUMBER_OF_MultiplePortsValuesTranslation
// USED_REGS: None
//
//******************************************************************************
#if USE_GETKEY_TIMER_ISR
struct
{
BYTE useIsr;
BYTE keyHead;
BYTE keyTail;
gmt_KEY_INDEX keyArray[13];
}IsrKeyStruct = {gmd_FALSE};
static gmt_KEY_INDEX __near ReadKey(void)
#else
gmt_KEY_INDEX far GetKey(void)
#endif
{
gmt_KEY_INDEX B_KeyCode = Key_None;
gmt_KEY_INDEX *Bp_ScanCode = B_ScanCode;
#if (USE_GPIO_KEYPAD | LBADC_USED | defined(PORT_IR_USED))
BYTE B_Key;
BYTE B_CountKey = 0;
#endif
#if defined(USE_EXTERNAL_KEY_HANDLER) && (USE_EXTERNAL_KEY_HANDLER)
*Bp_ScanCode = B_Key = TranslateExternalKey();
if (B_Key != Key_None)
{
B_LastKeyType = GPIO_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
#else
*Bp_ScanCode = Key_None;
#endif //USE_EXTERNAL_KEY_HANDLER
Bp_ScanCode++;
#if USE_GPIO_KEYPAD
#if (WB_MAJOR == 3) && (WB_MINOR == 1) && (WB_REVISION == 1)
// For WB version 3.1.1.10 NUMBER_OF_SCAN_KEY is a ROM constant, so
// us it in a regular runtime 'if' statement.
// Get GPIO keypad key.
// If any GPIO keys are mapped then we need to check GPIO keypad
if (NUMBER_OF_SCAN_KEY)
{
*Bp_ScanCode = B_Key = TranslateGPIOKey();
if (B_Key != Key_None)
{
B_LastKeyType = GPIO_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
}
else
{
*Bp_ScanCode = Key_None;
}
#else // WB != 3.1.1x
// For WB versions later than 3.1.1.10 NUMBER_OF_SCAN_KEY is a #define,
// so us it in a compile time #if statement.
// Get GPIO keypad key.
// If any GPIO keys are mapped then we need to check GPIO keypad
#if (NUMBER_OF_SCAN_KEY)
{
*Bp_ScanCode = B_Key = TranslateGPIOKey();
if (B_Key != Key_None)
{
B_LastKeyType = GPIO_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
}
#else
{
*Bp_ScanCode = Key_None;
}
#endif //NUMBER_OF_SCAN_KEY
#endif //WB == 3.1.1.x
#else
*Bp_ScanCode = Key_None;
#endif //USE_GPIO_KEYPAD
Bp_ScanCode++;
#ifdef PORT_ADC_1_USED
// Get key from multimedia keypad channel1
// If any ADC_1 keys are mapped, then we need to check ADC1
if (NUMBER_OF_ADC_1Values)
{
*Bp_ScanCode = B_Key = TranslateADCKey(ADC_KEY1);
if (B_Key != Key_None)
{
B_LastKeyType = ADC_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
}
else
*Bp_ScanCode = Key_None;
#else
*Bp_ScanCode = Key_None;
#endif
Bp_ScanCode++;
#ifdef PORT_ADC_2_USED
// Get key from multimedia keypad channel2
// If any ADC_2 keys are mapped, then we need to check ADC2
if (NUMBER_OF_ADC_2Values)
{
*Bp_ScanCode = B_Key = TranslateADCKey(ADC_KEY2);
if (B_Key != Key_None)
{
B_LastKeyType = ADC_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
}
else
*Bp_ScanCode = Key_None;
#else
*Bp_ScanCode = Key_None;
#endif
Bp_ScanCode++;
#ifdef PORT_ADC_3_USED
// Get key from multimedia keypad channel3
// If any ADC_3 keys are mapped, then we need to check ADC3
if (NUMBER_OF_ADC_3Values)
{
*Bp_ScanCode = B_Key = TranslateADCKey(ADC_KEY3);
if (B_Key != Key_None)
{
B_LastKeyType = ADC_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
}
else
*Bp_ScanCode = Key_None;
#else
*Bp_ScanCode = Key_None;
#endif
Bp_ScanCode++;
#ifdef PORT_IR_USED
// Get IR remote key.
// If any IR keys are mapped, then we need to check IR
if (NUMBER_OF_IRValues)
{
*Bp_ScanCode = B_Key = TranslateIrKey();
if (B_Key != Key_None)
{
B_LastKeyType = IR_KEY;
B_KeyCode = B_Key;
B_CountKey++;
}
} else
{
*Bp_ScanCode = Key_None;
}
#else
*Bp_ScanCode = Key_None;
#endif
Bp_ScanCode++;
#if WB_NUMBER_OF_INPUT_SOURCE > 1
//
// Get Multiple Ports keypad key.
//
if (B_CountKey > 1)
{
B_KeyCode = Key_None;
if(NUMBER_OF_MultiplePortsValuesTranslation)
{
BYTE B_CountI;
for (B_CountI = 0; B_CountI < NUMBER_OF_MultiplePortsValuesTranslation; B_CountI++)
{
BYTE B_Found = 0xff;
BYTE B_CountJ;
for (B_CountJ = 0; B_CountJ < NUMBER_OF_INPUT_SOURCE; B_CountJ++)
{
B_Found &= MultiplePortsValuesTranslation[B_CountI].Codes[B_CountJ] == B_ScanCode[B_CountJ];
}
if (B_Found)
{
B_KeyCode = MultiplePortsValuesTranslation[B_CountI].KeyIndex;
break;
}
}
}
}
#endif
#if DEBUG_INPUT
if (B_KeyCode)
msg("KeyValue = %d", B_KeyCode);
#endif
#if USE_GETKEY_TIMER_ISR
// don't allow array to fill up with same key elements.
if(IsrKeyStruct.useIsr == gmd_TRUE)
{
BYTE i;
BYTE tempHead = IsrKeyStruct.keyHead;
for(i=0;i<2;i++)
{
tempHead--;
if(tempHead >= sizeof(IsrKeyStruct.keyArray))
tempHead = sizeof(IsrKeyStruct.keyArray) - 1;
if(B_KeyCode != IsrKeyStruct.keyArray[tempHead])
break;
}
if(i>=2)
{// return so long as tail hasn't caught up.
if(abs(IsrKeyStruct.keyTail - IsrKeyStruct.keyHead) > 2)
return B_KeyCode;
}
IsrKeyStruct.keyArray[IsrKeyStruct.keyHead] = B_KeyCode;
IsrKeyStruct.keyHead++;
if(IsrKeyStruct.keyHead >= sizeof(IsrKeyStruct.keyArray))
IsrKeyStruct.keyHead = 0;
}
#endif
return B_KeyCode;
}
#if USE_GETKEY_TIMER_ISR
gmt_KEY_INDEX far GetKey(void)
{
BYTE key = Key_None;
if(IsrKeyStruct.keyHead != IsrKeyStruct.keyTail)
{
key = IsrKeyStruct.keyArray[IsrKeyStruct.keyTail];
IsrKeyStruct.keyTail++;
if(IsrKeyStruct.keyTail >= sizeof(IsrKeyStruct.keyArray))
IsrKeyStruct.keyTail = 0;
}
else if((IsrKeyStruct.useIsr == gmd_FALSE))
key = ReadKey();
return key;
}
//******************************************************************
// FUNCTION : StartGetKeyISR/StopGetKeyISR
// DESCRIPTION : Functions set up an interrupt and chain it to
// the system timer which already gives us a 1ms tick. Upon the
// GETKEY_TIME_MS time in the ISR, ReadKey() is called to
// read all the keypad devices and store the scan key code into
// IsrKeyStruct.keyArray[]
//******************************************************************
void far interrupt (*OldTimerIsr)(void);
void far interrupt GetKeyISR(void)
{
static WORD i=0;
#if (GET_KEY_TIMER_ISR == TIMER2_VECTOR)
if(i++ >= GETKEY_TIME_MS)
{
ReadKey();
i = 0;
}
OldTimerIsr();
#elif (GET_KEY_TIMER_ISR == TIMER1_VECTOR)
if(i++ >= (GETKEY_TIME_MS / 2) - 1) // timer0 runs at half the speed.
{
ReadKey();
i = 0;
}
CLEAR_PCB_REG_BITS(T1CON, MC);
WRITE_PCB_REG(EOI, TIMER1_VTYPE);
#elif (GET_KEY_TIMER_ISR == TIMER0_VECTOR)
if(i++ >= (GETKEY_TIME_MS / 2) - 1) // timer0 runs at half the speed.
{
ReadKey();
i = 0;
}
CLEAR_PCB_REG_BITS(T0CON, MC);
WRITE_PCB_REG(EOI, TIMER0_VTYPE);
#endif
}
void StartGetKeyISR(void)
{
#if (GET_KEY_TIMER_ISR != TIMER2_VECTOR)
WORD W_Tmo = READ_PCB_REG(T2CMPA);
#endif
IsrKeyStruct.keyHead = 0;
IsrKeyStruct.keyTail = 0;
IsrKeyStruct.useIsr = gmd_TRUE;
msg("** Start GetKeyISR **",0);
gm_DisableInterrupts();
#if (GET_KEY_TIMER_ISR == TIMER2_VECTOR)
if((void far interrupt (*)(void))GET_VECTOR(TIMER2_VECTOR) != GetKeyISR)
{
OldTimerIsr = (void far interrupt (*)(void))GET_VECTOR(TIMER2_VECTOR);
SET_VECTOR(TIMER2_VECTOR, GetKeyISR);
}
#elif (GET_KEY_TIMER_ISR == TIMER1_VECTOR)
// Timer2 is used as 1ms. interrupt. Just read Timer2 compare
// register and multiply by GETKEY_TIME_MS to get desired Timer1
// compare value. Run T1 at half the speed.
WRITE_PCB_REG(T1CMPA, (W_Tmo * 2)); // Configure timer1 value
WRITE_PCB_REG(T1CNT, 0); // Clear counter
SET_VECTOR(TIMER1_VECTOR, GetKeyISR);
WRITE_PCB_REG(T1CON, (EN|INH|INT|CONT));
#elif (GET_KEY_TIMER_ISR == TIMER0_VECTOR)
// Timer2 is used as 1ms. interrupt. Just read Timer2 compare
// register and multiply by GETKEY_TIME_MS to get desired Timer0
// compare value. Run T0 at half the speed.
WRITE_PCB_REG(T0CMPA, (W_Tmo * 2)); // Configure timer0 value
WRITE_PCB_REG(T0CNT, 0); // Clear counter
SET_VECTOR(TIMER0_VECTOR, GetKeyISR);
WRITE_PCB_REG(T0CON, (EN|INH|INT|CONT));
#endif
asm{ STI };
}
void StopGetKeyISR(void)
{
msg("** Stop GetKeyISR **",0);
#if (GET_KEY_TIMER_ISR == TIMER2_VECTOR)
gm_DisableInterrupts();
SET_VECTOR(TIMER2_VECTOR,OldTimerIsr);
asm{ STI };
#elif (GET_KEY_TIMER_ISR == TIMER1_VECTOR)
// stop timer.
WRITE_PCB_REG(T1CON, (INH|INT|CONT));
#elif (GET_KEY_TIMER_ISR == TIMER0_VECTOR)
// stop timer.
WRITE_PCB_REG(T0CON, (INH|INT|CONT));
#endif
IsrKeyStruct.useIsr = gmd_FALSE;
}
#endif
#endif
#undef __KEYPAD_C__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -