- Added better string handling and canned messages - Added LED error function - Moved code around - Prepared the matrix code for multiple styles of scanning (changed at compile time)simple
@@ -48,6 +48,7 @@ TARGET = main | |||
SRC = $(TARGET).c \ | |||
print.c \ | |||
usb_keyboard_debug.c \ | |||
scan_loop.c | |||
#usb_keyboard.c | |||
@@ -0,0 +1,228 @@ | |||
#ifndef __KEYMAP_h | |||
#define __KEYMAP_h | |||
#include "usb_keys.h" | |||
// Modifier Mask | |||
#define MODIFIERS_KEYPAD 0 | |||
#define MODIFIERS_KEYBOARD 4 | |||
static uint8_t keypad_modifierMask[] = {}; | |||
static uint8_t keyboard_modifierMask[] = { 1, 17, 33, 49 }; | |||
static uint8_t alternate_modifierMask[] = { 1, 17, 33, 49, 62 }; | |||
// Default 1-indexed key mappings | |||
static uint8_t keypadDefaultMap[] = { 0, | |||
KEYPAD_7, | |||
KEYPAD_8, | |||
KEYPAD_9, | |||
KEYPAD_SLASH, | |||
KEYPAD_4, | |||
KEYPAD_5, | |||
KEYPAD_6, | |||
KEYPAD_ASTERIX, | |||
KEYPAD_1, | |||
KEYPAD_2, | |||
KEYPAD_3, | |||
KEYPAD_MINUS, | |||
KEYPAD_ENTER, | |||
KEYPAD_0, | |||
KEYPAD_PERIOD, | |||
KEYPAD_PLUS }; | |||
static uint8_t defaultMap[] = { 0, | |||
KEY_GUI, | |||
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_TILDE, | |||
KEY_BACKSPACE, | |||
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_LLOCK, | |||
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 uint8_t navigationMap[] = { 0, | |||
KEY_GUI, | |||
KEY_F1, | |||
KEY_F2, | |||
KEY_F3, | |||
KEY_F4, | |||
KEY_F5, | |||
KEY_F6, | |||
KEY_F7, | |||
KEY_F8, | |||
KEY_F9, | |||
KEY_F10, | |||
KEY_F11, | |||
KEY_F12, | |||
KEY_INSERT, | |||
KEY_DELETE, | |||
KEY_BACKSPACE, | |||
KEY_ALT, | |||
KEY_CAPS_LOCK, | |||
0, | |||
0, | |||
0, | |||
0, | |||
0, | |||
0, | |||
0, | |||
KEY_SYSREQ_ATT, | |||
KEY_SCROLL_LOCK, | |||
KEY_PAUSE, | |||
KEY_UP, | |||
0, | |||
0, | |||
0, | |||
KEY_CTRL, | |||
KEY_CAPS_LLOCK, | |||
0, | |||
0, | |||
0, | |||
0, | |||
0, | |||
KEYPAD_ASTERIX, | |||
KEYPAD_SLASH, | |||
KEY_HOME, | |||
KEY_PAGE_UP, | |||
KEY_LEFT, | |||
KEY_RIGHT, | |||
KEY_ENTER, | |||
0, | |||
KEY_ESC, | |||
KEY_LEFT_SHIFT, | |||
0, | |||
0, | |||
0, | |||
0, | |||
0, | |||
KEYPAD_PLUS, | |||
KEYPAD_MINUS, | |||
KEY_END, | |||
KEY_PAGE_DOWN, | |||
KEY_DOWN, | |||
KEY_RIGHT_SHIFT, | |||
165, | |||
KEY_RIGHT_ALT, | |||
KEY_SPACE }; | |||
static uint8_t colemakMap[] = { 0, | |||
KEY_GUI, | |||
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_TILDE, | |||
KEY_BACKSPACE, | |||
KEY_ALT, | |||
KEY_TAB, | |||
KEY_Q, | |||
KEY_W, | |||
KEY_F, | |||
KEY_P, | |||
KEY_G, | |||
KEY_J, | |||
KEY_L, | |||
KEY_U, | |||
KEY_Y, | |||
KEY_SEMICOLON, | |||
KEY_LEFT_BRACE, | |||
KEY_RIGHT_BRACE, | |||
KEY_DELETE, | |||
KEY_PAGE_UP, | |||
KEY_CTRL, | |||
KEY_CAPS_LLOCK, | |||
KEY_A, | |||
KEY_R, | |||
KEY_S, | |||
KEY_T, | |||
KEY_D, | |||
KEY_H, | |||
KEY_N, | |||
KEY_E, | |||
KEY_I, | |||
KEY_O, | |||
KEY_QUOTE, | |||
KEY_ENTER, | |||
KEY_PAGE_DOWN, | |||
KEY_ESC, | |||
KEY_LEFT_SHIFT, | |||
KEY_Z, | |||
KEY_X, | |||
KEY_C, | |||
KEY_V, | |||
KEY_B, | |||
KEY_K, | |||
KEY_M, | |||
KEY_COMMA, | |||
KEY_PERIOD, | |||
KEY_SLASH, | |||
KEY_RIGHT_SHIFT, | |||
165, | |||
KEY_RIGHT_ALT, | |||
KEY_SPACE }; | |||
#endif | |||
@@ -23,7 +23,7 @@ | |||
#include <avr/pgmspace.h> | |||
#include <avr/interrupt.h> | |||
#include <util/delay.h> | |||
#include "usb_keys.h" | |||
//#include "usb_keys.h" | |||
#include "scan_loop.h" | |||
//#include "layouts.h" | |||
//#include "usb_keyboard.h" | |||
@@ -35,226 +35,20 @@ | |||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n)) | |||
// Debouncing Defines | |||
#define SAMPLE_THRESHOLD 110 | |||
#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 | |||
/* | |||
// Number of keys | |||
#define KEYBOARD_SIZE 63 | |||
#define KEYPAD_SIZE 16 | |||
// Drive Pin Defines | |||
#define DRIVE_reg_1 PORTD | |||
#define DRIVE_reg_2 PORTD | |||
#define DRIVE_reg_3 PORTD | |||
#define DRIVE_reg_4 PORTD | |||
#define DRIVE_reg_5 PORTD | |||
#define DRIVE_reg_6 PORTD | |||
#define DRIVE_reg_7 PORTE | |||
#define DRIVE_reg_8 PORTE | |||
#define DRIVE_reg_9 PORTE | |||
#define DRIVE_reg_10 <blank> | |||
#define DRIVE_reg_11 <blank> | |||
#define DRIVE_reg_12 <blank> | |||
#define DRIVE_pin_1 2 | |||
#define DRIVE_pin_2 3 | |||
#define DRIVE_pin_3 4 | |||
#define DRIVE_pin_4 5 | |||
#define DRIVE_pin_5 6 | |||
#define DRIVE_pin_6 7 | |||
#define DRIVE_pin_7 0 | |||
#define DRIVE_pin_8 1 | |||
#define DRIVE_pin_9 6 | |||
#define DRIVE_pin_10 <blank> | |||
#define DRIVE_pin_11 <blank> | |||
#define DRIVE_pin_12 <blank> | |||
// Detect Pin/Group Defines | |||
#define DETECT_group_1 1 | |||
#define DETECT_group_2 2 | |||
#define DETECT_group_3 3 | |||
#define DETECT_group_4 4 | |||
#define DETECT_group_5 5 | |||
#define DETECT_group_6 6 | |||
#define DETECT_group_7 7 | |||
#define DETECT_group_8 8 | |||
#define DETECT_group_9 9 | |||
#define DETECT_group_10 <blank> | |||
#define DETECT_group_11 <blank> | |||
#define DETECT_group_12 <blank> | |||
#define DETECT_group_size_1 7 | |||
#define DETECT_group_size_2 7 | |||
#define DETECT_group_size_3 6 | |||
#define DETECT_group_size_4 8 | |||
#define DETECT_group_size_5 7 | |||
#define DETECT_group_size_6 7 | |||
#define DETECT_group_size_7 8 | |||
#define DETECT_group_size_8 8 | |||
#define DETECT_group_size_9 4 | |||
#define DETECT_group_size_10 <blank> | |||
#define DETECT_group_size_11 <blank> | |||
#define DETECT_group_size_12 <blank> | |||
// Switch Codes | |||
#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> | |||
// Drive Macros (Generally don't need to be changed), except for maybe DRIVE_DETECT | |||
// Sleep is for signal debouncing | |||
#define DRIVE_DETECT(reg,pin,group) \ | |||
reg &= ~(1 << pin); \ | |||
detection(group); \ | |||
reg |= (1 << pin); \ | |||
_delay_us(1); | |||
#define DD_CASE(number) \ | |||
case number:\ | |||
DRIVE_DETECT(DRIVE_reg_##number, DRIVE_pin_##number, DETECT_group_##number) | |||
#define DD_CASE_ORD(number) \ | |||
DD_CASE(number) \ | |||
break; | |||
#define DD_CASE_END(number,var) \ | |||
DD_CASE(number) \ | |||
var = -1; \ | |||
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,test) \ | |||
if ( test ) { \ | |||
keyDetectArray[groupArray[index]]++; \ | |||
} | |||
// XXX - Detection Groups | |||
// Checks each of the specified pins, and then if press detected, determine if the key is normal or a modifier | |||
// Inverse logic applies for the PINs | |||
// Used for 1 detection group (Special group) | |||
#define DET_GROUP_1 \ | |||
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 \ | |||
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 \ | |||
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 \ | |||
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; | |||
// 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; \ | |||
} \ | |||
// Keypad detection | |||
// Each switch has it's own detection line, inverse logic | |||
#define KEYPAD_DETECT(test,switch_code) \ | |||
if ( !(test) ) { \ | |||
keypadDetectArray[switch_code]++; \ | |||
} \ | |||
// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) | |||
// Other Bits: Pressed state sample counter | |||
uint8_t keyboardDetectArray[KEYBOARD_SIZE + 1]; | |||
// Interrupt Variables | |||
uint16_t sendKeypressCounter = 0; | |||
volatile uint8_t sendKeypresses = 0; | |||
void detection( int group ) | |||
{ | |||
// XXX Modify for different detection groups <-> groupArray mappings | |||
switch ( group ) { | |||
DET_GROUP(1,2) | |||
DET_GROUP(2,2) | |||
DET_GROUP(3,3) | |||
DET_GROUP(4,4) | |||
DET_GROUP(5,2) | |||
DET_GROUP(6,2) | |||
DET_GROUP(7,4) | |||
DET_GROUP(8,4) | |||
DET_GROUP(9,1) | |||
} | |||
} | |||
*/ | |||
// Error LED Control | |||
void errorLED( uint8_t on ) | |||
{ | |||
// Error LED On | |||
if ( on ) { | |||
DDRD |= (1<<6); | |||
PORTD |= (1<<6); | |||
} | |||
// Error LED Off | |||
else { | |||
DDRD &= ~(1<<6); | |||
PORTD &= ~(1<<6); | |||
} | |||
} | |||
@@ -282,39 +76,6 @@ inline void pinSetup(void) | |||
PORTE = 0x00; | |||
PORTF = 0x00; | |||
} | |||
/* | |||
// Given a sampling array, and the current number of detected keypress | |||
// Add as many keypresses from the sampling array to the USB key send array as possible. | |||
void keyPressDetection( uint8_t *keys, uint8_t *validKeys, uint8_t numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) { | |||
for ( uint8_t key = 0; key < numberOfKeys + 1; key++ ) { | |||
if ( keys[key] & (1 << 7) ) { | |||
pint8( key ); | |||
//print(" "); | |||
uint8_t modFound = 0; | |||
// Determine if the key is a modifier | |||
for ( uint8_t mod = 0; mod < numberOfModifiers; mod++ ) { | |||
// Modifier found | |||
if ( modifiers[mod] == key ) { | |||
keyboard_modifier_keys |= map[key]; | |||
modFound = 1; | |||
break; | |||
} | |||
} | |||
if ( modFound ) | |||
continue; | |||
// Too many keys | |||
if ( *validKeys == 6 ) | |||
break; | |||
// Allow ignoring keys with 0's | |||
if ( map[key] != 0 ) | |||
keyboard_keys[(*validKeys)++] = map[key]; | |||
} | |||
} | |||
} | |||
*/ | |||
int main( void ) | |||
{ | |||
@@ -340,117 +101,22 @@ int main( void ) | |||
TCCR0B = 0x03; | |||
TIMSK0 = (1 << TOIE0); | |||
uint16_t led = 0; | |||
// Main Detection Loop | |||
while ( 1 ) { | |||
scan_loop(); | |||
//scan_loop(); | |||
// Loop should never get here (indicate error) | |||
errorLED( 1 ); | |||
// TODO HID Debug message | |||
// HID Debug Error message | |||
erro_print("Detection loop error, this is very bad...bug report!"); | |||
} | |||
} | |||
/* | |||
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) | |||
DD_CASE_ORD(2) | |||
DD_CASE_ORD(3) | |||
DD_CASE_ORD(4) | |||
DD_CASE_ORD(5) | |||
DD_CASE_ORD(6) | |||
DD_CASE_ORD(7) | |||
DD_CASE_ORD(8) | |||
DD_CASE_END(9,group) | |||
} | |||
// Check all Keyboard keys first | |||
if ( group != -1 ) | |||
continue; | |||
// Check Keypad keys | |||
KEYPAD_DETECT(PINA & (1 << 0),11) | |||
KEYPAD_DETECT(PINA & (1 << 1),3) | |||
KEYPAD_DETECT(PINA & (1 << 2),7) | |||
KEYPAD_DETECT(PINA & (1 << 3),4) | |||
KEYPAD_DETECT(PINA & (1 << 4),15) | |||
KEYPAD_DETECT(PINA & (1 << 5),6) | |||
KEYPAD_DETECT(PINA & (1 << 6),2) | |||
KEYPAD_DETECT(PINA & (1 << 7),10) | |||
KEYPAD_DETECT(PINF & (1 << 0),8) | |||
KEYPAD_DETECT(PINF & (1 << 1),12) | |||
KEYPAD_DETECT(PINF & (1 << 2),16) | |||
KEYPAD_DETECT(PINF & (1 << 3),13) | |||
KEYPAD_DETECT(PINF & (1 << 4),1) | |||
KEYPAD_DETECT(PINF & (1 << 5),5) | |||
KEYPAD_DETECT(PINF & (1 << 6),9) | |||
KEYPAD_DETECT(PINF & (1 << 7),14) | |||
// 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; | |||
uint8_t *keyboard_MODMASK = keyboard_modifierMask; | |||
uint8_t keyboard_NUMMODS = MODIFIERS_KEYBOARD; | |||
uint8_t *keyboard_MAP = defaultMap; | |||
uint8_t *keypad_MODMASK = keypad_modifierMask; | |||
uint8_t keypad_NUMMODS = MODIFIERS_KEYPAD; | |||
uint8_t *keypad_MAP = keypadDefaultMap; | |||
// Map selection - CapsLock FN | |||
if ( keyDetectArray[34] & (1 << 7) ) { // CapsLock FN Modifier | |||
keyboard_MAP = colemakMap; | |||
keyboard_MODMASK = alternate_modifierMask; | |||
keyboard_NUMMODS = 5; | |||
// Function Key | |||
if ( keyDetectArray[61] & (1 << 7) ) { | |||
keyboard_MAP = navigationMap; | |||
} | |||
} | |||
keyPressDetection( keyDetectArray, &validKeys, KEYBOARD_SIZE, keyboard_MODMASK, keyboard_NUMMODS, keyboard_MAP ); | |||
keyPressDetection( keypadDetectArray, &validKeys, KEYPAD_SIZE, keypad_MODMASK, keypad_NUMMODS, keypad_MAP ); | |||
//print(":\n"); | |||
// TODO undo potentially old keys | |||
for ( uint8_t c = validKeys; c < 6; c++ ) | |||
keyboard_keys[c] = 0; | |||
// Send keypresses | |||
usb_keyboard_send(); | |||
// Clear sendKeypresses Flag | |||
sendKeypresses = 0; | |||
// Clear modifiers | |||
keyboard_modifier_keys = 0; | |||
} | |||
return 0; | |||
} | |||
*/ | |||
// Timer Interrupt for flagging a send of the sampled key detection data to the USB host | |||
uint16_t sendKeypressCounter = 0; | |||
ISR( TIMER0_OVF_vect ) | |||
{ | |||
sendKeypressCounter++; |
@@ -0,0 +1,181 @@ | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
* in the Software without restriction, including without limitation the rights | |||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
* copies of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included in | |||
* all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
* THE SOFTWARE. | |||
*/ | |||
#include "matrix.h" | |||
#define REG_SET(reg) reg |= (1 << ( matrix[row][col] % 10 ) ) | |||
#define PIN_SET_COL(pin) \ | |||
switch ( scanMode ) { \ | |||
case scanCol: \ | |||
case scanCol_powrRow: \ | |||
case scanDual: \ | |||
REG_SET(port##pin); break; \ | |||
case scanRow_powrCol: REG_SET(ddr##pin); REG_SET(port##pin); break; \ | |||
} \ | |||
break | |||
#define PIN_SET_ROW(pin) \ | |||
switch ( scanMode ) { \ | |||
case scanRow: \ | |||
case scanRow_powrCol: \ | |||
case scanDual: \ | |||
REG_SET(port##pin); break; \ | |||
case scanCol_powrRow: REG_SET(ddr##pin); REG_SET(port##pin); break; \ | |||
} \ | |||
break | |||
#define PIN_CASE(pinLetter) \ | |||
case pin##pinLetter##0: \ | |||
case pin##pinLetter##1: \ | |||
case pin##pinLetter##2: \ | |||
case pin##pinLetter##3: \ | |||
case pin##pinLetter##4: \ | |||
case pin##pinLetter##5: \ | |||
case pin##pinLetter##6: \ | |||
case pin##pinLetter##7 | |||
#define PIN_TEST_COL(pin) \ | |||
if ( !( pin & ( 1 << ( matrix[0][col] % 10 ) ) \ | |||
detectArray[matrix[row][col]]++; \ | |||
break | |||
void matrix_pinSetup( uint8_t *matrix ) | |||
{ | |||
// Setup the variables | |||
uint8_t portA = 0x00; | |||
uint8_t portB = 0x00; | |||
uint8_t portC = 0x00; | |||
uint8_t portD = 0x00; | |||
uint8_t portE = 0x00; | |||
uint8_t portF = 0x00; | |||
uint8_t ddrA = 0x00; | |||
uint8_t ddrB = 0x00; | |||
uint8_t ddrC = 0x00; | |||
uint8_t ddrD = 0x00; | |||
uint8_t ddrE = 0x00; | |||
uint8_t ddrF = 0x00; | |||
// Loop through all the pin assignments, for the initial pin settings | |||
int row, col; | |||
// Rows | |||
for ( row = 1; row < sizeof(matrix); row++ ) { | |||
switch ( matrix[row][col] ) { | |||
PIN_CASE(A): | |||
PIN_SET_ROW(A); | |||
PIN_CASE(B): | |||
PIN_SET_ROW(B); | |||
PIN_CASE(C): | |||
PIN_SET_ROW(C); | |||
PIN_CASE(D): | |||
PIN_SET_ROW(D); | |||
PIN_CASE(E): | |||
PIN_SET_ROW(E); | |||
PIN_CASE(F): | |||
PIN_SET_ROW(F); | |||
default: | |||
continue; | |||
} | |||
} | |||
// Columns | |||
for ( col = 1; col < sizeof(matrix[0]); row++ ) { | |||
switch ( matrix[row][col] ) { | |||
PIN_CASE(A): | |||
PIN_SET_COL(A); | |||
PIN_CASE(B): | |||
PIN_SET_COL(B); | |||
PIN_CASE(C): | |||
PIN_SET_COL(C); | |||
PIN_CASE(D): | |||
PIN_SET_COL(D); | |||
PIN_CASE(E): | |||
PIN_SET_COL(E); | |||
PIN_CASE(F): | |||
PIN_SET_COL(F); | |||
default: | |||
continue; | |||
} | |||
} | |||
// Setting the pins | |||
DDRA = ddrA; | |||
DDRB = ddrB; | |||
DDRC = ddrC; | |||
DDRD = ddrD; | |||
DDRE = ddrE; | |||
DDRF = ddrF; | |||
PORTA = portA; | |||
PORTB = portB; | |||
PORTC = portC; | |||
PORTD = portD; | |||
PORTE = portE; | |||
PORTF = portF; | |||
} | |||
// TODO Proper matrix scanning | |||
void matrix_scan( uint8_t *matrix, uint8_t *detectArray ) | |||
{ | |||
// Column Scan | |||
#if scanMode == scanCol | |||
uint8_t col = 1; | |||
uint8_t row = 1; | |||
for ( ; col < sizeof(matrix[1]); col++ ) { | |||
switch ( matrix[0][col] / 10 ) { | |||
case 0: // PINA | |||
PIN_TEST_COL(PINA); | |||
case 1: // PINB | |||
PIN_TEST_COL(PINB); | |||
case 2: // PINC | |||
PIN_TEST_COL(PINC); | |||
case 3: // PIND | |||
PIN_TEST_COL(PIND); | |||
case 4: // PINE | |||
PIN_TEST_COL(PINE); | |||
case 5: // PINF | |||
PIN_TEST_COL(PINF); | |||
} | |||
} | |||
#endif | |||
// Row Scan | |||
#if scanMode == scanRow | |||
#endif | |||
// Column Scan, Power Row | |||
#if scanMode == scanCol_powrRow | |||
#endif | |||
// Row Scan, Power Column | |||
#if scanMode == scanRow_powrCol | |||
#endif | |||
// Dual Scan | |||
#if scanMode == scanDual | |||
#endif | |||
} | |||
@@ -0,0 +1,151 @@ | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
* in the Software without restriction, including without limitation the rights | |||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
* copies of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included in | |||
* all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
* THE SOFTWARE. | |||
*/ | |||
#ifndef __MATRIX_H | |||
#define __MATRIX_H | |||
// ----- Quick Map (don't change) ----- | |||
#define pinA0 0 | |||
#define pinA1 1 | |||
#define pinA2 2 | |||
#define pinA3 3 | |||
#define pinA4 4 | |||
#define pinA5 5 | |||
#define pinA6 6 | |||
#define pinA7 7 | |||
#define pinB0 10 | |||
#define pinB1 11 | |||
#define pinB2 12 | |||
#define pinB3 13 | |||
#define pinB4 14 | |||
#define pinB5 15 | |||
#define pinB6 16 | |||
#define pinB7 17 | |||
#define pinC0 20 | |||
#define pinC1 21 | |||
#define pinC2 22 | |||
#define pinC3 23 | |||
#define pinC4 24 | |||
#define pinC5 25 | |||
#define pinC6 26 | |||
#define pinC7 27 | |||
#define pinD0 30 | |||
#define pinD1 31 | |||
#define pinD2 32 | |||
#define pinD3 33 | |||
#define pinD4 34 | |||
#define pinD5 35 | |||
#define pinD6 36 | |||
#define pinD7 37 | |||
#define pinE0 40 | |||
#define pinE1 41 | |||
#define pinE2 42 | |||
#define pinE3 43 | |||
#define pinE4 44 | |||
#define pinE5 45 | |||
#define pinE6 46 | |||
#define pinE7 47 | |||
#define pinF0 50 | |||
#define pinF1 51 | |||
#define pinF2 52 | |||
#define pinF3 53 | |||
#define pinF4 54 | |||
#define pinF5 55 | |||
#define pinF6 56 | |||
#define pinF7 57 | |||
#define pinNULL 128 | |||
// ----- Scan Mode (usually dual-scan) ----- | |||
// Ordered by increasing memory/CPU usage | |||
#define scanRow 0 // Needed for powered switches (Hall-Effect) | |||
#define scanCol 1 // Opposite of scanRow | |||
#define scanRow_powrCol 2 // NKRO supported (simple detection) | |||
#define scanCol_powrRow 3 // Opposite of scanRow_powrCol | |||
#define scanDual 4 // Typical ~2KRO matrix | |||
// ----- Scan Mode Setting ----- | |||
#define scanMode scanCol | |||
// ----- Key Settings ----- | |||
#define keyboardSize 16 // # of keys | |||
// ----- Matrix Configuration ----- | |||
static uint8_t matrix_pinout[][] = { | |||
// Just layout the matrix by rows and columns | |||
// Usually you'll want to set the scanMode above to scanDual or scanCol_powrRow/scanRow_powrCol | |||
// The mode allows for optimization in the kind of scanning algorithms that are done | |||
// | |||
// The key numbers are used to translate into the keymap table (array) (and always start from 1, not 0). | |||
// See the keymap.h file for the various preconfigured arrays. | |||
// Scan Mode | Col 1 | Col 2 | Col 3 | Col 4 | Col 4 | ... | |||
// ------------------------------------------------------- | |||
// Row 1 | Key 1 Key 7 Key32 ... | |||
// Row 2 | Key 3 Key92 ... | |||
// Row 3 | Key23 ... | |||
// Row 4 | ... | |||
// Row 5 | | |||
// ... | | |||
{ scanMode, pinF4, pinA6, pinA1, pinA3, pinF5, pinA5, pinA2, pinF0, pinF6, pinA7, pinA0, pinF1, pinF3, pinF7, pinA4, pinF2 }, | |||
{ pinNULL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, | |||
// Example Rows | |||
//{ pinE0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, | |||
//{ pinE1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, }, | |||
}; | |||
// ----- Variables ----- | |||
// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) | |||
// Other Bits: Pressed state sample counter | |||
uint8_t keyboardDetectArray[keyboardSize + 1]; | |||
// ----- Functions ----- | |||
#endif // __MATRIX_H | |||
@@ -1,6 +1,4 @@ | |||
/* Very basic print functions, intended to be used with usb_debug_only.c | |||
* http://www.pjrc.com/teensy/ | |||
* Copyright (c) 2008 PJRC.COM, LLC | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
@@ -21,54 +19,172 @@ | |||
* THE SOFTWARE. | |||
*/ | |||
// Version 1.0: Initial Release | |||
// Compiler Includes | |||
#include <stdarg.h> | |||
// AVR Includes | |||
#include <avr/io.h> | |||
#include <avr/pgmspace.h> | |||
// Project Includes | |||
#include "print.h" | |||
void print_P(const char *s) | |||
// Defines | |||
// USB HID String Output | |||
void usb_debug_putstr( char* s ) | |||
{ | |||
while ( *s != '\0' ) | |||
usb_debug_putchar( *s++ ); | |||
} | |||
// Multiple string Output | |||
void usb_debug_putstrs( char* first, ... ) | |||
{ | |||
// Initialize the variadic function parameter list | |||
va_list ap; | |||
// Get the first parameter | |||
va_start( ap, first ); | |||
char *cur = first; | |||
// Loop through the variadic list until "\0\0\0" is found | |||
while ( !( cur[0] == '\0' && cur[1] == '\0' && cur[2] == '\0' ) ) | |||
{ | |||
// Print out the given string | |||
usb_debug_putstr( cur ); | |||
// Get the next argument ready | |||
cur = va_arg( ap, char* ); | |||
} | |||
va_end( ap ); // Not required, but good practice | |||
} | |||
// Print a constant string | |||
void _print(const char *s) | |||
{ | |||
char c; | |||
while (1) { | |||
c = pgm_read_byte(s++); | |||
if (!c) break; | |||
if (c == '\n') usb_debug_putchar('\r'); | |||
// Acquire the character from flash, and print it, as long as it's not NULL | |||
// Also, if a newline is found, print a carrige return as well | |||
while ( ( c = pgm_read_byte(s++) ) != '\0' ) | |||
{ | |||
if ( c == '\n' ) | |||
usb_debug_putchar('\r'); | |||
usb_debug_putchar(c); | |||
} | |||
} | |||
void phex1(unsigned char c) | |||
// String Functions | |||
void int8ToStr( uint8_t in, char* out ) | |||
{ | |||
usb_debug_putchar(c + ((c < 10) ? '0' : 'A' - 10)); | |||
// Position and sign containers | |||
uint8_t pos; | |||
pos = 0; | |||
// Evaluate through digits as decimal | |||
do | |||
{ | |||
out[pos++] = in % 10 + '0'; | |||
} | |||
while ( (in /= 10) > 0 ); | |||
// Append null | |||
out[pos] = '\0'; | |||
// Reverse the string to the correct order | |||
revsStr(out); | |||
} | |||
void phex(unsigned char c) | |||
void int16ToStr( uint16_t in, char* out ) | |||
{ | |||
phex1(c >> 4); | |||
phex1(c & 15); | |||
// Position and sign containers | |||
uint16_t pos; | |||
pos = 0; | |||
// Evaluate through digits as decimal | |||
do | |||
{ | |||
out[pos++] = in % 10 + '0'; | |||
} | |||
while ( (in /= 10) > 0 ); | |||
// Append null | |||
out[pos] = '\0'; | |||
// Reverse the string to the correct order | |||
revsStr(out); | |||
} | |||
void phex16(unsigned int i) | |||
void hexToStr_op( uint16_t in, char* out, uint8_t op ) | |||
{ | |||
phex(i >> 8); | |||
phex(i); | |||
// Position container | |||
uint16_t pos = 0; | |||
// Evaluate through digits as hex | |||
do | |||
{ | |||
uint16_t cur = in % 16; | |||
out[pos++] = cur + (( cur < 10 ) ? '0' : 'A' - 10); | |||
} | |||
while ( (in /= 16) > 0 ); | |||
// Output formatting options | |||
switch ( op ) | |||
{ | |||
case 1: // Add 0x | |||
out[pos++] = 'x'; | |||
out[pos++] = '0'; | |||
break; | |||
case 2: // 8-bit padding | |||
case 4: // 16-bit padding | |||
while ( pos < op ) | |||
out[pos++] = '0'; | |||
break; | |||
} | |||
// Append null | |||
out[pos] = '\0'; | |||
// Reverse the string to the correct order | |||
revsStr(out); | |||
} | |||
void pint8(unsigned char c) | |||
void revsStr( char* in ) | |||
{ | |||
// 100's | |||
if ( c > 99 ) | |||
usb_debug_putchar( c / 100 + '0' ); | |||
// Iterators | |||
int i, j; | |||
// 10's - Note: Uses dropping of decimal of float/double types | |||
if ( c > 9 ) | |||
usb_debug_putchar( c / 10 - (c / 100) * 10 + '0' ); | |||
// Temp storage | |||
char c; | |||
// 1's | |||
usb_debug_putchar( c % 10 + '0' ); | |||
// Loop through the string, and reverse the order of the characters | |||
for ( i = 0, j = lenStr( in ) - 1; i < j; i++, j-- ) | |||
{ | |||
c = in[i]; | |||
in[i] = in[j]; | |||
in[j] = c; | |||
} | |||
} | |||
uint16_t lenStr( char* in ) | |||
{ | |||
// Iterator | |||
char *pos; | |||
// Loop until null is found | |||
for ( pos = in; *pos; pos++ ); | |||
// Return the difference between the pointers of in and pos (which is the string length) | |||
return (pos - in); | |||
} | |||
@@ -1,17 +1,87 @@ | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
* in the Software without restriction, including without limitation the rights | |||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
* copies of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included in | |||
* all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
* THE SOFTWARE. | |||
*/ | |||
#ifndef print_h__ | |||
#define print_h__ | |||
// AVR Includes | |||
#include <avr/pgmspace.h> | |||
// Project Includes | |||
#include "usb_keyboard_debug.h" | |||
// this macro allows you to write print("some text") and | |||
// the string is automatically placed into flash memory :) | |||
#define print(s) print_P(PSTR(s)) | |||
#define pchar(c) usb_debug_putchar(c) | |||
// Defines | |||
#define NL "\r\n" | |||
/* XXX | |||
* Note that all the variadic functions below, take comma separated string lists, they are purposely not printf style (simplicity) | |||
*/ | |||
// Function Aliases | |||
#define dPrint(c) usb_debug_putchar(c) | |||
#define dPrintStr(c) usb_debug_putstr (c) | |||
#define dPrintStrs(...) usb_debug_putstrs(__VA_ARGS__, "\0\0\0") // Convenience Variadic Macro | |||
#define dPrintStrNL(c) dPrintStrs (c, NL) // Appends New Line Macro | |||
#define dPrintStrsNL(...) usb_debug_putstrs(__VA_ARGS__, NL, "\0\0\0") // Appends New Line Macro | |||
// Special Msg Constructs (Uses VT100 tags) | |||
#define dPrintMsg(colour_code_str,msg,...) \ | |||
usb_debug_putstrs("\033[", colour_code_str, "m", msg, "\033[0m - ", __VA_ARGS__, NL, "\0\0\0") | |||
#define printMsg(colour_code_str,msg,str) \ | |||
print("\033[" colour_code_str "m" msg "\033[0m - " str NL) | |||
// Info Messages | |||
#define info_dPrint(...) dPrintMsg ("1;32", "INFO", __VA_ARGS__) // Info Msg | |||
#define info_print(str) printMsg ("1;32", "INFO", str) // Info Msg | |||
// Warning Messages | |||
#define warn_dPrint(...) dPrintMsg ("1;33", "WARNING", __VA_ARGS__) // Warning Msg | |||
#define warn_print(str) printMsg ("1;33", "WARNING", str) // Warning Msg | |||
void print_P(const char *s); | |||
void phex(unsigned char c); | |||
void phex16(unsigned int i); | |||
void pint8(unsigned char c); | |||
// Error Messages | |||
#define erro_dPrint(...) dPrintMsg ("1;5;31", "ERROR", __VA_ARGS__) // Error Msg | |||
#define erro_print(str) printMsg ("1;5;31", "ERROR", str) // Error Msg | |||
// Debug Messages | |||
#define dbug_dPrint(...) dPrintMsg ("1;35", "DEBUG", __VA_ARGS__) // Debug Msg | |||
#define dbug_print(str) printMsg ("1;35", "DEBUG", str) // Debug Msg | |||
// Static String Printing | |||
#define print(s) _print(PSTR(s)) | |||
void _print(const char *s); | |||
void usb_debug_putstr( char* s ); | |||
void usb_debug_putstrs( char* first, ... ); | |||
// String Functions | |||
#define hexToStr(hex, out) hexToStr_op(hex, out, 1) | |||
void int8ToStr ( uint8_t in, char* out ); | |||
void int16ToStr ( uint16_t in, char* out ); | |||
void hexToStr_op( uint16_t in, char* out, uint8_t op ); | |||
void revsStr ( char* in ); | |||
uint16_t lenStr ( char* in ); | |||
#endif | |||
@@ -0,0 +1,137 @@ | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
* in the Software without restriction, including without limitation the rights | |||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
* copies of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included in | |||
* all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
* THE SOFTWARE. | |||
*/ | |||
#include <stdint.h> | |||
#include "usb_keyboard_debug.h" | |||
#include "keymap.h" | |||
// Debouncing Defines | |||
#define SAMPLE_THRESHOLD 110 | |||
#define MAX_SAMPLES 127 // Max is 127, reaching 128 is very bad | |||
// 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 | |||
#define KEYBOARD_SIZE 23 | |||
uint8_t keyboardDetectArray[KEYBOARD_SIZE + 1]; | |||
// Interrupt Variable | |||
volatile uint8_t sendKeypresses = 0; | |||
// USB Data Send | |||
void usb_send( uint8_t validKeys ) | |||
{ | |||
// TODO undo potentially old keys | |||
for ( uint8_t c = validKeys; c < 6; c++ ) | |||
keyboard_keys[c] = 0; | |||
// Send keypresses | |||
usb_keyboard_send(); | |||
// Clear sendKeypresses Flag | |||
sendKeypresses = 0; | |||
// Clear modifiers | |||
keyboard_modifier_keys = 0; | |||
} | |||
// Given a sampling array, and the current number of detected keypress | |||
// Add as many keypresses from the sampling array to the USB key send array as possible. | |||
void keyPressDetection( uint8_t *keys, uint8_t *validKeys, uint8_t numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) { | |||
for ( uint8_t key = 0; key < numberOfKeys + 1; key++ ) { | |||
if ( keys[key] & (1 << 7) ) { | |||
pint8( key ); | |||
//print(" "); | |||
uint8_t modFound = 0; | |||
// Determine if the key is a modifier | |||
for ( uint8_t mod = 0; mod < numberOfModifiers; mod++ ) { | |||
// Modifier found | |||
if ( modifiers[mod] == key ) { | |||
keyboard_modifier_keys |= map[key]; | |||
modFound = 1; | |||
break; | |||
} | |||
} | |||
if ( modFound ) | |||
continue; | |||
// Too many keys | |||
if ( *validKeys == 6 ) | |||
break; | |||
// Allow ignoring keys with 0's | |||
if ( map[key] != 0 ) | |||
keyboard_keys[(*validKeys)++] = map[key]; | |||
} | |||
} | |||
} | |||
// Main Detection Loop | |||
void scan_loop( void ) | |||
{ | |||
//matrix_pinSetup( matrix_pinout ); | |||
uint8_t count = 0; | |||
for ( ;; ) { | |||
//matrix_scan( matrix_pinout, keyboardDetectArray ); | |||
// Check count to see if the sample threshold may have been reached, otherwise collect more data | |||
if ( count++ < MAX_SAMPLES ) | |||
continue; | |||
// Reset Sample Counter | |||
count = 0; | |||
// Assess debouncing sample table | |||
//DEBOUNCE_ASSESS(keyDetectArray,KEYBOARD_SIZE) | |||
// Send keypresses over USB if the ISR has signalled that it's time | |||
if ( !sendKeypresses ) | |||
continue; | |||
// Layout Setup | |||
uint8_t validKeys = 0; | |||
uint8_t *keyboard_MODMASK = keyboard_modifierMask; | |||
uint8_t keyboard_NUMMODS = MODIFIERS_KEYBOARD; | |||
uint8_t *keyboard_MAP = defaultMap; | |||
// TODO Layout Switching | |||
// TODO Macro Processing | |||
// Debounce Sampling Array to USB Data Array | |||
keyPressDetection( keyboardDetectArray, &validKeys, KEYBOARD_SIZE, keyboard_MODMASK, keyboard_NUMMODS, keyboard_MAP ); | |||
// Send USB Data | |||
usb_send( validKeys ); | |||
} | |||
} | |||
@@ -0,0 +1,31 @@ | |||
/* Copyright (C) 2011 by Jacob Alexander | |||
* | |||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||
* of this software and associated documentation files (the "Software"), to deal | |||
* in the Software without restriction, including without limitation the rights | |||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
* copies of the Software, and to permit persons to whom the Software is | |||
* furnished to do so, subject to the following conditions: | |||
* | |||
* The above copyright notice and this permission notice shall be included in | |||
* all copies or substantial portions of the Software. | |||
* | |||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||
* THE SOFTWARE. | |||
*/ | |||
#ifndef __SCAN_LOOP_H | |||
#define __SCAN_LOOP_H | |||
//extern uint8_t keyboardDetectArray[KEYBOARDZ | |||
extern volatile uint8_t sendKeypresses; | |||
void scan_loop( void ); | |||
#endif // __SCAN_LOOP_H | |||
@@ -0,0 +1,8 @@ | |||
#!/bin/bash | |||
#| Loads the hex file onto the teensy 2.0 | |||
sudo teensy-loader-cli -mmcu=atmega32u4 -w Build/main.hex | |||
exit 0 | |||