Browse Source

Keyboard functionally working with very very good debouncing.

- defaultMap needs to be adjusted
- Modifiers are not yet accounted for when sending keypresses
- keypad needs to be added (detect,debounce, and send)
simple
Jacob Alexander 13 years ago
parent
commit
4b883dda10
3 changed files with 240 additions and 156 deletions
  1. 227
    156
      main.c
  2. 12
    0
      print.c
  3. 1
    0
      print.h

+ 227
- 156
main.c View File

@@ -32,8 +32,20 @@
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))

// Sleep defined in milliseconds
#define PRE_DRIVE_SLEEP 50
#define POST_DRIVE_SLEEP 50


// Number of keys
#define KEYBOARD_SIZE 63
#define KEYPAD_SIZE 16


// Debouncing Defines
#define SAMPLE_THRESHOLD 100
#define MAX_SAMPLES 127 // Max is 127, reaching 128 is very bad


// Verified Keypress Defines
#define USB_TRANSFER_DIVIDER 10 // 1024 == 1 Send of keypresses per second, 1 == 1 Send of keypresses per ~1 millisecond


// Drive Pin Defines
@@ -102,15 +114,15 @@
#define DETECT_group_array_9 {{KEY_0,KEY_O,KEY_L,KEY_H,KEY_5,KEY_R,KEY_N},{0,0,0,0,0,0,0}}
*/
// Switch Codes
#define DETECT_group_array_1 {11,27,43,40,6, 22,55}
#define DETECT_group_array_2 {10,26,58,41,7, 23,56}
#define DETECT_group_array_3 {9, 25,42,8, 24,57}
#define DETECT_group_array_4 {12,28,44,39,5, 21,54,59}
#define DETECT_group_array_5 {13,29,45,38,4, 20,53}
#define DETECT_group_array_6 {14,30,46,37,3, 19,52}
#define DETECT_group_array_7 {15,31,61,63,51,36,18,2}
#define DETECT_group_array_8 {16,32,47,35,1, 17,50,62}
#define DETECT_group_array_9 {48,34,33,49} // 49/60 are the same line
#define DETECT_group_array_1 {55,22,6 ,40,43,27,11}
#define DETECT_group_array_2 {56,23,7 ,41,58,26,10}
#define DETECT_group_array_3 {57,24,8 ,42,25,9}
#define DETECT_group_array_4 {54,21,5 ,39,44,28,12,59}
#define DETECT_group_array_5 {53,20,4 ,38,45,29,13}
#define DETECT_group_array_6 {52,19,3 ,37,46,30,14}
#define DETECT_group_array_7 {51,18,2 ,36,61,31,15,63}
#define DETECT_group_array_8 {50,17,1 ,35,47,32,16,62}
#define DETECT_group_array_9 {48,49,33,34} // 49/60 are the same line
#define DETECT_group_array_10 <blank>
#define DETECT_group_array_11 <blank>
#define DETECT_group_array_12 <blank>
@@ -121,8 +133,7 @@
#define DRIVE_DETECT(reg,pin,group) \
reg &= ~(1 << pin); \
detection(group); \
reg |= (1 << pin); \
_delay_ms(POST_DRIVE_SLEEP);
reg |= (1 << pin);

#define DD_CASE(number) \
case number:\
@@ -138,10 +149,13 @@
break;


// Updates the current detection sample and last sample bit
// Detection Macros (Probably don't need to be changed, but depending the matrix, may have to be)
// Determine if key is either normal or a modifier
#define DET_GROUP_CHECK(index) \
curDetect.keyDetectArray[curDetect.keyDetectCount++] = groupArray[index];
#define DET_GROUP_CHECK(index,test) \
if ( test ) { \
keyDetectArray[groupArray[index]]++; \
}


// XXX - Detection Groups
@@ -150,147 +164,135 @@

// Used for 1 detection group (Special group)
#define DET_GROUP_1 \
if ( !( PINB & (1 << 7) ) ) \
DET_GROUP_CHECK(0) \
if ( !( PINC & (1 << 0) ) ) \
DET_GROUP_CHECK(1) \
if ( !( PIND & (1 << 0) ) ) \
DET_GROUP_CHECK(2) \
if ( !( PIND & (1 << 1) ) ) \
DET_GROUP_CHECK(3)
DET_GROUP_CHECK(0,!( PINB & (1 << 7) )) \
DET_GROUP_CHECK(1,!( PINC & (1 << 0) )) \
DET_GROUP_CHECK(2,!( PIND & (1 << 0) )) \
DET_GROUP_CHECK(3,!( PIND & (1 << 1) )) \

// Used for 4 detection groups (Skips J1 P9)
#define DET_GROUP_2 \
if ( !( PINE & (1 << 7) ) ) \
DET_GROUP_CHECK(0) \
if ( !( PINB & (1 << 0) ) ) \
DET_GROUP_CHECK(1) \
if ( !( PINB & (1 << 1) ) ) \
DET_GROUP_CHECK(2) \
if ( !( PINB & (1 << 2) ) ) \
DET_GROUP_CHECK(3) \
if ( !( PINB & (1 << 3) ) ) \
DET_GROUP_CHECK(4) \
if ( !( PINB & (1 << 4) ) ) \
DET_GROUP_CHECK(5) \
if ( !( PINB & (1 << 5) ) ) \
DET_GROUP_CHECK(6) \
DET_GROUP_CHECK(0,!( PINE & (1 << 7) )) \
DET_GROUP_CHECK(1,!( PINB & (1 << 0) )) \
DET_GROUP_CHECK(2,!( PINB & (1 << 1) )) \
DET_GROUP_CHECK(3,!( PINB & (1 << 2) )) \
DET_GROUP_CHECK(4,!( PINB & (1 << 3) )) \
DET_GROUP_CHECK(5,!( PINB & (1 << 4) )) \
DET_GROUP_CHECK(6,!( PINB & (1 << 5) )) \

// Used for 1 detection group (Skips J1 P6 and J1 P9)
#define DET_GROUP_3 \
if ( !( PINE & (1 << 7) ) ) \
DET_GROUP_CHECK(0) \
if ( !( PINB & (1 << 0) ) ) \
DET_GROUP_CHECK(1) \
if ( !( PINB & (1 << 1) ) ) \
DET_GROUP_CHECK(2) \
if ( !( PINB & (1 << 2) ) ) \
DET_GROUP_CHECK(3) \
if ( !( PINB & (1 << 4) ) ) \
DET_GROUP_CHECK(4) \
if ( !( PINB & (1 << 5) ) ) \
DET_GROUP_CHECK(5) \
DET_GROUP_CHECK(0,!( PINE & (1 << 7) )) \
DET_GROUP_CHECK(1,!( PINB & (1 << 0) )) \
DET_GROUP_CHECK(2,!( PINB & (1 << 1) )) \
DET_GROUP_CHECK(3,!( PINB & (1 << 2) )) \
DET_GROUP_CHECK(4,!( PINB & (1 << 4) )) \
DET_GROUP_CHECK(5,!( PINB & (1 << 5) )) \

// Used for 3 detection groups (No skips, except special group 1)
#define DET_GROUP_4 \
if ( !( PINE & (1 << 7) ) ) \
DET_GROUP_CHECK(0) \
if ( !( PINB & (1 << 0) ) ) \
DET_GROUP_CHECK(1) \
if ( !( PINB & (1 << 1) ) ) \
DET_GROUP_CHECK(2) \
if ( !( PINB & (1 << 2) ) ) \
DET_GROUP_CHECK(3) \
if ( !( PINB & (1 << 3) ) ) \
DET_GROUP_CHECK(4) \
if ( !( PINB & (1 << 4) ) ) \
DET_GROUP_CHECK(5) \
if ( !( PINB & (1 << 5) ) ) \
DET_GROUP_CHECK(6) \
if ( !( PINB & (1 << 6) ) ) \
DET_GROUP_CHECK(7) \
DET_GROUP_CHECK(0,!( PINE & (1 << 7) )) \
DET_GROUP_CHECK(1,!( PINB & (1 << 0) )) \
DET_GROUP_CHECK(2,!( PINB & (1 << 1) )) \
DET_GROUP_CHECK(3,!( PINB & (1 << 2) )) \
DET_GROUP_CHECK(4,!( PINB & (1 << 3) )) \
DET_GROUP_CHECK(5,!( PINB & (1 << 4) )) \
DET_GROUP_CHECK(6,!( PINB & (1 << 5) )) \
DET_GROUP_CHECK(7,!( PINB & (1 << 6) )) \

// Combines the DET_GROUP_Xs above for the given groupArray
#define DET_GROUP(group,det_group) \
case group: \
{ \
uint8_t groupArray[DETECT_group_size_##group] = DETECT_group_array_##group; \
_delay_us(1); \
DET_GROUP_##det_group \
} \
break;

struct keys {
uint8_t keyDetectCount;
uint8_t keyDetectArray[40];
uint8_t modifiers;
} curDetect, prevDetect;

// Loop over all of the sampled keys of the given array
// If the number of samples is higher than the sample threshold, flag the high bit, clear otherwise
// This should be resetting VERY quickly, cutting off a potentially valid keypress is not an issue
#define DEBOUNCE_ASSESS(table,size) \
for ( uint8_t key = 1; key < size + 1; key++ ) {\
table[key] = ( table[key] & ~(1 << 7) ) > SAMPLE_THRESHOLD ? (1 << 7) : 0x00; \
} \


// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress)
// Other Bits: Pressed state sample counter
uint8_t keyDetectArray[KEYBOARD_SIZE + 1];
uint8_t keypadDetectArray[KEYPAD_SIZE + 1];

uint16_t sendKeypressCounter = 0;
volatile uint8_t sendKeypresses = 0;

static const uint8_t defaultMap[] = { 0,
KEY_INSERT,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSLASH,
KEY_ALT,
KEY_TAB,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_LEFT_BRACE,
KEY_RIGHT_BRACE,
KEY_DELETE,
KEY_UP,
KEY_CTRL,
KEY_CAPS_LOCK,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_SEMICOLON,
KEY_QUOTE,
KEY_ENTER,
KEY_DOWN,
KEY_ESC,
KEY_LEFT_SHIFT,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_RIGHT_SHIFT,
KEY_LEFT,
KEY_RIGHT,
KEY_SPACE };

// Scan Code Decoder (for debug)
void printDecodeScancode( int code )
{
static const uint8_t defaultMap[] = { 0,
KEY_INSERT,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_0,
KEY_MINUS,
KEY_EQUAL,
KEY_BACKSLASH,
KEY_ALT,
KEY_TAB,
KEY_Q,
KEY_W,
KEY_E,
KEY_R,
KEY_T,
KEY_Y,
KEY_U,
KEY_I,
KEY_O,
KEY_P,
KEY_LEFT_BRACE,
KEY_RIGHT_BRACE,
KEY_DELETE,
KEY_UP,
KEY_CTRL,
KEY_CAPS_LOCK,
KEY_A,
KEY_S,
KEY_D,
KEY_F,
KEY_G,
KEY_H,
KEY_J,
KEY_K,
KEY_L,
KEY_SEMICOLON,
KEY_QUOTE,
KEY_ENTER,
KEY_DOWN,
KEY_ESC,
KEY_LEFT_SHIFT,
KEY_Z,
KEY_X,
KEY_C,
KEY_V,
KEY_B,
KEY_N,
KEY_M,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_RIGHT_SHIFT,
KEY_LEFT,
KEY_RIGHT,
KEY_SPACE };

static const char* decodeArray[] = { "", "", "", "", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Enter", "Esc", "Backspace", "Tab", "Space", "-_", "=+", "[{", "]}", "\\", "#", ";:", "'\"", "`~", ",<", ".>", "/?", "Caps Lock", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Print Screen", "Scroll Lock", "Pause", "Insert", "Home", "Page Up", "Delete", "End", "Page Down", "Right", "Left", "Down", "Up", "Num Lock", "K1", "K2", "K3", "K4", "K5", "K6", "K7", "K8", "K9", "K0", "K." };
print_P( decodeArray[ defaultMap[code] ] );
@@ -298,8 +300,6 @@ void printDecodeScancode( int code )

void detection( int group )
{
_delay_ms(PRE_DRIVE_SLEEP);

// XXX Modify for different detection groups <-> groupArray mappings
switch ( group ) {
DET_GROUP(1,2)
@@ -317,7 +317,7 @@ void detection( int group )


// XXX This part is configurable
void pinSetup(void)
inline void pinSetup(void)
{
// For each pin, 0=input, 1=output
DDRA = 0x00;
@@ -327,18 +327,19 @@ void pinSetup(void)
DDRE = 0x43;
DDRF = 0x00;


// Setting pins to either high or pull-up resistor
PORTA = 0x00;
PORTA = 0xFF;
PORTB = 0xFF;
PORTC = 0x01;
PORTD = 0xFF;
PORTE = 0xC3;
PORTF = 0x00;
PORTF = 0xFF;
}

int main( void )
{
// set for 16 MHz clock
// Setup with 16 MHz clock
CPU_PRESCALE( 0 );

// Configuring Pins
@@ -354,13 +355,18 @@ int main( void )
// and do whatever it does to actually be ready for input
_delay_ms(1000);

// Make sure variables are properly initialized
curDetect.keyDetectCount = 0;
curDetect.modifiers = 0;
// Setup ISR Timer for flagging a kepress send to USB
// Set to 256 * 1024 (8 bit timer with Clock/1024 prescalar) timer
//
TCCR0A = 0x00;
TCCR0B = 0x03;
TIMSK0 = (1 << TOIE0);

// Main Detection Loop
// XXX Change number of ORDs if number of lines differ
for ( int group = 1;;group++ ) {
int8_t group = 1;
uint8_t count = 0;
for ( ;;group++ ) {
// XXX Change number of ORDs if number of lines (RowsxColumns) differ
// Determine which keys are being pressed
switch ( group ) {
DD_CASE_ORD(1)
@@ -374,45 +380,110 @@ int main( void )
DD_CASE_END(9,group)
}

// Check all Keyboard keys first
if ( group != -1 )
continue;

// Check Keypad keys
// TODO

// Check count to see if the sample threshold may have been reached, otherwise collect more data
count++;
if ( count < MAX_SAMPLES )
continue;

// Reset Sample Counter
count = 0;

// Assess debouncing sample table
DEBOUNCE_ASSESS(keyDetectArray,KEYBOARD_SIZE)
//DEBOUNCE_ASSESS(keypadDetectArray,KEYPAD_SIZE)

// Send keypresses over USB if the ISR has signalled that it's time
if ( !sendKeypresses )
continue;


// Detect Valid Keypresses - TODO
uint8_t validKeys = 0;
for ( uint8_t key = 0; key < KEYBOARD_SIZE + 1; key++ ) {
//phex(keyDetectArray[key]);
//print ("|");
if ( keyDetectArray[key] & (1 << 7) ) {
//print("0x");
//phex( key );
pint8( key );
print(" ");

// Too many keys
if ( validKeys == 6 )
break;
keyboard_keys[validKeys++] = defaultMap[key];
}
}
print(":\n");

// TODO undo potentially old keys
for ( uint8_t c = validKeys; c < 6; c++ )
keyboard_keys[c] = 0;


// Debugging Output
//phex(PINA);
//phex(PINF);
//print("\n");



// Print out the current keys pressed
if ( curDetect.keyDetectCount > 0 ) {
/*
if ( keyDetectCount > 0 ) {
print("Switch: ");
for ( int c = 0; c < curDetect.keyDetectCount; c++ ) {
for ( int c = 0; c < keyDetectCount; c++ ) {
print("0x");
phex( curDetect.keyDetectArray[c] );
phex( keyDetectArray[c] );
print("|");
//printDecodeScancode( curDetect.keyDetectArray[c] );
//printDecodeScancode( keyDetectArray[c] );
print(" ");

}
print("\n");
}
if ( curDetect.modifiers ) {
if ( modifiers ) {
print("Modifiers: ");
phex( curDetect.modifiers );
phex( modifiers );
print("\n");
}
*/

// After going through each of the key groups, send the detected keys and modifiers
// Currently limited to the USB spec (6 keys + modifiers)
// Making sure to pass zeros when there are no keys being pressed
for ( int c = 0; c < 6 && c < curDetect.keyDetectCount; c++ )
keyboard_keys[c] = c < curDetect.keyDetectCount ? curDetect.keyDetectArray[c] : 0;
/*
for ( int c = 0; c < 6 && c < keyDetectCount; c++ )
keyboard_keys[c] = c < keyDetectCount ? keyDetectArray[c] : 0;

// Modifiers
keyboard_modifier_keys = curDetect.modifiers;
keyboard_modifier_keys = modifiers;
*/

// Send keypresses
//usb_keyboard_send();
usb_keyboard_send();

// Cleanup
curDetect.keyDetectCount = 0;
curDetect.modifiers = 0;
// Clear sendKeypresses Flag
sendKeypresses = 0;
}

// usb_keyboard_press(KEY_B, KEY_SHIFT);
return 0;
}

ISR( TIMER0_OVF_vect )
{
sendKeypressCounter++;
if ( sendKeypressCounter > USB_TRANSFER_DIVIDER ) {
sendKeypressCounter = 0;
sendKeypresses = 1;
}
}


+ 12
- 0
print.c View File

@@ -57,6 +57,18 @@ void phex16(unsigned int i)
phex(i);
}

void pint8(unsigned char c)
{
// 100's
if ( c > 99 )
usb_debug_putchar( c / 100 + '0' );

// 10's - Note: Uses dropping of decimal of float/double types
if ( c > 9 )
usb_debug_putchar( c / 10 - (c / 100) * 10 + '0' );

// 1's
usb_debug_putchar( c % 10 + '0' );
}



+ 1
- 0
print.h View File

@@ -12,5 +12,6 @@
void print_P(const char *s);
void phex(unsigned char c);
void phex16(unsigned int i);
void pint8(unsigned char c);

#endif