]> git.donarmstrong.com Git - kiibohd-controller.git/commitdiff
Initial MatrixARM implementation
authorJacob Alexander <haata@kiibohd.com>
Fri, 1 Aug 2014 08:26:25 +0000 (01:26 -0700)
committerJacob Alexander <haata@kiibohd.com>
Fri, 1 Aug 2014 08:26:25 +0000 (01:26 -0700)
- Cleaned up Macro and USB callback naming
- Added security jumper for automated reload (MCHCK based only)
- Added additional LED position

16 files changed:
CMakeLists.txt
Debug/led/led.c
Lib/mk20dx.h
Macro/PartialMap/macro.c
Macro/PartialMap/macro.h
Output/pjrcUSB/arm/usb_dev.c
Output/pjrcUSB/output_com.c
Output/usbMuxUart/output_com.c
Scan/MD1/defaultMap.h [new file with mode: 0644]
Scan/MD1/matrix.h [new file with mode: 0644]
Scan/MD1/scan_loop.c [new file with mode: 0644]
Scan/MD1/scan_loop.h [new file with mode: 0644]
Scan/MD1/setup.cmake [new file with mode: 0644]
Scan/MatrixARM/matrix_scan.c [new file with mode: 0644]
Scan/MatrixARM/matrix_scan.h [new file with mode: 0644]
Scan/MatrixARM/setup.cmake [new file with mode: 0644]

index 4ec941c0e1377a23867bff0a20f821f1fd77a082..e053e0456bb24a3f41b9c4c88e1b916def057cb6 100644 (file)
@@ -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" )
index 22a70c99f35d1e2431cc20d86334f084aafeedb2..ece3a48deb87371b7b8e22cef26d3f17b5e0e71e 100644 (file)
@@ -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
 }
index 9af51a386283569cfeab44e365a7ab825a4f8f0a..42be1540067cbf840ca67d8e682381001bda1915 100644 (file)
@@ -57,7 +57,6 @@
 #include <stdint.h>
 
 // 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
index 02caa9796a9dff93b5235d5511ec89b6812dff58..50cee843c0e5eb0844143a1f8bab87861c84b958 100644 (file)
@@ -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 )
index 6722c2ca9906eabdcc93894e687db98b3f0e02a1..b78cd5da19c6d312383907154f7624e4cc78c2e9 100644 (file)
@@ -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 <http://www.gnu.org/licenses/>.
  */
 
 #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 -----
 
 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();
 
index aab87f2f5b2e91ef4ead39d23cbb588674ecddb1..3b2d3a98e7dca758089932bc2bf19ba471ee9ed5 100644 (file)
@@ -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");
index 8acc4a3ca980288d007ba47fb90be840b0ce0500..bd748ad0ffcb11ec447947fe59518c7dd445a8c4 100644 (file)
@@ -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 );
 }
 
 
index 80c7a4cc9a5a33741d0739ace70b9a705a68cd41..86f5cf6b5a4c0258e26657b2e62804d04a992a51 100644 (file)
@@ -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 (file)
index 0000000..e69de29
diff --git a/Scan/MD1/matrix.h b/Scan/MD1/matrix.h
new file mode 100644 (file)
index 0000000..948f7db
--- /dev/null
@@ -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 (file)
index 0000000..5481d30
--- /dev/null
@@ -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 <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;
+}
+
diff --git a/Scan/MD1/scan_loop.h b/Scan/MD1/scan_loop.h
new file mode 100644 (file)
index 0000000..73508bb
--- /dev/null
@@ -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 <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
+
diff --git a/Scan/MD1/setup.cmake b/Scan/MD1/setup.cmake
new file mode 100644 (file)
index 0000000..3b6ea0c
--- /dev/null
@@ -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 (file)
index 0000000..d31441d
--- /dev/null
@@ -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 <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 );
+       }
+}
+
diff --git a/Scan/MatrixARM/matrix_scan.h b/Scan/MatrixARM/matrix_scan.h
new file mode 100644 (file)
index 0000000..bdf727e
--- /dev/null
@@ -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 (file)
index 0000000..631f6d6
--- /dev/null
@@ -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
+)
+