- Cleaned up Macro and USB callback naming - Added security jumper for automated reload (MCHCK based only) - Added additional LED positionsimple
#| Please look at the {Scan,Macro,Output,Debug} for information on the modules and how to create new ones | #| 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 | ##| 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 | ##| Provides the mapping functions for DefaultMap and handles any macro processing before sending to the OutputModule | ||||
set( MacroModule "PartialMap" ) | set( MacroModule "PartialMap" ) |
// MCHCK | // MCHCK | ||||
#elif defined(_mk20dx128vlf5_) | #elif defined(_mk20dx128vlf5_) | ||||
/* Actual MCHCK | |||||
// Enable pin | // Enable pin | ||||
GPIOB_PDDR |= (1<<16); | GPIOB_PDDR |= (1<<16); | ||||
// Setup pin - B16 - See Lib/pin_map.mchck for more details on pins | // 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); | 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 | #endif | ||||
} | } | ||||
// MCHCK | // MCHCK | ||||
#elif defined(_mk20dx128vlf5_) | #elif defined(_mk20dx128vlf5_) | ||||
/* Actual MCHCK | |||||
// Error LED On (B16) | // Error LED On (B16) | ||||
if ( on ) { | if ( on ) { | ||||
GPIOB_PSOR |= (1<<16); | GPIOB_PSOR |= (1<<16); | ||||
else { | else { | ||||
GPIOB_PCOR |= (1<<16); | 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 | #endif | ||||
} | } |
#include <stdint.h> | #include <stdint.h> | ||||
// chapter 11: Port control and interrupts (PORT) | // 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_ISF (uint32_t)0x01000000 // Interrupt Status Flag | ||||
#define PORT_PCR_IRQC(n) (uint32_t)(((n) & 15) << 16) // Interrupt Configuration | #define PORT_PCR_IRQC(n) (uint32_t)(((n) & 15) << 16) // Interrupt Configuration | ||||
#define PORT_PCR_IRQC_MASK (uint32_t)0x000F0000 | #define PORT_PCR_IRQC_MASK (uint32_t)0x000F0000 | ||||
#define PORT_PCR_SRE (uint32_t)0x00000004 // Slew Rate Enable | #define PORT_PCR_SRE (uint32_t)0x00000004 // Slew Rate Enable | ||||
#define PORT_PCR_PE (uint32_t)0x00000002 // Pull Enable | #define PORT_PCR_PE (uint32_t)0x00000002 // Pull Enable | ||||
#define PORT_PCR_PS (uint32_t)0x00000001 // Pull Select | #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_PCR1 *(volatile uint32_t *)0x40049004 // Pin Control Register n | ||||
#define PORTA_PCR2 *(volatile uint32_t *)0x40049008 // 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 | #define PORTA_PCR3 *(volatile uint32_t *)0x4004900C // Pin Control Register n |
} | } | ||||
// 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 | // Macro Procesing Loop | ||||
// Called once per USB buffer send | // Called once per USB buffer send | ||||
inline void Macro_process() | 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 Macro debug mode is set, clear the USB Buffer | ||||
if ( macroDebugMode ) | if ( macroDebugMode ) |
/* Copyright (C) 2014 by Jacob Alexander | /* 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 <http://www.gnu.org/licenses/>. | |||||
*/ | */ | ||||
#ifndef __macro_h | #ifndef __macro_h | ||||
// ----- Defines ----- | |||||
// Key states (DO NOT USE for analog keyboards) | |||||
#define DEPRESSED 0 | |||||
#define RELEASED 1 | |||||
#define PRESSED 254 | |||||
#define HELD 255 | |||||
// ----- Variables ----- | |||||
// ----- Macros ----- | |||||
// ----- Functions ----- | // ----- Functions ----- | ||||
void Macro_keyState( uint8_t scanCode, uint8_t state ); | void Macro_keyState( uint8_t scanCode, uint8_t state ); | ||||
void Macro_analogState( 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_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_process(); | ||||
void Macro_setup(); | void Macro_setup(); | ||||
{ | { | ||||
// MCHCK | // MCHCK | ||||
#if defined(_mk20dx128vlf5_) | #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 | // Teensy 3.0 and 3.1 | ||||
#else | #else | ||||
asm volatile("bkpt"); | asm volatile("bkpt"); |
USBKeys_Modifiers = 0; | USBKeys_Modifiers = 0; | ||||
USBKeys_Sent = 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 ); | |||||
} | } | ||||
USBKeys_Modifiers = 0; | USBKeys_Modifiers = 0; | ||||
USBKeys_Sent = 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 ); | |||||
} | } | ||||
/* 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 | |||||
/* 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 <Lib/ScanLib.h> | |||||
// Project Includes | |||||
#include <cli.h> | |||||
#include <led.h> | |||||
#include <print.h> | |||||
// 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; | |||||
} | |||||
/* 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 <stdint.h> | |||||
// 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 | |||||
###| 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 | |||||
) | |||||
/* 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 <Lib/ScanLib.h> | |||||
// Project Includes | |||||
#include <cli.h> | |||||
#include <led.h> | |||||
#include <print.h> | |||||
#include <macro.h> | |||||
// Local Includes | |||||
#include "matrix_scan.h" | |||||
// Matrix Configuration | |||||
#include <matrix.h> | |||||
// ----- 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 ); | |||||
} | |||||
} | |||||
/* 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 | |||||
###| 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 | |||||
) | |||||