]> git.donarmstrong.com Git - kiibohd-controller.git/blobdiff - Scan/MatrixARM/matrix_scan.c
Changed CK3 matrix scan to Config_Pullup, inverted rows and columns
[kiibohd-controller.git] / Scan / MatrixARM / matrix_scan.c
index a9018df9494a5d47ba5f3faee7347a207f5840c6..669314329efff3079c93dc065e45800b54cae004 100644 (file)
@@ -30,6 +30,7 @@
 #include <led.h>
 #include <print.h>
 #include <macro.h>
+#include <Lib/delay.h>
 
 // Local Includes
 #include "matrix_scan.h"
@@ -70,6 +71,15 @@ CLIDict_Def( matrixCLIDict, "Matrix Module Commands" ) = {
 // Debounce Array
 KeyState Matrix_scanArray[ Matrix_colsNum * Matrix_rowsNum ];
 
+// Ghost Arrays
+#ifdef GHOSTING_MATRIX
+KeyGhost Matrix_ghostArray[ Matrix_colsNum * Matrix_rowsNum ];
+
+uint8_t col_use[Matrix_colsNum], row_use[Matrix_rowsNum];  // used count
+uint8_t col_ghost[Matrix_colsNum], row_ghost[Matrix_rowsNum];  // marked as having ghost if 1
+#endif
+
+
 // Matrix debug flag - If set to 1, for each keypress the scan code is displayed in hex
 //                     If set to 2, for each key state change, the scan code is displayed along with the state
 uint8_t matrixDebugMode = 0;
@@ -101,7 +111,9 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type )
        // Assumes 0x40 between GPIO Port registers and 0x1000 between PORT pin registers
        // See Lib/mk20dx.h
        volatile unsigned int *GPIO_PDDR = (unsigned int*)(&GPIOA_PDDR) + gpio_offset;
+       #ifndef GHOSTING_MATRIX
        volatile unsigned int *GPIO_PSOR = (unsigned int*)(&GPIOA_PSOR) + gpio_offset;
+       #endif
        volatile unsigned int *GPIO_PCOR = (unsigned int*)(&GPIOA_PCOR) + gpio_offset;
        volatile unsigned int *GPIO_PDIR = (unsigned int*)(&GPIOA_PDIR) + gpio_offset;
        volatile unsigned int *PORT_PCR  = (unsigned int*)(&PORTA_PCR0) + port_offset;
@@ -110,16 +122,30 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type )
        switch ( type )
        {
        case Type_StrobeOn:
+               #ifdef GHOSTING_MATRIX
+               *GPIO_PCOR |= (1 << gpio.pin);
+               *GPIO_PDDR |= (1 << gpio.pin);  // output, low
+               #else
                *GPIO_PSOR |= (1 << gpio.pin);
+               #endif
                break;
 
        case Type_StrobeOff:
+               #ifdef GHOSTING_MATRIX
+               // Ghosting martix needs to put not used (off) strobes in high impedance state
+               *GPIO_PDDR &= ~(1 << gpio.pin);  // input, high Z state
+               #endif
                *GPIO_PCOR |= (1 << gpio.pin);
                break;
 
        case Type_StrobeSetup:
+               #ifdef GHOSTING_MATRIX
+               *GPIO_PDDR &= ~(1 << gpio.pin);  // input, high Z state
+               *GPIO_PCOR |= (1 << gpio.pin);
+               #else
                // Set as output pin
                *GPIO_PDDR |= (1 << gpio.pin);
+               #endif
 
                // Configure pin with slow slew, high drive strength and GPIO mux
                *PORT_PCR = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
@@ -138,7 +164,11 @@ uint8_t Matrix_pin( GPIO_Pin gpio, Type type )
                break;
 
        case Type_Sense:
+               #ifdef GHOSTING_MATRIX  // inverted
+               return *GPIO_PDIR & (1 << gpio.pin) ? 0 : 1;
+               #else
                return *GPIO_PDIR & (1 << gpio.pin) ? 1 : 0;
+               #endif
 
        case Type_SenseSetup:
                // Set as input pin
@@ -206,6 +236,11 @@ void Matrix_setup()
                Matrix_scanArray[ item ].activeCount      = 0;
                Matrix_scanArray[ item ].inactiveCount    = DebounceDivThreshold_define; // Start at 'off' steady state
                Matrix_scanArray[ item ].prevDecisionTime = 0;
+               #ifdef GHOSTING_MATRIX
+               Matrix_ghostArray[ item ].prev            = KeyState_Off;
+               Matrix_ghostArray[ item ].cur             = KeyState_Off;
+               Matrix_ghostArray[ item ].saved           = KeyState_Off;
+               #endif
        }
 
        // Clear scan stats counters
@@ -273,9 +308,19 @@ void Matrix_scan( uint16_t scanNum )
        // For each strobe, scan each of the sense pins
        for ( uint8_t strobe = 0; strobe < Matrix_colsNum; strobe++ )
        {
+               #ifdef STROBE_DELAY
+               uint32_t start = micros();
+               while ((micros() - start) < STROBE_DELAY);
+               #endif
+
                // Strobe Pin
                Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOn );
 
+               #ifdef STROBE_DELAY
+               start = micros();
+               while ((micros() - start) < STROBE_DELAY);
+               #endif
+
                // Scan each of the sense pins
                for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ )
                {
@@ -377,7 +422,9 @@ void Matrix_scan( uint16_t scanNum )
                                state->prevDecisionTime = currentTime;
 
                                // Send keystate to macro module
+                               #ifndef GHOSTING_MATRIX
                                Macro_keyState( key, state->curState );
+                               #endif
 
                                // Matrix Debug, only if there is a state change
                                if ( matrixDebugMode && state->curState != state->prevState )
@@ -403,6 +450,97 @@ void Matrix_scan( uint16_t scanNum )
                Matrix_pin( Matrix_cols[ strobe ], Type_StrobeOff );
        }
 
+
+       // Matrix ghosting check and elimination
+       // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
+#ifdef GHOSTING_MATRIX
+       // strobe = column, sense = row
+
+       // Count (rows) use for columns
+       //print("C ");
+       for ( uint8_t col = 0; col < Matrix_colsNum; col++ )
+       {
+               uint8_t used = 0;
+               for ( uint8_t row = 0; row < Matrix_rowsNum; row++ )
+               {
+                       uint8_t key = Matrix_colsNum * row + col;
+                       KeyState *state = &Matrix_scanArray[ key ];
+                       if ( keyOn(state->curState) )
+                               used++;
+               }
+               //printInt8(used);
+               col_use[col] = used;
+               col_ghost[col] = 0;  // clear
+       }
+
+       // Count (columns) use for rows
+       //print("  R ");
+       for ( uint8_t row = 0; row < Matrix_rowsNum; row++ )
+       {
+               uint8_t used = 0;
+               for ( uint8_t col = 0; col < Matrix_colsNum; col++ )
+               {
+                       uint8_t key = Matrix_colsNum * row + col;
+                       KeyState *state = &Matrix_scanArray[ key ];
+                       if ( keyOn(state->curState) )
+                               used++;
+               }
+               //printInt8(used);
+               row_use[row] = used;
+               row_ghost[row] = 0;  // clear
+       }
+       
+       // Check if matrix has ghost
+       // Happens when key is pressed and some other key is pressed in same row and another in same column
+       //print("  G ");
+       for ( uint8_t col = 0; col < Matrix_colsNum; col++ )
+       {
+               for ( uint8_t row = 0; row < Matrix_rowsNum; row++ )
+               {
+                       uint8_t key = Matrix_colsNum * row + col;
+                       KeyState *state = &Matrix_scanArray[ key ];
+                       if ( keyOn(state->curState) && col_use[col] >= 2 && row_use[row] >= 2 )
+                       {
+                               // mark col and row as having ghost
+                               col_ghost[col] = 1;
+                               row_ghost[row] = 1;
+                               //print(" ");  printInt8(col);  print(",");  printInt8(row);
+                       }
+               }
+       }
+       //print( NL );
+
+       // Send keys
+       for ( uint8_t col = 0; col < Matrix_colsNum; col++ )
+       {
+               for ( uint8_t row = 0; row < Matrix_rowsNum; row++ )
+               {
+                       uint8_t key = Matrix_colsNum * row + col;
+                       KeyState *state = &Matrix_scanArray[ key ];
+                       KeyGhost *st = &Matrix_ghostArray[ key ];
+                       
+                       // col or row is ghosting (crossed)
+                       uint8_t ghost = (col_ghost[col] > 0 || row_ghost[row] > 0) ? 1 : 0;
+                       
+                       st->prev = st->cur;  // previous
+                       // save state if no ghost or outside ghosted area
+                       if ( ghost == 0 )
+                               st->saved = state->curState;  // save state if no ghost
+                       // final
+                       // use saved state if ghosting, or current if not
+                       st->cur = ghost > 0 ? st->saved : state->curState;
+                       
+                       //  Send keystate to macro module
+                       KeyPosition k = !st->cur 
+                               ? (!st->prev ? KeyState_Off : KeyState_Release)
+                               : ( st->prev ? KeyState_Hold : KeyState_Press);
+                       Macro_keyState( key, k );
+               }
+       }
+#endif
+       // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 
+
+
        // State Table Output Debug
        if ( matrixDebugStateCounter > 0 )
        {