Browse Source

Code re-factor now compiles.

- 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
Jacob Alexander 12 years ago
parent
commit
1e03ed42aa
10 changed files with 964 additions and 375 deletions
  1. 1
    0
      Makefile
  2. 228
    0
      keymap.h
  3. 7
    341
      main.c
  4. 181
    0
      matrix.c
  5. 151
    0
      matrix.h
  6. 142
    26
      print.c
  7. 78
    8
      print.h
  8. 137
    0
      scan_loop.c
  9. 31
    0
      scan_loop.h
  10. 8
    0
      sload

+ 1
- 0
Makefile View File

@@ -48,6 +48,7 @@ TARGET = main
SRC = $(TARGET).c \
print.c \
usb_keyboard_debug.c \
scan_loop.c
#usb_keyboard.c



+ 228
- 0
keymap.h View File

@@ -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


+ 7
- 341
main.c View File

@@ -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++;

+ 181
- 0
matrix.c View File

@@ -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
}


+ 151
- 0
matrix.h View File

@@ -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



+ 142
- 26
print.c View File

@@ -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);
}


+ 78
- 8
print.h View File

@@ -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


+ 137
- 0
scan_loop.c View File

@@ -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 );
}
}


+ 31
- 0
scan_loop.h View File

@@ -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


+ 8
- 0
sload View File

@@ -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