From 6557022f206483aea761e057b65dba500b5decee Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Sat, 15 Oct 2011 20:01:46 -0700 Subject: [PATCH] Basic matrix module for the hall effect keypad now working. - Includes new "table pinning" setup (much easier to understand) - Matrix layouts will be split into their own dependent modules later - Changed the HID Raw view id (too many teensy devices on this computer...) - Moved the macro processing outside of the usb timer signal (this will be slower overall, but will result in more consistant behaviour) --- CMakeLists.txt | 2 +- Macro/basic/macro.c | 30 +++---- Scan/matrix/matrix.h | 88 +----------------- Scan/matrix/{matrix.c => matrix_scan.c} | 79 +++++++++++----- Scan/matrix/matrix_scan.h | 115 ++++++++++++++++++++++++ Scan/matrix/scan_loop.c | 37 +++++--- Scan/matrix/scan_loop.h | 23 ++++- Scan/matrix/setup.cmake | 8 +- USB/pjrc/usb_keyboard_debug.c | 3 +- main.c | 11 ++- setup.cmake | 2 +- 11 files changed, 259 insertions(+), 139 deletions(-) rename Scan/matrix/{matrix.c => matrix_scan.c} (62%) create mode 100644 Scan/matrix/matrix_scan.h diff --git a/CMakeLists.txt b/CMakeLists.txt index e275627..08182eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set( SRCS main.c ${SCAN_SRCS} ${MACRO_SRCS} ${USB_SRCS} ${DEBUG_SRCS} ) #| "atmega32u4" # Teensy 2.0 #| "at90usb646" # Teensy++ 1.0 #| "at90usb1286" # Teensy++ 2.0 -set( MCU "at90usb1286" ) +set( MCU "atmega32u4" ) #| Compiler flag to set the C Standard level. diff --git a/Macro/basic/macro.c b/Macro/basic/macro.c index d961015..c704708 100644 --- a/Macro/basic/macro.c +++ b/Macro/basic/macro.c @@ -42,24 +42,26 @@ // 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 numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) -//void keyPressDetection( uint8_t *keys, uint8_t numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) +inline void keyPressDetection( uint8_t *keys, uint8_t numberOfKeys, uint8_t *modifiers, uint8_t numberOfModifiers, uint8_t *map ) { USBKeys_Sent = 0; - for ( uint8_t key = 1; key < numberOfKeys + 1; key++ ) - //for ( uint8_t key = 0; key < numberOfKeys + 1; key++ ) + // Parse the detection array starting from 1 (all keys are purposefully mapped from 1 -> total as per typical PCB labels) + for ( uint8_t key = 0; key < numberOfKeys + 1; key++ ) { - //if ( keys[key] & (1 << 7) ) - if ( keys[key] ) + if ( keys[key] & (1 << 7) ) { - uint8_t modFound = 0; + // Display the detected scancode + char tmpStr[4]; + int8ToStr( key, tmpStr ); + dPrintStrs( tmpStr, " " ); // Determine if the key is a modifier + uint8_t modFound = 0; for ( uint8_t mod = 0; mod < numberOfModifiers; mod++ ) { // Modifier found if ( modifiers[mod] == key ) { - USBKeys_Modifiers |= map[key]; + //USBKeys_Modifiers |= map[key]; modFound = 1; break; } @@ -80,17 +82,15 @@ void keyPressDetection( uint8_t *keys, uint8_t numberOfKeys, uint8_t *modifiers, // Allow ignoring keys with 0's if ( map[key] != 0 ) USBKeys_Array[USBKeys_Sent++] = map[key]; - - /* - char tmpStr[3]; - hexToStr_op( USBKeys_Array[0], tmpStr, 2 ); - warn_dPrint("Found key: 0x", tmpStr ); - */ } } + + // Add debug separator if keys sent via USB + if ( USBKeys_Sent > 0 ) + print("\033[1;32m|\033[0m\n"); } -void process_macros(void) +inline void process_macros(void) { // Debounce Sampling Array to USB Data Array keyPressDetection( KeyIndex_Array, KeyIndex_Size, MODIFIER_MASK, sizeof(MODIFIER_MASK), KEYINDEX_MASK ); diff --git a/Scan/matrix/matrix.h b/Scan/matrix/matrix.h index 7af35ac..6ac8819 100644 --- a/Scan/matrix/matrix.h +++ b/Scan/matrix/matrix.h @@ -28,76 +28,8 @@ #include -// ----- 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 ----- +// ----- Scan Mode Setting (See matrix_scan.h for more details) ----- #define scanMode scanCol @@ -105,6 +37,7 @@ // ----- Key Settings ----- #define KEYBOARD_SIZE 16 // # of keys #define MAX_ROW_SIZE 16 // # of keys in the largest row +#define MAX_COL_SIZE 1 // # of keys in the largest column @@ -131,31 +64,18 @@ static const uint8_t matrix_pinout[][MAX_ROW_SIZE + 1] = { // ... | - { scanMode, pinF4, pinA6, pinA1, pinA3, pinF5, pinA5, pinA2, pinF0, pinF6, pinA7, pinA0, pinF1, pinF3, pinF7, pinA4, pinF2 }, + { scanMode, pinF0, pinF4, pinB7, pinD3, pinF5, pinF1, pinD1, pinD2, pinF6, pinF7, pinB2, pinD0, pinB0, pinB6, pinB1, pinB3 }, { 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, }, +//{ pinE1, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 0, 0 }, }; -// ----- Variables ----- - -// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) -// Other Bits: Pressed state sample counter -extern uint8_t KeyIndex_Array [KEYBOARD_SIZE + 1]; - static const uint8_t KeyIndex_Size = KEYBOARD_SIZE; - - - -// ----- Functions ----- - - #endif // __MATRIX_H - diff --git a/Scan/matrix/matrix.c b/Scan/matrix/matrix_scan.c similarity index 62% rename from Scan/matrix/matrix.c rename to Scan/matrix/matrix_scan.c index 644cf45..f8aed80 100644 --- a/Scan/matrix/matrix.c +++ b/Scan/matrix/matrix_scan.c @@ -24,14 +24,20 @@ // AVR Includes #include +// Project Includes +#include + // Local Includes -#include "matrix.h" +#include "matrix_scan.h" + +// Matrix Configuration +#include // ----- Macros ----- -#define REG_SET(reg) reg |= (1 << ( matrix[row][col] % 10 ) ) +#define REG_SET(reg) reg |= (1 << ( matrix[row*(MAX_ROW_SIZE+1)+col] % 10 ) ) #define PIN_SET_COL(pin) \ switch ( scanMode ) { \ @@ -64,21 +70,20 @@ case pin##pinLetter##7 #define PIN_TEST_COL(pin) \ - if ( !( pin & ( 1 << ( matrix[0][col] % 10 ) ) \ - detectArray[matrix[row][col]]++; \ + if ( !( pin & ( 1 << ( matrix[0*(MAX_ROW_SIZE+1)+col] % 10 ) ) ) ) \ + detectArray[matrix[row*(MAX_ROW_SIZE+1)+col]]++; \ break // ----- Variables ----- -uint8_t KeyIndex_Array[KEYBOARD_SIZE + 1]; - // ----- Functions ----- -void matrix_pinSetup( uint8_t *matrix ) +// Goes through the defined matrix and matrix mode, and sets the initial state of all of the available pins +inline void matrix_pinSetup( uint8_t *matrix ) { // Setup the variables uint8_t portA = 0x00; @@ -96,12 +101,14 @@ void matrix_pinSetup( uint8_t *matrix ) uint8_t ddrF = 0x00; // Loop through all the pin assignments, for the initial pin settings - //int row, col; + uint16_t row, col; // Rows - /* - for ( row = 1; row < sizeof(matrix); row++ ) { - switch ( matrix[row][col] ) { + for ( col = 0, row = 1; row < MAX_COL_SIZE + 1; row++ ) + { + // We can't pass 2D arrays, so just point to the first element and calculate directly + switch ( matrix[row*(MAX_ROW_SIZE+1)+col] ) + { PIN_CASE(A): PIN_SET_ROW(A); PIN_CASE(B): @@ -121,8 +128,11 @@ void matrix_pinSetup( uint8_t *matrix ) } // Columns - for ( col = 1; col < sizeof(matrix[0]); row++ ) { - switch ( matrix[row][col] ) { + for ( col = 1, row = 0; col < (MAX_ROW_SIZE+1) + 1; col++ ) + { + // We can't pass 2D arrays, so just point to the first element and calculate directly + switch ( matrix[row*(MAX_ROW_SIZE+1)+col] ) + { PIN_CASE(A): PIN_SET_COL(A); PIN_CASE(B): @@ -140,17 +150,42 @@ void matrix_pinSetup( uint8_t *matrix ) continue; } } - */ + + // Pin Status + char tmpStr[6]; + info_print("Initial Matrix Pin Setup"); + info_print(" ddrA ddrB ddrC ddrD ddrE ddrF"); + print(" "); + hexToStr_op( ddrA, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( ddrB, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( ddrC, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( ddrD, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( ddrE, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( ddrF, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + print("\n"); + info_print("portA portB portC portD portE portF"); + print(" "); + hexToStr_op( portA, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( portB, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( portC, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( portD, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( portE, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + hexToStr_op( portF, tmpStr, 2 ); dPrintStrs( " 0x", tmpStr ); + print("\n"); // Setting the pins +#if defined(__AVR_AT90USB1286__) DDRA = ddrA; +#endif DDRB = ddrB; DDRC = ddrC; DDRD = ddrD; DDRE = ddrE; DDRF = ddrF; +#if defined(__AVR_AT90USB1286__) PORTA = portA; +#endif PORTB = portB; PORTC = portC; PORTD = portD; @@ -159,17 +194,20 @@ void matrix_pinSetup( uint8_t *matrix ) } // TODO Proper matrix scanning -void matrix_scan( uint8_t *matrix, uint8_t *detectArray ) +inline 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 ) { + uint16_t col = 1; + uint16_t row = 1; + for ( ; col < (MAX_ROW_SIZE+1) + 1; col++ ) + { + switch ( matrix[0*(MAX_ROW_SIZE+1)+col] / 10 ) + { +#if defined(__AVR_AT90USB1286__) case 0: // PINA PIN_TEST_COL(PINA); +#endif case 1: // PINB PIN_TEST_COL(PINB); case 2: // PINC @@ -182,7 +220,6 @@ void matrix_scan( uint8_t *matrix, uint8_t *detectArray ) PIN_TEST_COL(PINF); } } - */ #endif // Row Scan diff --git a/Scan/matrix/matrix_scan.h b/Scan/matrix/matrix_scan.h new file mode 100644 index 0000000..9492425 --- /dev/null +++ b/Scan/matrix/matrix_scan.h @@ -0,0 +1,115 @@ +/* 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_SCAN_H +#define __MATRIX_SCAN_H + +// ----- Includes ----- + +// Compiler Includes +#include + +// Local Includes + + + +// ----- Defines ----- + +// ----- 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 matrix (simple detection) +#define scanCol_powrRow 3 // Opposite of scanRow_powrCol +#define scanDual 4 // Typical ~2KRO matrix + + + +// ----- Variables ----- + + + +// ----- Functions ----- + +void matrix_pinSetup( uint8_t *matrix ); +void matrix_scan( uint8_t *matrix, uint8_t *detectArray ); + +#endif // __MATRIX_SCAN_H + diff --git a/Scan/matrix/scan_loop.c b/Scan/matrix/scan_loop.c index d47fd2c..7e0121a 100644 --- a/Scan/matrix/scan_loop.c +++ b/Scan/matrix/scan_loop.c @@ -21,8 +21,16 @@ // ----- Includes ----- +// AVR Includes +#include + +// Project Includes +#include +#include + // Local Includes #include "scan_loop.h" +#include "matrix_scan.h" @@ -40,9 +48,8 @@ // 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; \ - } \ + for ( uint8_t key = 1; key < size + 1; key++ ) \ + table[key] = ( table[key] & ~(1 << 7) ) > SAMPLE_THRESHOLD ? (1 << 7) : 0x00 @@ -51,29 +58,39 @@ // Keeps track of the number of scans, so we only do a debounce assess when it would be valid (as it throws away data) uint8_t scan_count = 0; +// This is where the matrix scan data is held, as well as debouncing is evaluated to, which (depending on the read value) is handled +// by the macro module +uint8_t KeyIndex_Array[KEYBOARD_SIZE + 1]; + // ----- Functions ----- // Setup -void scan_setup() +inline void scan_setup() { - //matrix_pinSetup( matrix_pinout ); + matrix_pinSetup( (uint8_t*)matrix_pinout ); } // Main Detection Loop -void scan_loop() +inline uint8_t scan_loop() { - //matrix_scan( matrix_pinout, keyboardDetectArray ); - // Check count to see if the sample threshold may have been reached, otherwise collect more data if ( scan_count++ < MAX_SAMPLES ) - return; + { + matrix_scan( (uint8_t*)matrix_pinout, KeyIndex_Array ); + + // Signal Main Detection Loop to continue scanning + return 0; + } // Reset Sample Counter scan_count = 0; // Assess debouncing sample table - //DEBOUNCE_ASSESS(keyDetectArray,KEYBOARD_SIZE) + DEBOUNCE_ASSESS( KeyIndex_Array, KeyIndex_Size ); + + // Ready to allow for USB send + return 1; } diff --git a/Scan/matrix/scan_loop.h b/Scan/matrix/scan_loop.h index ec79bd1..a451d66 100644 --- a/Scan/matrix/scan_loop.h +++ b/Scan/matrix/scan_loop.h @@ -24,15 +24,34 @@ // ----- Includes ----- +// Compiler Includes +#include + // Local Includes -#include "matrix.h" +#include "matrix_scan.h" + +// Matrix Configuration +#include + + + +// ----- Defines ----- + + + +// ----- Variables ----- + +// NOTE: Highest Bit: Valid keypress (0x80 is valid keypress) +// Other Bits: Pressed state sample counter +extern uint8_t KeyIndex_Array [KEYBOARD_SIZE + 1]; + static const uint8_t KeyIndex_Size = KEYBOARD_SIZE; // ----- Functions ----- void scan_setup( void ); -void scan_loop( void ); +uint8_t scan_loop( void ); #endif // __SCAN_LOOP_H diff --git a/Scan/matrix/setup.cmake b/Scan/matrix/setup.cmake index b529a51..f86bab6 100644 --- a/Scan/matrix/setup.cmake +++ b/Scan/matrix/setup.cmake @@ -12,7 +12,7 @@ # set( SCAN_SRCS - matrix.c + matrix_scan.c scan_loop.c ) @@ -22,3 +22,9 @@ set( SCAN_SRCS # add_definitions( -I${HEAD_DIR}/Keymap ) +#| Keymap Settings +add_definitions( + -DMODIFIER_MASK=tandy1000_modifierMask + -DKEYINDEX_MASK=tandy1000_colemak +) + diff --git a/USB/pjrc/usb_keyboard_debug.c b/USB/pjrc/usb_keyboard_debug.c index 588a0bc..6aec93f 100644 --- a/USB/pjrc/usb_keyboard_debug.c +++ b/USB/pjrc/usb_keyboard_debug.c @@ -135,7 +135,8 @@ static const uint8_t PROGMEM keyboard_hid_report_desc[] = { }; static const uint8_t PROGMEM debug_hid_report_desc[] = { - 0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) + 0x06, 0x30, 0xFF, // Usage Page 0xFF31 (vendor defined) + //0x06, 0x31, 0xFF, // Usage Page 0xFF31 (vendor defined) 0x09, 0x74, // Usage 0x74 0xA1, 0x53, // Collection 0x53 0x75, 0x08, // report size = 8 bits diff --git a/main.c b/main.c index b31b58c..6eb4627 100644 --- a/main.c +++ b/main.c @@ -62,8 +62,11 @@ volatile uint8_t sendKeypresses = 0; // Initial Pin Setup, make sure they are sane inline void pinSetup(void) { + // For each pin, 0=input, 1=output +#if defined(__AVR_AT90USB1286__) DDRA = 0x00; +#endif DDRB = 0x00; DDRC = 0x00; DDRD = 0x00; @@ -72,7 +75,9 @@ inline void pinSetup(void) // Setting pins to either high or pull-up resistor +#if defined(__AVR_AT90USB1286__) PORTA = 0x00; +#endif PORTB = 0x00; PORTC = 0x00; PORTD = 0x00; @@ -113,13 +118,13 @@ int main(void) while ( scan_loop() ); sei(); + // Run Macros over Key Indices and convert to USB Keys + process_macros(); + // Send keypresses over USB if the ISR has signalled that it's time if ( !sendKeypresses ) continue; - // Run Macros over Key Indices and convert to USB Keys - process_macros(); - // Send USB Data usb_send(); diff --git a/setup.cmake b/setup.cmake index 00c0794..f841284 100644 --- a/setup.cmake +++ b/setup.cmake @@ -20,7 +20,7 @@ #| Please the {Scan,Macro,USB,Debug}/module.txt for information on the modules and how to create new ones ##| Deals with acquiring the keypress information and turning it into a key index -set( ScanModule "Tandy1000" ) +set( ScanModule "matrix" ) ##| Uses the key index and potentially applies special conditions to it, mapping it to a usb key code set( MacroModule "basic" )