From d6345c307fa4c64deb3f293fe91760f05c928120 Mon Sep 17 00:00:00 2001 From: Jacob Alexander Date: Fri, 1 Aug 2014 01:26:25 -0700 Subject: [PATCH] Initial MatrixARM implementation - Cleaned up Macro and USB callback naming - Added security jumper for automated reload (MCHCK based only) - Added additional LED position --- CMakeLists.txt | 2 +- Debug/led/led.c | 19 +++ Lib/mk20dx.h | 2 +- Macro/PartialMap/macro.c | 12 +- Macro/PartialMap/macro.h | 45 ++---- Output/pjrcUSB/arm/usb_dev.c | 25 +++- Output/pjrcUSB/output_com.c | 4 +- Output/usbMuxUart/output_com.c | 4 +- Scan/MD1/defaultMap.h | 0 Scan/MD1/matrix.h | 66 +++++++++ Scan/MD1/scan_loop.c | 87 ++++++++++++ Scan/MD1/scan_loop.h | 54 ++++++++ Scan/MD1/setup.cmake | 34 +++++ Scan/MatrixARM/matrix_scan.c | 242 +++++++++++++++++++++++++++++++++ Scan/MatrixARM/matrix_scan.h | 128 +++++++++++++++++ Scan/MatrixARM/setup.cmake | 36 +++++ 16 files changed, 706 insertions(+), 54 deletions(-) create mode 100644 Scan/MD1/defaultMap.h create mode 100644 Scan/MD1/matrix.h create mode 100644 Scan/MD1/scan_loop.c create mode 100644 Scan/MD1/scan_loop.h create mode 100644 Scan/MD1/setup.cmake create mode 100644 Scan/MatrixARM/matrix_scan.c create mode 100644 Scan/MatrixARM/matrix_scan.h create mode 100644 Scan/MatrixARM/setup.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ec941c..e053e04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ include( Lib/CMake/initialize.cmake ) #| Please look at the {Scan,Macro,Output,Debug} 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 "MDPure" ) +set( ScanModule "MD1" ) ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule set( MacroModule "PartialMap" ) diff --git a/Debug/led/led.c b/Debug/led/led.c index 22a70c9..ece3a48 100644 --- a/Debug/led/led.c +++ b/Debug/led/led.c @@ -53,11 +53,19 @@ inline void init_errorLED() // MCHCK #elif defined(_mk20dx128vlf5_) +/* Actual MCHCK // Enable pin GPIOB_PDDR |= (1<<16); // Setup pin - B16 - See Lib/pin_map.mchck for more details on pins PORTB_PCR16 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); +*/ + // Kiibohd MCHCK Variant + // Enable pin + GPIOA_PDDR |= (1<<19); + + // Setup pin - A19 - See Lib/pin_map.mchck for more details on pins + PORTA_PCR19 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); #endif } @@ -92,6 +100,7 @@ inline void errorLED( uint8_t on ) // MCHCK #elif defined(_mk20dx128vlf5_) +/* Actual MCHCK // Error LED On (B16) if ( on ) { GPIOB_PSOR |= (1<<16); @@ -100,6 +109,16 @@ inline void errorLED( uint8_t on ) else { GPIOB_PCOR |= (1<<16); } +*/ + // Kiibohd MCHCK Variant + // Error LED On (A19) + if ( on ) { + GPIOA_PSOR |= (1<<19); + } + // Error LED Off + else { + GPIOA_PCOR |= (1<<19); + } #endif } diff --git a/Lib/mk20dx.h b/Lib/mk20dx.h index 9af51a3..42be154 100644 --- a/Lib/mk20dx.h +++ b/Lib/mk20dx.h @@ -57,7 +57,6 @@ #include // chapter 11: Port control and interrupts (PORT) -#define PORTA_PCR0 *(volatile uint32_t *)0x40049000 // Pin Control Register n #define PORT_PCR_ISF (uint32_t)0x01000000 // Interrupt Status Flag #define PORT_PCR_IRQC(n) (uint32_t)(((n) & 15) << 16) // Interrupt Configuration #define PORT_PCR_IRQC_MASK (uint32_t)0x000F0000 @@ -70,6 +69,7 @@ #define PORT_PCR_SRE (uint32_t)0x00000004 // Slew Rate Enable #define PORT_PCR_PE (uint32_t)0x00000002 // Pull Enable #define PORT_PCR_PS (uint32_t)0x00000001 // Pull Select +#define PORTA_PCR0 *(volatile uint32_t *)0x40049000 // Pin Control Register n #define PORTA_PCR1 *(volatile uint32_t *)0x40049004 // Pin Control Register n #define PORTA_PCR2 *(volatile uint32_t *)0x40049008 // Pin Control Register n #define PORTA_PCR3 *(volatile uint32_t *)0x4004900C // Pin Control Register n diff --git a/Macro/PartialMap/macro.c b/Macro/PartialMap/macro.c index 02caa97..50cee84 100644 --- a/Macro/PartialMap/macro.c +++ b/Macro/PartialMap/macro.c @@ -248,13 +248,6 @@ void Macro_evalResultMacro( ResultMacro *resultMacro ) } -// Called immediately after USB has finished sending a buffer -inline void Macro_finishWithUSBBuffer( uint8_t sentKeys ) -{ - // XXX Currently not used to trigger anything (with this particular Macro module) -} - - // Macro Procesing Loop // Called once per USB buffer send inline void Macro_process() @@ -349,8 +342,9 @@ inline void Macro_process() } */ - // Signal buffer that we've used it - Scan_finishedWithBuffer( KeyIndex_BufferUsed ); + // Signal buffer that we've used it TODO + Scan_finishedWithMacro( 0 ); + //Scan_finishedWithBuffer( KeyIndex_BufferUsed ); // If Macro debug mode is set, clear the USB Buffer if ( macroDebugMode ) diff --git a/Macro/PartialMap/macro.h b/Macro/PartialMap/macro.h index 6722c2c..b78cd5d 100644 --- a/Macro/PartialMap/macro.h +++ b/Macro/PartialMap/macro.h @@ -1,22 +1,17 @@ /* Copyright (C) 2014 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: + * This file is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * 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. + * You should have received a copy of the GNU General Public License + * along with this file. If not, see . */ #ifndef __macro_h @@ -29,31 +24,11 @@ -// ----- Defines ----- - -// Key states (DO NOT USE for analog keyboards) -#define DEPRESSED 0 -#define RELEASED 1 -#define PRESSED 254 -#define HELD 255 - - -// ----- Variables ----- - - - -// ----- Macros ----- - - - // ----- Functions ----- void Macro_keyState( uint8_t scanCode, uint8_t state ); void Macro_analogState( uint8_t scanCode, uint8_t state ); void Macro_ledState( uint8_t ledCode, uint8_t state ); -void Macro_bufferAdd( uint8_t byte ); -void Macro_bufferRemove( uint8_t byte ); -void Macro_finishWithUSBBuffer( uint8_t sentKeys ); void Macro_process(); void Macro_setup(); diff --git a/Output/pjrcUSB/arm/usb_dev.c b/Output/pjrcUSB/arm/usb_dev.c index aab87f2..3b2d3a9 100644 --- a/Output/pjrcUSB/arm/usb_dev.c +++ b/Output/pjrcUSB/arm/usb_dev.c @@ -684,11 +684,28 @@ void usb_device_reload() { // MCHCK #if defined(_mk20dx128vlf5_) - // This line must be exactly the same in the bootloader - const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; - for ( int pos = 0; pos < sizeof(sys_reset_to_loader_magic); pos++ )(&VBAT)[pos] = sys_reset_to_loader_magic[ pos ]; - SOFTWARE_RESET(); + // MCHCK Kiibohd Variant + // Check to see if PTA3 (has a pull-up) is connected to GND (usually via jumper) + // Only allow reload if the jumper is present (security) + GPIOA_PDDR &= ~(1<<3); // Input + PORTA_PCR3 = PORT_PCR_PFE | PORT_PCR_MUX(1); // Internal pull-up + + // Check for jumper + if ( GPIOA_PDIR & (1<<3) ) + { + print( NL ); + warn_print("Security jumper not present, cancelling firmware reload..."); + info_msg("Replace jumper on middle 2 pins, or manually press the firmware reload button."); + } + else + { + // This line must be exactly the same in the bootloader + const uint8_t sys_reset_to_loader_magic[] = "\xff\x00\x7fRESET TO LOADER\x7f\x00\xff"; + for ( int pos = 0; pos < sizeof(sys_reset_to_loader_magic); pos++ )(&VBAT)[pos] = sys_reset_to_loader_magic[ pos ]; + SOFTWARE_RESET(); + } + // Teensy 3.0 and 3.1 #else asm volatile("bkpt"); diff --git a/Output/pjrcUSB/output_com.c b/Output/pjrcUSB/output_com.c index 8acc4a3..bd748ad 100644 --- a/Output/pjrcUSB/output_com.c +++ b/Output/pjrcUSB/output_com.c @@ -131,8 +131,8 @@ inline void Output_send(void) USBKeys_Modifiers = 0; USBKeys_Sent = 0; - // Signal Scan Module we are finishedA - Scan_finishedWithUSBBuffer( USBKeys_Sent <= USBKeys_MaxSize ? USBKeys_Sent : USBKeys_MaxSize ); + // Signal Scan Module we are finished + Scan_finishedWithOutput( USBKeys_Sent <= USBKeys_MaxSize ? USBKeys_Sent : USBKeys_MaxSize ); } diff --git a/Output/usbMuxUart/output_com.c b/Output/usbMuxUart/output_com.c index 80c7a4c..86f5cf6 100644 --- a/Output/usbMuxUart/output_com.c +++ b/Output/usbMuxUart/output_com.c @@ -134,8 +134,8 @@ inline void Output_send(void) USBKeys_Modifiers = 0; USBKeys_Sent = 0; - // Signal Scan Module we are finishedA - Scan_finishedWithUSBBuffer( USBKeys_Sent <= USBKeys_MaxSize ? USBKeys_Sent : USBKeys_MaxSize ); + // Signal Scan Module we are finished + Scan_finishedWithOutput( USBKeys_Sent <= USBKeys_MaxSize ? USBKeys_Sent : USBKeys_MaxSize ); } diff --git a/Scan/MD1/defaultMap.h b/Scan/MD1/defaultMap.h new file mode 100644 index 0000000..e69de29 diff --git a/Scan/MD1/matrix.h b/Scan/MD1/matrix.h new file mode 100644 index 0000000..948f7db --- /dev/null +++ b/Scan/MD1/matrix.h @@ -0,0 +1,66 @@ +/* Copyright (C) 2014 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 + +// ----- Macros ----- + +// Convenience Macros +#define gpio( port, pin ) { Port_##port, Pin_##pin } +#define Matrix_colsNum sizeof( Matrix_cols ) / sizeof( GPIO_Pin ) +#define Matrix_rowsNum sizeof( Matrix_rows ) / sizeof( GPIO_Pin ) +#define Matrix_maxKeys sizeof( Matrix_scanArray ) / sizeof( KeyState ) + + + +// ----- Matrix Definition ----- + +// Freescale ARM MK20's support GPIO PTA, PTB, PTC, PTD and PTE 0..31 +// Not all chips have access to all of these pins (most don't have 160 pins :P) +// +// NOTE: +// Before using a pin, make sure it supports being a GPIO *and* doesn't have a default pull-up/pull-down +// Checking this is completely on the ownness of the user + +// MD1 +// +// Columns (Strobe) +// PTB0..3,16,17 +// PTC4,5 +// PTD0 +// +// Rows (Sense) +// PTD1..7 + +// Debounce threshold +#define DEBOUNCE_THRESHOLD 32 + +// Define Rows (Sense) and Columns (Strobes) +GPIO_Pin Matrix_cols[] = { gpio(B,0), gpio(B,1), gpio(B,2), gpio(B,3), gpio(B,16), gpio(B,17), gpio(C,4), gpio(C,5) }; +GPIO_Pin Matrix_rows[] = { gpio(D,1), gpio(D,2), gpio(D,3), gpio(D,4), gpio(D,5), gpio(D,6), gpio(D,7) }; + +// Define type of scan matrix +Config Matrix_type = Config_Pullup; + + +#endif // __MATRIX_H + diff --git a/Scan/MD1/scan_loop.c b/Scan/MD1/scan_loop.c new file mode 100644 index 0000000..5481d30 --- /dev/null +++ b/Scan/MD1/scan_loop.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2014 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. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include + +// Local Includes +#include "scan_loop.h" +#include "macro.h" + + + +// ----- Variables ----- + +// Indicates if the next scan is the first after a USB send +uint8_t Scan_firstScan = 1; + +// Number of scans since the last USB send +uint16_t Scan_scanCount = 0; + + + +// ----- Functions ----- + +// Setup +inline void Scan_setup() +{ + // Setup GPIO pins for matrix scanning + Matrix_setup(); + + // First scan is next + Scan_firstScan = 1; +} + + +// Main Detection Loop +inline uint8_t Scan_loop() +{ + Matrix_scan( Scan_scanCount++, Scan_firstScan ); + + // No longer the first scan + Scan_firstScan = 0; + + return 0; +} + + +// Signal from Macro Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithMacro( uint8_t sentKeys ) +{ +} + + +// Signal from Output Module that all keys have been processed (that it knows about) +inline void Scan_finishedWithOutput( uint8_t sentKeys ) +{ + // Reset scan loop indicator (resets each key debounce state) + // TODO should this occur after USB send or Macro processing? + Scan_firstScan = 1; + Scan_scanCount = 0; +} + diff --git a/Scan/MD1/scan_loop.h b/Scan/MD1/scan_loop.h new file mode 100644 index 0000000..73508bb --- /dev/null +++ b/Scan/MD1/scan_loop.h @@ -0,0 +1,54 @@ +/* Copyright (C) 2014 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 + +// ----- Includes ----- + +// Compiler Includes +#include + +// Local Includes + + + +// ----- Defines ----- + + + +// ----- Variables ----- + + + +// ----- Functions ----- + +// Functions to be called by main.c +void Scan_setup( void ); +uint8_t Scan_loop( void ); + +// Call-backs +void Scan_finishedWithMacro( uint8_t sentKeys ); // Called by Macro Module +void Scan_finishedWithOutput( uint8_t sentKeys ); // Called by Output Module + + +#endif // __SCAN_LOOP_H + diff --git a/Scan/MD1/setup.cmake b/Scan/MD1/setup.cmake new file mode 100644 index 0000000..3b6ea0c --- /dev/null +++ b/Scan/MD1/setup.cmake @@ -0,0 +1,34 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2014 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + + +### +# Module C files +# + +set( SCAN_SRCS + scan_loop.c + ../MatrixARM/matrix_scan.c +) + + +### +# Module Specific Options +# +add_definitions( + -I${HEAD_DIR}/Scan/MatrixARM +) + + +### +# Compiler Family Compatibility +# +set( ScanModuleCompatibility + arm +) + diff --git a/Scan/MatrixARM/matrix_scan.c b/Scan/MatrixARM/matrix_scan.c new file mode 100644 index 0000000..d31441d --- /dev/null +++ b/Scan/MatrixARM/matrix_scan.c @@ -0,0 +1,242 @@ +/* Copyright (C) 2014 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. + */ + +// ----- Includes ----- + +// Compiler Includes +#include + +// Project Includes +#include +#include +#include +#include + +// Local Includes +#include "matrix_scan.h" + +// Matrix Configuration +#include + + + +// ----- Variables ----- + +// Debounce Array +KeyState Matrix_scanArray[ Matrix_colsNum * Matrix_rowsNum ]; + + + +// ----- Functions ----- + +// Pin action (Strobe, Sense, Strobe Setup, Sense Setup) +// NOTE: This function is highly dependent upon the organization of the register map +// Only guaranteed to work with Freescale MK20 series uCs +uint8_t Matrix_pin( GPIO_Pin gpio, Type type ) +{ + // Register width is defined as size of a pointer + uint8_t port_offset = (uint8_t)gpio.port * sizeof(unsigned int*); + + // Assumes 6 registers between GPIO Port registers + volatile unsigned int GPIO_PDDR = *(&GPIOA_PDDR + port_offset * 6); + volatile unsigned int GPIO_PSOR = *(&GPIOA_PSOR + port_offset * 6); + volatile unsigned int GPIO_PCOR = *(&GPIOA_PCOR + port_offset * 6); + volatile unsigned int GPIO_PDIR = *(&GPIOA_PDIR + port_offset * 6); + + // Assumes 35 registers between PORT pin registers + volatile unsigned int PORT_PCR = *(&PORTA_PCR0 + port_offset * 35); + + // Operation depends on Type + switch ( type ) + { + case Type_StrobeOn: + GPIO_PSOR |= (1 << gpio.pin); + break; + + case Type_StrobeOff: + GPIO_PCOR |= (1 << gpio.pin); + break; + + case Type_StrobeSetup: + // Set as output pin + GPIO_PDDR |= (1 << gpio.pin); + + // Configure pin with slow slew, high drive strength and GPIO mux + PORT_PCR = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1); + + // Enabling open-drain if specified + switch ( Matrix_type ) + { + case Config_Opendrain: + PORT_PCR |= PORT_PCR_ODE; + break; + + // Do nothing otherwise + default: + break; + } + break; + + case Type_Sense: + return GPIO_PDIR & (1 << gpio.pin) ? 1 : 0; + + case Type_SenseSetup: + // Set as input pin + GPIO_PDDR &= ~(1 << gpio.pin); + + // Configure pin with passive filter and GPIO mux + PORT_PCR = PORT_PCR_PFE | PORT_PCR_MUX(1); + + // Pull resistor config + switch ( Matrix_type ) + { + case Config_Pullup: + PORT_PCR |= PORT_PCR_PE | PORT_PCR_PS; + break; + + case Config_Pulldown: + PORT_PCR |= PORT_PCR_PE; + break; + + // Do nothing otherwise + default: + break; + } + break; + } + + return 0; +} + +// Setup GPIO pins for matrix scanning +void Matrix_setup() +{ + // Setup Strobe Pins + for ( uint8_t pin = 0; pin < Matrix_colsNum; pin++ ) + { + Matrix_pin( Matrix_cols[ pin ], Type_StrobeSetup ); + } + + // Setup Sense Pins + for ( uint8_t pin = 0; pin < Matrix_rowsNum; pin++ ) + { + Matrix_pin( Matrix_rows[ pin ], Type_SenseSetup ); + } + + // Clear out Debounce Array + for ( uint8_t item = 0; item < Matrix_maxKeys; item++ ) + { + Matrix_scanArray[ item ].prevState = KeyState_Off; + Matrix_scanArray[ item ].curState = KeyState_Off; + Matrix_scanArray[ item ].activeCount = 0; + Matrix_scanArray[ item ].inactiveCount = 0; + } +} + +// Scan the matrix for keypresses +// NOTE: firstScan should be set on the first scan after a USB send (to reset all the counters) +void Matrix_scan( uint16_t scanNum, uint8_t firstScan ) +{ + // For each strobe, scan each of the sense pins + for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ ) + { + // Strobe Pin + Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOn ); + + // Scan each of the sense pins + for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ ) + { + // Key position + uint8_t key = Matrix_rowsNum * strobe + sense; + KeyState *state = &Matrix_scanArray[ key ]; + + // If first scan, reset state + if ( firstScan ) + { + // Set previous state, and reset current state + state->prevState = state->curState; + state->curState = KeyState_Invalid; + } + + // Signal Detected + if ( Matrix_pin( Matrix_rows[ sense ], Type_Sense ) ) + { + // Only update if not going to wrap around + state->activeCount += state->activeCount < 255 ? 1 : 0; + state->inactiveCount -= state->inactiveCount > 0 ? 1 : 0; + } + // Signal Not Detected + else + { + // Only update if not going to wrap around + state->inactiveCount += state->inactiveCount < 255 ? 1 : 0; + state->activeCount -= state->activeCount > 0 ? 1 : 0; + } + + // Check for state change if it hasn't been set + // Only check if the minimum number of scans has been met + // the current state is invalid + // and either active or inactive count is over the debounce threshold + if ( scanNum > DEBOUNCE_THRESHOLD + && state->curState != KeyState_Invalid + && ( state->activeCount > DEBOUNCE_THRESHOLD || state->inactiveCount > DEBOUNCE_THRESHOLD ) ) + { + switch ( state->prevState ) + { + case KeyState_Press: + case KeyState_Hold: + if ( state->activeCount > DEBOUNCE_THRESHOLD ) + { + state->curState = KeyState_Hold; + } + else + { + state->curState = KeyState_Release; + } + break; + + case KeyState_Release: + case KeyState_Off: + if ( state->activeCount > DEBOUNCE_THRESHOLD ) + { + state->curState = KeyState_Press; + } + else if ( state->inactiveCount > DEBOUNCE_THRESHOLD ) + { + state->curState = KeyState_Off; + } + break; + + case KeyState_Invalid: + erro_print("Matrix scan bug!! Report me!"); + break; + } + + // Send keystate to macro module + Macro_keyState( key, state->curState ); + } + } + + // Unstrobe Pin + Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOff ); + } +} + diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h new file mode 100644 index 0000000..bdf727e --- /dev/null +++ b/Scan/MatrixARM/matrix_scan.h @@ -0,0 +1,128 @@ +/* Copyright (C) 2014 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 ----- + + + +// ----- Enums ----- + +// Freescale MK20s have GPIO ports A...E +typedef enum Port { + Port_A = 0, + Port_B = 1, + Port_C = 2, + Port_D = 3, + Port_E = 4, +} Port; + +// Each port has a possible 32 pins +typedef enum Pin { + Pin_0 = 0, + Pin_1 = 1, + Pin_2 = 2, + Pin_3 = 3, + Pin_4 = 4, + Pin_5 = 5, + Pin_6 = 6, + Pin_7 = 7, + Pin_8 = 8, + Pin_9 = 9, + Pin_10 = 10, + Pin_11 = 11, + Pin_12 = 12, + Pin_13 = 13, + Pin_14 = 14, + Pin_15 = 15, + Pin_16 = 16, + Pin_17 = 17, + Pin_18 = 18, + Pin_19 = 19, + Pin_20 = 20, + Pin_21 = 21, + Pin_22 = 22, + Pin_23 = 23, + Pin_24 = 24, + Pin_25 = 25, + Pin_26 = 26, + Pin_27 = 27, + Pin_28 = 28, + Pin_29 = 29, + Pin_30 = 30, + Pin_31 = 31, +} Pin; + +// Type of pin +typedef enum Type { + Type_StrobeOn, + Type_StrobeOff, + Type_StrobeSetup, + Type_Sense, + Type_SenseSetup, +} Type; + +// Sense/Strobe configuration +typedef enum Config { + Config_Pullup, // Internal pull-up + Config_Pulldown, // Internal pull-down + Config_Opendrain, // External pull resistor +} Config; + +// Keypress States +typedef enum KeyPosition { + KeyState_Off = 0, + KeyState_Press = 1, + KeyState_Hold = 2, + KeyState_Release = 3, + KeyState_Invalid, +} KeyPosition; + + + +// ----- Structs ----- + +// Struct container for defining Rows (Sense) and Columns (Strobes) +typedef struct GPIO_Pin { + Port port; + Pin pin; +} GPIO_Pin; + +// Debounce Element +typedef struct KeyState { + KeyPosition prevState; + KeyPosition curState; + uint8_t activeCount; + uint8_t inactiveCount; +} KeyState; + + + +// ----- Functions ----- + +void Matrix_setup(); +void Matrix_scan( uint16_t scanNum, uint8_t firstScan ); + + +#endif // __MATRIX_SCAN_H + diff --git a/Scan/MatrixARM/setup.cmake b/Scan/MatrixARM/setup.cmake new file mode 100644 index 0000000..631f6d6 --- /dev/null +++ b/Scan/MatrixARM/setup.cmake @@ -0,0 +1,36 @@ +###| CMake Kiibohd Controller Scan Module |### +# +# Written by Jacob Alexander in 2014 for the Kiibohd Controller +# +# Released into the Public Domain +# +### + +### +# Warning, that this module is not meant to be built stand-alone +# +message( FATAL_ERROR +"The 'MatrixARM' module is not a stand-alone module, and requires further setup." +) + +### +# Module C files +# + +set( SCAN_SRCS + matrix_scan.c +) + + +### +# Module Specific Options +# + + +### +# Compiler Family Compatibility +# +set( ScanModuleCompatibility + arm +) +