Chapter 12 - Capturing Inputs part 2

advertisement
Chapter 12
Capturing Input
Change Notification Module
Di Jasio - Programming 32-bit Microcontrollers in C
Using CN to Capture Keyboard
Inputs
Di Jasio - Programming 32-bit Microcontrollers in C
CN - ISR
void __ISR( _CHANGE_NOTICE_VECTOR, ipl1) CNInterrupt( void)
{ // change notification interrupt service routine
// 1. make sure it was a falling edge
if ( PS2CLK == 0)
{
switch( PS2State){
default:
case PS2START:
// verify start bit
if ( ! PS2DAT)
{
KCount = 8;
// init bit counter
KParity = 0;
// init parity check
PS2State = PS2BIT;
}
break;
case PS2BIT:
KBDBuf >>=1;
// shift in data bit
if ( PS2DAT)
KBDBuf += 0x80;
KParity ^= KBDBuf;
// update parity
if ( --KCount == 0)
// if all bit read, move on
PS2State = PS2PARITY;
break;
case PS2PARITY:
if ( PS2DAT)
KParity ^=
if ( KParity &
PS2State =
else
PS2State =
break;
// verify parity
0x80;
0x80)
// if parity odd, continue
PS2STOP;
PS2START;
Di Jasio - Programming 32-bit Microcontrollers in C
case PS2STOP:
if ( PS2DAT)
{
KBDCode = KBDBuf;
KBDReady = 1;
}
PS2State = PS2START;
break;
} // switch state machine
} // if falling edge
// clear interrupt flag
mCNClearIntFlag();
} // CN Interrupt
// verify stop bit
// save code in mail box
// set flag, code availab
I/O Polling (Timer based)
Di Jasio - Programming 32-bit Microcontrollers in C
I/O Polling State Machine
Di Jasio - Programming 32-bit Microcontrollers in C
I/O Polling - ISR
void __ISR( _TIMER_4_VECTOR, ipl1) T4Interrupt( void)
{
int d, k;
// sample the inputs clock and data at the same time
d = PS2DAT;
k = PS2CLK;
// keyboard state machine
if ( KState)
{
// previous time clock was high KState 1
if ( !k)
// PS2CLK == 0
{
// falling edge detected,
KState = 0;
// transition to State0
<<<< insert data state machine here >>>>
} // falling edge
else
{ // clock still high, remain in State1
} // clock still high
} // state 1
else
{ // state 0
if ( k)
// PS2CLK == 1
{ // rising edge, transition to State1
KState = 1;
} // rising edge
else
{ // clocl still low, remain in State0
} // clock still low
} // state 0
// clear the interrupt flag
mT4ClearIntFlag();
} // T4 Interrupt
Di Jasio - Programming 32-bit Microcontrollers in C
I/O Polling w/Timeout
Di Jasio - Programming 32-bit Microcontrollers in C
I/O Polling w/Timeout - ISR
void __ISR( _TIMER_4_VECTOR, ipl1) T4Interrupt( void)
{
int d, k;
// sample the inputs clock and data at the same time
d = PS2DAT;
k = PS2CLK;
// keyboard state machine
if ( KState)
{
// previous time clock was high
if ( !k)
{
// falling edge detected,
KState = 0;
KTimer = KMAX;
KState 1
// PS2CLK == 0
// transition to State0
// restart the counter
<<<< insert data state machine here >>>>
} // falling edge
else
{ // clock still high, remain in State1
KTimer--;
if ( KTimer ==0)
// Timeout
PS2State = PS2START;
// Reset data SM
} // clock still high
} // Kstate 1
else
{ // Kstate 0
if ( k)
// PS2CLK == 1
{ // rising edge, transition to State1
KState = 1;
} // rising edge
else
{ // clocl still low, remain in State0
KTimer--;
if ( KTimer == 0)
// Timeout
PS2State = PS2START;
// Reset data SM
} // clock still low
} // Kstate 0
// clear the interrupt flag
mT4ClearIntFlag();
} // T4 Interrupt
Di Jasio - Programming 32-bit Microcontrollers in C
Switch
switch( PS2State){
default:
case PS2START:
if ( !d)
{
KCount = 8;
KParity = 0;
PS2State = PS2BIT;
}
break;
// PS2DAT == 0
// init bit counter
// init parity check
case PS2BIT:
KBDBuf >>=1;
//
if ( d)
//
KBDBuf += 0x80;
KParity ^= KBDBuf;
//
if ( --KCount == 0)
//
PS2State = PS2PARITY;
break;
case PS2PARITY:
if ( d)
KParity ^=
if ( KParity &
PS2State =
else
PS2State =
break;
Di Jasio - Programming 32-bit Microcontrollers in C
calculate parity
all bit read
// PS2DAT == 1
0x80;
0x80)
// parity odd, continue
PS2STOP;
PS2START;
case PS2STOP:
if ( d)
{
KBDCode = KBDBuf;
KBDReady = 1;
}
PS2State = PS2START;
break;
} // switch
shift in data bit
PS2DAT == 1
// PS2DAT == 1
// write in the buffer
InitKBD
void initKBD( void)
{
// init I/Os
ODCGbits.ODCG13 = 1;
_TRISG13 = 1;
_TRISG12 = 1;
// make RG13 open drain (PS2clk)
// make RG13 an input pin (for now)
// make RG12 an input pin
// clear the kbd flag
KBDReady = 0;
// configure Timer4
PR4 = 25*TPS - 1;
T4CON = 0x8000;
mT4SetIntPriority( 1);
mT4ClearIntFlag();
mT4IntEnable( 1);
} // init KBD
Di Jasio - Programming 32-bit Microcontrollers in C
//
//
//
//
//
25 us
T4 on, prescaler 1:1
lower priority
clear interrupt flag
enable interrupt
Efficiency Evaluation
void __ISR(..) T4Interrupt( void)
{
_RA2 = 1;
// flag up, inside the ISR
<<< Interrupt service routine here >>
_RA2 = 0;
}
Di Jasio - Programming 32-bit Microcontrollers in C
// flag down, back to the main
Keyboard Buffering
A Circular Buffer
// circular buffer
unsigned char KCB[ KB_SIZE];
// head and tail or write and read pointers
volatile int KBR, KBW;
Di Jasio - Programming 32-bit Microcontrollers in C
Using the Circular Buffer
Insertion:
case PS2STOP:
if ( PS2IN & DATMASK)
{
KCB[ KBW] = KBDBuf;
// check if buffer full
if ( (KBW+1)%KB_SIZE !=
KBW++;
KBW %= KB_SIZE;
}
PS2State = PS2START;
break;
// verify stop bit
// write in the buffer
KBR)
// else increment ptr
// wrap around
Extraction:
int getKeyCode( char *c)
{
if ( KBR == KBW)
return FALSE;
// buffer empty
// else buffer contains at least one key code
*c = KCB[ KBR++];
// extract the first key code
KBR %= KB_SIZE;
// wrap around the pointer
return TRUE;
} // getKeyCode
Di Jasio - Programming 32-bit Microcontrollers in C
KeyCodes Decoding
// PS2 keyboard codes (standard set #2)
const char keyCodes[128]={
0, F9,
0, F5, F3, F1, F2, F12,
0, F10, F8, F6, F4, TAB, '`',
0,
0,
0,L_SHFT, 0,L_CTRL,'q','1',
0,
0,
0, 'z', 's', 'a', 'w', '2',
0,
0, 'c', 'x', 'd', 'e', '4', '3',
0,
0, ' ', 'v', 'f', 't', 'r', '5',
0,
0, 'n', 'b', 'h', 'g', 'y', '6',
0,
0,
0, 'm', 'j', 'u', '7', '8',
0,
0, ',', 'k', 'i', 'o', '0', '9',
0,
0, '.', '/', 'l', ';', 'p', '-',
0,
0,
0,'\'',
0, '[', '=',
0,
0,
CAPS, R_SHFT,ENTER, ']', 0,0x5c,
0,
0,
0,
0,
0,
0,
0,
0, BKSP, 0,
0, '1',
0, '4', '7',
0,
0,
0,
0, '.', '2', '5', '6', '8', ESC, NUM,
F11, '+', '3', '-', '*', '9',
0,
0
};
const char keySCodes[128] = {
0, F9,
0, F5, F3, F1, F2, F12,
0, F10, F8, F6, F4, TAB, '~',
0,
0,
0,L_SHFT, 0,L_CTRL,'Q','!',
0,
0,
0, 'Z', 'S', 'A', 'W', '@',
0,
0, 'C', 'X', 'D', 'E', '$', '#',
0,
0, ' ', 'V', 'F', 'T', 'R', '%',
0,
0, 'N', 'B', 'H', 'G', 'Y', '^',
0,
0,
0, 'M', 'J', 'U', '&', '*',
0,
0, '<', 'K', 'I', 'O', ')', '(',
0,
0, '>', '?', 'L', ':', 'P', '_',
0,
0,
0,'\"',
0, '{', '+',
0,
0,
CAPS, R_SHFT,ENTER, '}', 0, '|',
0,
0,
0,
0,
0,
0,
0,
0, BKSP, 0,
0, '1',
0, '4', '7',
0,
0,
0,
0, '.', '2', '5', '6', '8', ESC, NUM,
F11, '+', '3', '-', '*', '9',
0,
0
};
Di Jasio - Programming 32-bit Microcontrollers in C
//00
//08
//10
//18
//20
//28
//30
//38
//40
//48
//50
//58
//60
//68
//70
//78
//00
//08
//10
//18
//20
//28
//30
//38
//40
//48
//50
//58
//60
//68
//70
//78
getc()
char getC( void)
{
unsigned char c;
while( 1)
{
while( !KBDReady);
// wait for a key pressed
// check if it is a break code
while (KBDCode == 0xf0)
{
// consume the break code
KBDReady = 0;
// wait for a new key code
while ( !KBDReady);
// check if the shift button is released
if ( KBDCode == L_SHFT)
CapsFlag = 0;
// and discard it
KBDReady = 0;
// wait for the next key
while ( !KBDReady);
}
// check for special keys
if ( KBDCode == L_SHFT)
{
CapsFlag = 1;
KBDReady = 0;
}
else if ( KBDCode == CAPS)
{
CapsFlag = !CapsFlag;
KBDReady = 0;
}
Di Jasio - Programming 32-bit Microcontrollers in C
else // translate into an ASCII code
{
if ( CapsFlag)
c = keySCodes[KBDCode%128];
else
c = keyCodes[KBDCode%128];
break;
}
}
// consume the current character
KBDReady = 0;
return ( c);
} // getC
Download