📄 keypad.c
字号:
{
IrLWord <<= 1;
}
if( (B_IrClockCounter < IR_LOGIC1_MAX) && (B_IrClockCounter > IR_LOGIC1_MIN))
{
IrLWord <<= 1;
IrLWord |= 0x0001;
}
#if IR_DEVICE_LENGTH
if(IrIndex == IR_DEVICE_LENGTH)
{
IrAddress = IrLWord;
}
#endif
if(IrIndex == IR_DATA_LENGTH)
{
IRKey = IrLWord;
IrIndex = 0;
IrLWord = 0;
}
if(IrIndex > IR_DATA_LENGTH)
{
IrIndex = 0;
IrLWord = 0;
}
WRITE_PCB_REG(T1CNT, 0); // Clear counter
WRITE_PCB_REG(T1CON, (EN|INH|INT|CONT));
CLEAR_PCB_REG_BITS(IMASK, TMR);
B_IrClockCounter = 0;
WRITE_PCB_REG(EOI, INT2_VTYPE); // Clear interrupt
}
//******************************************************************************
//
// FUNCTION: interrupt IRTimerInt(void)
// USAGE: Timer1 interrupt service routine.
//
// INPUT: None
// OUTPUT: None
// GLOBALS: None
// USED_REGS: T1CON, EOI
//
//******************************************************************************
void far interrupt IRTimerInt(void)
{
B_IrClockCounter++;
W_IrPacketCounter++;
if(W_IrPacketCounter > IR_AUTOREPEAT_RESET)
{
// Clear key
IRKey = 0;
// disable timer interrupt
WRITE_PCB_REG(T1CON, (INH|INT|CONT));
B_IrClockCounter = 0;
W_IrPacketCounter = 0;
}
CLEAR_PCB_REG_BITS(T1CON, MC);
WRITE_PCB_REG(EOI, TIMER1_VTYPE);
}
#else // USE_RC5
//******************************************************************************
//
// FUNCTION: IRInit(DWORD D_CpuClock)
// USAGE: Initialization of infrared reciever.
// Use Mcu timer1 and external interrupt.
//
// INPUT: D_CpuClock - CPU clock speed
// OUTPUT: None
// GLOBALS: None
// USED_REGS: IRQ_CONFIG, I2CON, IMASK, T1CMPA
//
//******************************************************************************
// RC5RC
void far IRInit(DWORD D_CpuClock)
{
//Setup Int2 interrupt register
gm_SetRegBitsWord(IRQ_CONFIG, GPIO_IRQ_IN_EN);
WRITE_PCB_REG(I2CON, 0);
SET_VECTOR(INT2_VECTOR, IREdgeInterrupt);
CLEAR_PCB_REG_BITS(IMASK, I2);
//Setup Timer1 time out values
{
W_IRPeriodTIme = (WORD)(D_CpuClock/4499L); // Generate 0.889ms timeout
SET_VECTOR(TIMER1_VECTOR, IRTimerInt);
}
}
//******************************************************************************
//
// FUNCTION: interrupt IREdgeInterrupt(void)
// USAGE: Rising edge interrupt service routine
//
// INPUT: None
// OUTPUT: None
// GLOBALS: None
// USED_REGS: T1CNT, T1CON, IMASK, EOI
//
//******************************************************************************
void far interrupt IREdgeInterrupt(void)
{
IrIndex = 0;
IrLWord = 0;
B_EdgeState = 0;
W_IrPacketCounter = 0;
WRITE_PCB_REG(T1CNT, 0); // Clear counter value
WRITE_PCB_REG(T1CMPA, W_IRPeriodTIme + (W_IRPeriodTIme >> 1)); // Configure timer1 value
WRITE_PCB_REG(T1CON, (EN|INH|INT|CONT));
CLEAR_PCB_REG_BITS(IMASK, TMR);
SET_PCB_REG_BITS(IMASK, I2); // Mask this interrupt
gm_ClearRegBitsWord(IRQ_CONFIG, GPIO_IRQ_IN_EN); // enable GPIO input
WRITE_PCB_REG(EOI, INT2_VTYPE); // Clear interrupt
}
//******************************************************************************
//
// FUNCTION: interrupt IRTimerInt(void)
// USAGE: Timer1 interrupt service routine.
//
// INPUT: None
// OUTPUT: None
// GLOBALS: None
// USED_REGS: T1CON, EOI
//
//******************************************************************************
void far interrupt IRTimerInt(void)
{
BYTE B_Input;
WRITE_PCB_REG(T1CMPA, W_IRPeriodTIme); // Configure timer1 value
B_Input = gm_ReadRegWord(GPINPUT1) & INPUT_BIT_MASK;
if(IrIndex == 0)
B_EdgeState = B_Input;
if(IrIndex < IR_DATA_LENGTH)
{
if(IrIndex & 0x01)
{
if(B_EdgeState != B_Input)
{
IrLWord <<= 1;
if(B_Input)
IrLWord |= 0x0001;
}
}
IrIndex++;
B_EdgeState = B_Input;
}
else
{
if(IrLWord & 0x1000)
{
if((IrLWord & 0x07ff) == 0)
IrLWord = ZERRO_KEY_CODE;
IRKey = IrLWord & 0x07ff;
W_IrPacketCounter = IR_DATA_LENGTH + 1;
}
IrLWord = 0;
IrIndex = 0;
gm_SetRegBitsWord(IRQ_CONFIG, GPIO_IRQ_IN_EN); // enable GPIO input
CLEAR_PCB_REG_BITS(IMASK, I2); // Mask this interrupt
}
W_IrPacketCounter++;
if(W_IrPacketCounter > IR_AUTOREPEAT_RESET)
{
IRKey = 0;
IrLWord = 0;
IrIndex = 0;
// disable timer interrupt
WRITE_PCB_REG(T1CON, (INH|INT|CONT));
}
CLEAR_PCB_REG_BITS(T1CON, MC);
WRITE_PCB_REG(EOI, TIMER1_VTYPE);
}
#endif // IR_DRIVER != USE_RC5
//******************************************************************************
//
// FUNCTION: static KEY_INDEX TranslateIrKey(void)
// USAGE: Comparing Ir value with table code by the method binary search
//
// INPUT: none
// OUTPUT: KEY_INDEX - id pushed key
// If none of the key is pressed, return value Key_None
// GLOBALS: Number_Of_IRValues - number of members in array IRValues[]
// IRValues - translating Ir code to id key.
// USED_REGS: None
//
//******************************************************************************
static gmt_KEY_INDEX TranslateIrKey(void)
{
BYTE B_Result;
SWORD B_Offset;
SWORD B_Min = 0;
SWORD B_Max = NUMBER_OF_IRValues - 1;
BYTE B_Value = IRKey;
// ScanRemoteKey to see if a new value was found.
if (B_Value)
{
#if DEBUG_IR_CODE
msg("Ir Code =0x%x", B_Value);
#endif
while(B_Min <= B_Max)
{
// For IR the codes must match exactly, so do a binary search only
// returning the value when the codes are exactly equal.
B_Offset = ((WORD)B_Max + B_Min) / 2;
B_Result = IRValues[B_Offset].Code;
if (B_Result == B_Value)
{
return(IRValues[B_Offset].KeyIndex);
}
else
{
if (B_Result > B_Value)
B_Max = B_Offset - 1;
else
B_Min = B_Offset + 1;
}
}
}
return Key_None;
}
#endif
//******************************************************************************
//
// FUNCTION: void far InitGpioKeyMap(void)
// USAGE: Initialize key map table for gpio. Fill up the key mapping table base on the information in
// WB file, osd_Trtbl.c. The key mapping table will be used in key scanning.
// INPUT: None
// OUTPUT: None
// GLOBALS: None
// USED_REGS: None
//
//******************************************************************************
void InitGpioKeyMap(void)
{
#if USE_GPIO_KEYPAD
//
// Temporary variables for a loop index
//
WORD i;
WORD W_Mask;
//
// Fill up the key mapping table base on the information in
// WB file: osd_Trtbl.c. The key mapping table will be used in
// key scanning.
//
for (i = 0; i < NUMBER_OF_SCAN_KEY; i++)
{
//
// Individual GPIO Pins
//
W_Mask = Wa_KeyMapMask[KeyMapping[i].Bit];
switch(KeyMapping[i].Port)
{
case 0:
Sta_KeyMapTbl[i].W_GpioPortAddr = GPINPUT1;
gm_WriteRegByte(GPIO_DIRCTRL1, gm_ReadRegByte(GPIO_DIRCTRL1) & ~W_Mask); // GPIO1 pin as input
break;
case 1:
Sta_KeyMapTbl[i].W_GpioPortAddr = GPINPUT2;
gm_WriteRegByte(GPIO_DIRCTRL2, gm_ReadRegByte(GPIO_DIRCTRL2) & ~W_Mask); // GPIO2 pin as input
break;
case 2:
Sta_KeyMapTbl[i].W_GpioPortAddr = GPINPUT3;
gm_WriteRegByte(GPIO_DIRCTRL3, gm_ReadRegByte(GPIO_DIRCTRL3) & ~W_Mask); // GPIO3 pin as input
break;
}
// store the associated pin position in the array Sta_KeyMapTbl
Sta_KeyMapTbl[i].W_GpioPinPos = W_Mask;
}
#endif
}
//******************************************************************************
//
// FUNCTION: gmt_GPIO_KEY_VALUE far gm_ReadKeyPad(void)
// USAGE: Scan Key from Gpio
// INPUT: None
// OUTPUT: Key Value
// GLOBALS: None
// USED_REGS: None
//
//******************************************************************************
#if USE_GPIO_KEYPAD
gmt_GPIO_KEY_VALUE far gm_ReadKeyPad(void)
{
BYTE B_Key = 0;
BYTE i;
for (i = 0; i < NUMBER_OF_SCAN_KEY; i++)
{
#if KeyPolarity
if ((gm_ReadRegByte(Sta_KeyMapTbl[i].W_GpioPortAddr) & Sta_KeyMapTbl[i].W_GpioPinPos) != 0)
#else
if ((gm_ReadRegByte(Sta_KeyMapTbl[i].W_GpioPortAddr) & Sta_KeyMapTbl[i].W_GpioPinPos) == 0)
#endif
{
B_Key |= Wa_KeyMapMask[i];
}
}
return(B_Key);
}
#endif
//******************************************************************************
//
// FUNCTION: static KEY_INDEX TranslateGPIOKey(none)
// USAGE: Comparing GPIO key value with table code by the method binary tree
//
// INPUT: none
// OUTPUT: KEY_INDEX - id pushed key
// If none of the key is pressed, return value 0.
// If invalid key is pressed, return value 255.
// GLOBALS: Number_Of_KeyPadTranslation - number of members in array KeyPadTranslation[]
// KeyPadTranslation - translating GPIO code to id key.
// USED_REGS: None
//
//******************************************************************************
#if USE_GPIO_KEYPAD
static gmt_KEY_INDEX TranslateGPIOKey(void)
{
gmt_GPIO_KEY_VALUE B_Result;
SWORD B_Offset;
SWORD B_Min = 0;
SWORD B_Max = NUMBER_OF_GPIOValues - 1;
gmt_GPIO_KEY_VALUE B_Value = gm_ReadKeyPad();
if (B_Value)
{
while(B_Min <= B_Max)
{
B_Offset = ((WORD)B_Max + B_Min) / 2;
B_Result = GPIOValues[B_Offset].KeyValue;
if (B_Result == B_Value)
{
#if DEBUG_OSD_KEYPAD
msg("TranslateGPIOKey: B_Offset = %d ", B_Offset);
msg("TranslateGPIOKey = 0x%x", GPIOValues[B_Offset].KeyIndex);
#endif
return(GPIOValues[B_Offset].KeyIndex);
} else
{
if (B_Result > B_Value)
{
B_Max = B_Offset - 1;
} else
{
B_Min = B_Offset + 1;
}
}
}
#if DEBUG_OSD_KEYPAD
msg("TranslateGPIOKey = Invalid Key ", GPIOValues[B_Offset].KeyIndex);
#endif
return 255; // invalid key
}
return 0; // key none
}
#endif // USE_GPIO_KEYPAD
//******************************************************************************
//
// FUNCTION: ADCDelay
// USAGE: LOW_BW_ADC_STATUS always returns conversion complete, so this is
// a delay function to give timer for LBADC conversion to complete.
// NOTE: we cant use a gm_Delay function because the LBADC can be
// read in an interrupt where we can't use gm_DelayXX functions.
// INPUT: void
// OUTPUT: void
// GLOBALS: none
// USED_REGS: none
//
//******************************************************************************
static void __near ADCDelay(void)
{
// function calls alone take about 7us.
}
//******************************************************************************
//
// FUNCTION: BYTE far ScanAdcKey (WORD B_Channel)
// USAGE: First configure the low bandwidth ADC of keypad then retrieve the converted data
// INPUT: B_Channel
// OUTPUT: ADC key data
// GLOBALS: none
// USED_REGS: none
//
//******************************************************************************
#if LBADC_USED
BYTE far ScanAdcKey(BYTE B_Channel)
{
BYTE B_Key = 0;
BYTE B_Ctrl;
//
// 1) Configure LBW ADC channel 1, 2 and then 3 to handle keyboard key input
// 2) Program the Low Bandwidth ADC control register to start conversion.
//
B_Ctrl = LBADC_EN | B_Channel | DIV_BY_1;
gm_WriteRegByte (LOW_BW_ADC_CTRL, B_Ctrl);
gm_WriteRegByte (LOW_BW_ADC_CTRL, B_Ctrl | LBADC_START_CONV);
//
// When conversion done, copy the conversion result to the BYTE pointer.
//
// LOW_BW_ADC_STATUS needs 3TCLKs to clear after a LBADC_START_CONV,
// add delay to give time for LOW_BW_ADC_STATUS to read correctly.
ADCDelay();
while(((gm_ReadRegByte (LOW_BW_ADC_STATUS)) & BIT0)==0) continue;
#if AdcPolarity
B_Key = ~((BYTE) gm_ReadRegByte (LOW_BW_ADC_RESULT)); // Read key data
#else
B_Key = (BYTE) gm_ReadRegByte (LOW_BW_ADC_RESULT); // Read key data
#endif
//
// Reset the Low Bandwidth ADC control register to idle.
//
gm_WriteRegByte (LOW_BW_ADC_CTRL, B_Ctrl);
#if DEBUG_SCAN_CODE
if(B_PreKeyCode!=B_Key)
{
msg("ScanCode = 0x%x", B_Key);
B_PreKeyCode = B_Key;
}
#endif
return B_Key;
}
#endif //LBADC_USED
//******************************************************************************
//
// FUNCTION: static SBYTE CheckADCCode(BYTE B_TableCode, BYTE B_Value)
// USAGE: Comparing ADC value with table code
//
// INPUT: B_TableCode, B_Value - ADC value
// OUTPUT: 0 = the table code equals ADC value
// 1 = the table code less ADC value
// -1 = the table code greater ADC value
// GLOBALS: None
// USED_REGS: None
//
//******************************************************************************
#if LBADC_USED
static SBYTE CheckADCCode(BYTE B_TableCode, BYTE B_Value)
{
// If B_Value is within the ADC_DELTA range we return 0 because it matchs
// otherwise we return 1 if table code is less than ADC and -1 if table
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -