или так. мультикнопочная, нажатие , отжатие, автоповтор - ведет себя как комповая клава. Sw2, Sw1 - физические входы
kbd.h
#ifndef DEF_KBD_INC
#define KBD_PRESS_FLAG 0x80
#define KBD_RELEASE_FLAG 0x00
// SCAN-Codes
enum SCAN{
SCAN_SW1=1,
SCAN_SW2,
SCAN_ESC,
/*Virtual key */ // scan-коды которые генерятся другими модулями.
SCAN_VIRTUAL =0xF0,
SCAN_PROG_ADDR,
SCAN_CANCEL
};
typedef BYTE t_SCANCode;
typedef BYTE t_KbdState;
typedef BYTE t_KbdDelay;
#define DEF_KBD_INC
#endif
Kbd.c
#include <machine.h>
#include <globalt.h>
#include "hardware.h"
#include <osa.h>
#include <timesdef.h>
#include "tasks.h"
#include "kbd.h"
#define KBD_AUTO_REPEAT_DELAY TIME_500mS
#define KBD_ANTI_RATTLE_DELAY TIME_50mS
#define KBD_AUTO_REPEAT TIME_350mS
#define KBD_POLL_DELAY TIME_10mS
#define GetCurrKbdState() (~(Sw2<<1 | Sw1))
#define KEYBOARD_MASK 0x3
#define KBD_SW1 0x1
#define KBD_SW2 0x2
#define KBD_TWO 0x3
static void SendScanCode(t_KbdState PrevState, t_KbdState CurrState);
static t_KbdState KBdPrevState;
static t_KbdState KBdCurrState;
void TaskKeyBoard(void){
static WORD i;
BYTE bTmp;
KBdPrevState=~KEYBOARD_MASK;
KBdCurrState=~KEYBOARD_MASK;
loop{
OS_Delay(KBD_POLL_DELAY);
if((bTmp=GetCurrKbdState()) != KBdPrevState){ // without bTmp not work properly
loop{
OS_Delay(KBD_ANTI_RATTLE_DELAY);
KBdPrevState=KBdCurrState;
KBdCurrState=GetCurrKbdState();
if(KBdCurrState & KEYBOARD_MASK){
SendScanCode(KBdPrevState, KBdCurrState);
for(i=KBD_AUTO_REPEAT_DELAY/KBD_POLL_DELAY; i; i--){
OS_Delay(KBD_POLL_DELAY);
breakif((bTmp=GetCurrKbdState()) != KBdCurrState);
}
continueif(i);
// KBD_AUTO_REPEAT_DELAY - Ok
SendScanCode(KBdPrevState, KBdCurrState);
loop{
for(i=KBD_AUTO_REPEAT/KBD_POLL_DELAY; i; i--){
OS_Delay(KBD_POLL_DELAY);
if((bTmp=GetCurrKbdState()) != KBdCurrState){
break;
}
}
breakif(i);
// KBD_AUTO_REPEAT - Ok
SendScanCode(KBdPrevState, KBdCurrState);
}
continue;
}
asm("Nop");
SendScanCode(KBdPrevState, KBdCurrState);
break;
}
}
asm("Nop");
}
}
static void SendScanCode(t_KbdState PrevState, t_KbdState CurrState){
static t_KbdState ReleaseState;
BYTE ScanCode;
t_KbdState State;
if(CurrState>PrevState){
ReleaseState=0;
State=CurrState;
}else{
if(ReleaseState==PrevState) return; // Skip send message
ReleaseState=State=PrevState;
}
switch(State&KEYBOARD_MASK){
case KBD_SW1:
ScanCode=SCAN_SW1;
break;
case KBD_SW2:
ScanCode = SCAN_SW2;
break;
case KBD_TWO:
ScanCode=SCAN_ESC;
break;
default:
return;
}
if(CurrState>PrevState)
ScanCode |= KBD_PRESS_FLAG;
OS_Smsg_Send(MSG_ScanCode_P, (OST_SMSG)ScanCode);
}