jsoltren/XMIT build fixes for macOS
[jackhill/qmk/firmware.git] / keyboards / xwhatsit / matrix.c
index 7faadd8..70a380a 100644 (file)
 #include "matrix_manipulate.h"
 #include <string.h>
 
-#if defined(CONTROLLER_IS_XWHATSIT_BEAMSPRING_REV_4)
-#define CAPSENSE_DAC_SCLK   B1
-#define CAPSENSE_DAC_DIN    B2
-#define CAPSENSE_DAC_SYNC_N B0
-#define CAPSENSE_DAC_MAX    1023
-
-#define CAPSENSE_SHIFT_DIN  C4
-#define CAPSENSE_SHIFT_OE   C6
-#define CAPSENSE_SHIFT_SHCP C5
-#define CAPSENSE_SHIFT_STCP C7
-#define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTC)
-#define CAPSENSE_SHIFT_STCP_BIT 7
-
-#define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PIND)
-#define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
-#define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
-#define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
-#define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
-#define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
-#define CAPSENSE_READ_ROWS_VALUE (dest_row_1 & 0xf)
-// Note: for now Beamspring reads PIND twice to match model F timings. We might change that in the future
-
-#define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (row)
-#define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (row)
-#ifndef CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL
-#define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (col)
-#endif
-#define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
-
-#elif defined(CONTROLLER_IS_XWHATSIT_MODEL_F_OR_WCASS_MODEL_F)
-
-#define CAPSENSE_DAC_SCLK   B1
-#define CAPSENSE_DAC_DIN    B2
-#define CAPSENSE_DAC_SYNC_N B0
-#define CAPSENSE_DAC_MAX    1023
-
-#define CAPSENSE_SHIFT_DIN  D4
-#define CAPSENSE_SHIFT_OE   D5
-#define CAPSENSE_SHIFT_SHCP D7
-#define CAPSENSE_SHIFT_STCP D6
-#define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTD)
-#define CAPSENSE_SHIFT_STCP_BIT 6
-
-#define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PINC)
-#define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
-#define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
-#define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
-#define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
-#define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
-#define CAPSENSE_READ_ROWS_VALUE ((dest_row_1 >> 4) | (dest_row_2 << 4))
-
-#define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (7-(row))
-#define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (7-(row))
-#ifndef CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL
-#define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (col)
-#endif
-#define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
-
-#elif defined(CONTROLLER_IS_THROUGHT_HOLE_BEAMSPRING)
-
-#define CAPSENSE_DAC_MCP4921
-#define CAPSENSE_DAC_NCS F6
-#define CAPSENSE_DAC_SCK B1
-#define CAPSENSE_DAC_SDI B2
-#define CAPSENSE_DAC_MAX 4095
-
-#define CAPSENSE_SHIFT_DIN  B2
-#define CAPSENSE_SHIFT_OE   B6
-#define CAPSENSE_SHIFT_SHCP B1
-#define CAPSENSE_SHIFT_STCP F7
-#define CAPSENSE_SHIFT_STCP_IO _SFR_IO_ADDR(PORTF)
-#define CAPSENSE_SHIFT_STCP_BIT 7
-
-
-// TODO
-// Rows:
-// Physical position from left to right: (only the right-most are used for beamspring)
-// 1    2    3    4    5    6    7    8
-// TH schematic numbering (sense/row lines)
-// 8    6    7    5    4    3    2    1
-// F5,  B5,  F4,  B4,  D4,  C6,  D1,  D0
-#define CAPSENSE_READ_ROWS_PIN_1 _SFR_IO_ADDR(PINC)
-#define CAPSENSE_READ_ROWS_PIN_2 _SFR_IO_ADDR(PIND)
-#define CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS "in %[dest_row_1], %[ioreg_row_1]\n\tin %[dest_row_2], %[ioreg_row_2]"
-#define CAPSENSE_READ_ROWS_OUTPUT_CONSTRAINTS [dest_row_1] "=&r" (dest_row_1), [dest_row_2] "=&r" (dest_row_2)
-#define CAPSENSE_READ_ROWS_INPUT_CONSTRAINTS [ioreg_row_1] "I" (CAPSENSE_READ_ROWS_PIN_1), [ioreg_row_2] "I" (CAPSENSE_READ_ROWS_PIN_2)
-#define CAPSENSE_READ_ROWS_LOCAL_VARS uint8_t dest_row_1, dest_row_2
-#define CAPSENSE_READ_ROWS_VALUE (((dest_row_1 >> 4) & 0x04) | (dest_row_2 & 0x03) | ((dest_row_2 >> 1) & 0x08))
-
-#define CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row) (3-(row))
-#define CAPSENSE_PHYSICAL_ROW_TO_KEYMAP_ROW(row) (3-(row))
-#ifndef CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL
-#define CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col) (col)
-#endif
-//#define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS
-#define CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
-// TODO END
+/* Notes on Expansion Header:
 
-#else
+Pinout:
+--1--O   O--2--
+--3--O   O--4--
+--5--O   O--6--
 
-#ifndef CAPSENSE_DAC_SCLK
-#error "Please select controller type in config.h, or please define each macro that is defined when selecting a particular macro type in matrix.c"
-#endif
-#endif
+Pin 1 is always VCC
+Pin 6 in always GND
 
-#ifndef CAPSENSE_KEYBOARD_SETTLE_TIME_US
-#error "Please define CAPSENSE_KEYBOARD_SETTLE_TIME_US in config.h"
-#endif
-#ifndef CAPSENSE_DAC_SETTLE_TIME_US
-#error "Please define CAPSENSE_DAC_SETTLE_TIME_US in config.h"
-#endif
-#ifndef CAPSENSE_HARDCODED_SAMPLE_TIME
-#error "Please define CAPSENSE_HARDCODED_SAMPLE_TIME in config.h"
-#endif
+When using xwhatsit's solenoid controller board,
+pin 2 is connected to the ENABLE input of the current
+limiter, and pin 4 drives the solenoid.
 
-#ifndef CAPSENSE_CAL_ENABLED
-#error "Please define CAPSENSE_CAL_ENABLED as 1/0 in config.h"
-#endif
-#ifndef CAPSENSE_CAL_DEBUG
-#error "Please define CAPSENSE_CAL_DEBUG as 1/0 in config.h"
-#endif
-#ifndef CAPSENSE_CAL_INIT_REPS
-#define CAPSENSE_CAL_INIT_REPS 16
-#endif
-#ifndef CAPSENSE_CAL_EACHKEY_REPS
-#define CAPSENSE_CAL_EACHKEY_REPS 16
-#endif
-#ifndef CAPSENSE_CAL_BINS
-#error "Please define CAPSENSE_CAL_BINS in config.h"
-#endif
-#ifndef CAPSENSE_CAL_THRESHOLD_OFFSET
-#error "Please define CAPSENSE_CAL_THRESHOLD_OFFSET in config.h"
-#endif
+On original xwhatsit controllers:
+pin 2 = PB7
+pin 3 = PB4
+pin 4 = PB6
+pin 5 = PB5
 
-#if (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS)) && (!defined(CAPSENSE_CONDUCTIVE_PLASTIC_IS_PUSHED_DOWN_ON_KEYPRESS))
-#error "Please specify whether the flyplate is pushed down or pulled up on keypress!"
-#endif
+On the TH xwhatsit controller:
+pin 2 = HEADER3 = TXO        = PD3
+pin 3 = HEADER1 = D(igital)6 = PD7
+pin 4 = HEADER4 = RXI        = PD2
+pin 5 = HEADER2 = D(igital)7 = PE6
+*/
+
+// USING_SOLENOID_ENABLE_PIN must be defined in config.h if you are using and xwhatsit type solenoid
 
 static inline uint8_t read_rows(void)
 {
@@ -234,7 +125,8 @@ void dac_write_threshold(uint16_t value)
 
 #endif
 
-#define SHIFT_BITS ((MATRIX_COLS > 16) ? 24 : 16)
+#define SHIFT_BITS (((CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(MATRIX_COLS - 1) >= 16) || \
+                     (CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(0) >= 16)) ? 24 : 16)
 
 void shift_select_nothing(void)
 {
@@ -249,18 +141,25 @@ void shift_select_nothing(void)
     writePin(CAPSENSE_SHIFT_STCP, 0);
 }
 
-void shift_data(uint32_t data)
+void shift_data(uint32_t data, int data_idle, int shcp_idle, int stcp_idle)
 {
     int i;
+    writePin(CAPSENSE_SHIFT_SHCP, 0);
+    writePin(CAPSENSE_SHIFT_STCP, 0);
     for (i=SHIFT_BITS-1; i>=0; i--)
     {
         writePin(CAPSENSE_SHIFT_DIN, (data >> (SHIFT_BITS - 1)) & 1);
         writePin(CAPSENSE_SHIFT_SHCP, 1);
-        writePin(CAPSENSE_SHIFT_SHCP, 0);
+        if (!((i == 0) && (shcp_idle))) {
+            writePin(CAPSENSE_SHIFT_SHCP, 0);
+        }
         data <<= 1;
     }
     writePin(CAPSENSE_SHIFT_STCP, 1);
-    writePin(CAPSENSE_SHIFT_STCP, 0);
+    if (!stcp_idle) {
+        writePin(CAPSENSE_SHIFT_STCP, 0);
+    }
+    writePin(CAPSENSE_SHIFT_DIN, !!data_idle);
 }
 
 void shift_select_col_no_strobe(uint8_t col)
@@ -287,13 +186,28 @@ void shift_init(void)
     setPinOutput(CAPSENSE_SHIFT_OE);
     setPinOutput(CAPSENSE_SHIFT_STCP);
     setPinOutput(CAPSENSE_SHIFT_SHCP);
+    writePin(CAPSENSE_SHIFT_OE, 0);
     writePin(CAPSENSE_SHIFT_STCP, 0);
     writePin(CAPSENSE_SHIFT_SHCP, 0);
     shift_select_nothing();
     wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
 }
 
-// the following function requires storage for 2 * (time + 1) bytes
+// Timing:
+// IN instructions (1 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE)
+// Store to array instructions (2 * number of bytes)
+// adiw: 1 cycle
+// cp: 1 cycle
+// cpc: 1 cycle
+// brlo: 2 cycles (when jumping)
+// --- Total loop length:
+// 3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 cycles
+// first sample elements will be taken after [1..CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE-1] cycles
+// second sample elements will be taken after
+//       [3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 + 1..
+//        3 * CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 5 + CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE-1] cycles
+
+// the following function requires storage for CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE * (time + 1) bytes
 // but returns valid data only in the first (time + 1) bytes
 void test_multiple(uint8_t col, uint16_t time, uint8_t *array)
 {
@@ -306,9 +220,8 @@ void test_multiple(uint8_t col, uint16_t time, uint8_t *array)
              "ldi %B[index], 0"                 "\n\t"
              "cli"                              "\n\t"
              "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
-        "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS         "\n\t"
-             "st %a[arr]+, %[dest_row_1]"       "\n\t"
-             "st %a[arr]+, %[dest_row_2]"       "\n\t"
+        "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS            "\n\t"
+             CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS "\n\t"
              "adiw %A[index], 0x01"             "\n\t"
              "cp %A[index], %A[time]"           "\n\t"
              "cpc %B[index], %B[time]"          "\n\t"
@@ -328,29 +241,29 @@ void test_multiple(uint8_t col, uint16_t time, uint8_t *array)
     p0 = p1 = 0;
     for (i=0; i<=time; i++)
     {
-        dest_row_1 = array[p0++];
-        dest_row_2 = array[p0++];
+        CAPSENSE_READ_ROWS_EXTRACT_FROM_ARRAY;
         array[p1++] = CAPSENSE_READ_ROWS_VALUE;
     }
     shift_select_nothing();
     wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
 }
 
-uint8_t test_single(uint8_t col, uint16_t time)
+uint8_t test_single(uint8_t col, uint16_t time, uint8_t *interference_ptr)
 {
     shift_select_col_no_strobe(col);
     uint16_t index;
     CAPSENSE_READ_ROWS_LOCAL_VARS;
-    uint8_t dummy_data;
-    uint8_t *arrayp = &dummy_data;
+    uint8_t array[CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE + 1]; // one sample before triggering, and one dummy byte
+    uint8_t *arrayp = array;
     asm volatile (
              "ldi %A[index], 0"                 "\n\t"
              "ldi %B[index], 0"                 "\n\t"
              "cli"                              "\n\t"
+             CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS                 "\n\t"
+             CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS      "\n\t"
              "sbi %[stcp_regaddr], %[stcp_bit]" "\n\t"
-        "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS         "\n\t"
-             "st %a[arr], %[dest_row_1]"       "\n\t"
-             "st %a[arr], %[dest_row_2]"       "\n\t"
+        "1:" CAPSENSE_READ_ROWS_ASM_INSTRUCTIONS                 "\n\t"
+             CAPSENSE_READ_ROWS_STORE_TO_ARRAY_INSTRUCTIONS_FAKE "\n\t"
              "adiw %A[index], 0x01"             "\n\t"
              "cp %A[index], %A[time]"           "\n\t"
              "cpc %B[index], %B[time]"          "\n\t"
@@ -368,7 +281,15 @@ uint8_t test_single(uint8_t col, uint16_t time)
       : "memory" );
     shift_select_nothing();
     wait_us(CAPSENSE_KEYBOARD_SETTLE_TIME_US);
-    return CAPSENSE_READ_ROWS_VALUE;
+    uint8_t value_at_time = CAPSENSE_READ_ROWS_VALUE;
+    if (interference_ptr)
+    {
+        uint16_t p0 = 0;
+        CAPSENSE_READ_ROWS_EXTRACT_FROM_ARRAY;
+        uint8_t interference = CAPSENSE_READ_ROWS_VALUE;
+        *interference_ptr = interference;
+    }
+    return value_at_time;
 }
 
 #ifndef NO_PRINT
@@ -378,7 +299,7 @@ uint8_t test_single(uint8_t col, uint16_t time)
 void test_col_print_data_v2(uint8_t col)
 {
     uprintf("%d: ", col);
-    static uint8_t data[NRTIMES*2];
+    static uint8_t data[NRTIMES*CAPSENSE_READ_ROWS_NUMBER_OF_BYTES_PER_SAMPLE];
     static uint8_t sums[(TESTATONCE+1) * MATRIX_ROWS];
     uint8_t to_time = NRTIMES-1;
     uint8_t from_time = 0;
@@ -514,7 +435,7 @@ uint16_t measure_middle(uint8_t col, uint8_t row, uint8_t time, uint8_t reps)
         uint8_t i;
         for (i=0;i<reps;i++)
         {
-            sum += (test_single(col, time) >> row) & 1;
+            sum += (test_single(col, time, NULL) >> row) & 1;
         }
         if (sum < reps_div2)
         {
@@ -611,13 +532,13 @@ uint16_t calibration_measure_all_valid_keys(uint8_t time, uint8_t reps, bool loo
             for (i=0;i<reps;i++) {
                 if (looking_for_all_zero)
                 {
-                    uint8_t all_zero = (test_single(physical_col, time) & valid_physical_rows) == 0;
+                    uint8_t all_zero = (test_single(physical_col, time, NULL) & valid_physical_rows) == 0;
                     if (!all_zero) {
                         min = mid + 1;
                         goto next_binary_search;
                     }
                 } else {
-                    uint8_t all_ones = (test_single(physical_col, time) & valid_physical_rows) == valid_physical_rows;
+                    uint8_t all_ones = (test_single(physical_col, time, NULL) & valid_physical_rows) == valid_physical_rows;
                     if (!all_ones) {
                         max = mid - 1;
                         goto next_binary_search;
@@ -709,8 +630,46 @@ void calibration(void)
     }
 }
 
+void set_leds(int num_lock, int caps_lock, int scroll_lock)
+{
+    #if defined(LED_NUM_LOCK_PIN)
+        #if defined(LED_NUM_LOCK_ACTIVE_LOW)
+            writePin(LED_NUM_LOCK_PIN, !num_lock);
+        #else
+            writePin(LED_NUM_LOCK_PIN, num_lock);
+        #endif
+    #endif
+    #if defined(LED_CAPS_LOCK_PIN)
+        #if defined(LED_CAPS_LOCK_ACTIVE_LOW)
+            writePin(LED_CAPS_LOCK_PIN, !caps_lock);
+        #else
+            writePin(LED_CAPS_LOCK_PIN, caps_lock);
+        #endif
+    #endif
+    #if defined(LED_SCROLL_LOCK_PIN)
+        #if defined(LED_SCROLL_LOCK_ACTIVE_LOW)
+            writePin(LED_SCROLL_LOCK_PIN, !scroll_lock);
+        #else
+            writePin(LED_SCROLL_LOCK_PIN, scroll_lock);
+        #endif
+    #endif
+}
+
 void real_keyboard_init_basic(void)
 {
+    SETUP_UNUSED_PINS();
+
+    #if defined(LED_NUM_LOCK_PIN)
+        setPinOutput(LED_NUM_LOCK_PIN);
+    #endif
+    #if defined(LED_CAPS_LOCK_PIN)
+        setPinOutput(LED_CAPS_LOCK_PIN);
+    #endif
+    #if defined(LED_SCROLL_LOCK_PIN)
+        setPinOutput(LED_SCROLL_LOCK_PIN);
+    #endif
+    set_leds(0, 0, 0);
+
     #ifndef NO_PRINT
     uprintf("shift_init()");
     #endif
@@ -723,6 +682,7 @@ void real_keyboard_init_basic(void)
     #ifndef NO_PRINT
     uprintf(" DONE\n");
     #endif
+    SETUP_ROW_GPIOS();
     #if CAPSENSE_CAL_ENABLED
     calibration();
     #else
@@ -730,16 +690,32 @@ void real_keyboard_init_basic(void)
     dac_write_threshold(CAPSENSE_HARDCODED_THRESHOLD);
     dac_write_threshold(CAPSENSE_HARDCODED_THRESHOLD);
     #endif
-    #if defined(CONTROLLER_IS_THROUGHT_HOLE_BEAMSPRING)
+    #if defined(CONTROLLER_IS_THROUGH_HOLE_BEAMSPRING) || defined(CONTROLLER_IS_THROUGH_HOLE_MODEL_F)
         // Disable on-board leds.
         setPinOutput(D5);
         writePin(D5, 1);
         setPinOutput(B0);
         writePin(B0, 1);
     #endif
+    #ifdef USING_SOLENOID_ENABLE_PIN
+        // ^^ this must be defined in config.h if you are using and xwhatsit type solenoid
+        setPinOutput(USING_SOLENOID_ENABLE_PIN);
+        writePin(USING_SOLENOID_ENABLE_PIN, 1);
+    #endif
+}
+
+
+bool led_update_kb(led_t led_state) {
+    bool res = led_update_user(led_state);
+    if(res) {
+        set_leds(led_state.num_lock, led_state.caps_lock, led_state.scroll_lock);
+    }
+    return res;
 }
 
 void matrix_init_custom(void) {
+
+
     //test_v2();
     //tracking_test();
     real_keyboard_init_basic();
@@ -798,21 +774,24 @@ void matrix_scan_raw(matrix_row_t current_matrix[]) {
         dac_write_threshold(cal_thresholds[cal]);
         for (col=0;col<MATRIX_COLS;col++) {
             uint8_t real_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
-            uint8_t d;
+            uint8_t d, interference;
             uint8_t d_tested = 0;
             for (row=0;row<MATRIX_ROWS;row++) {
                 if (assigned_to_threshold[cal][row] & (((matrix_row_t)1) << col))
                 {
                     if (!d_tested)
                     {
-                        d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME);
+                        d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME, &interference);
                         #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
                             d = ~d;
                         #endif
                         d_tested = 1;
                     }
                     uint8_t physical_row = CAPSENSE_KEYMAP_ROW_TO_PHYSICAL_ROW(row);
-                    current_matrix[row] |= ((matrix_row_t)((d >> physical_row) & 1)) << col;
+                    if (!((interference >> physical_row) & 1))
+                    {
+                        current_matrix[row] |= ((matrix_row_t)((d >> physical_row) & 1)) << col;
+                    }
                 }
             }
         }
@@ -821,7 +800,8 @@ void matrix_scan_raw(matrix_row_t current_matrix[]) {
     for (col=0;col<MATRIX_COLS;col++)
     {
         uint8_t real_col = CAPSENSE_KEYMAP_COL_TO_PHYSICAL_COL(col);
-        uint8_t d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME);
+        uint8_t interference;
+        uint8_t d = test_single(real_col, CAPSENSE_HARDCODED_SAMPLE_TIME, &interference);
         #ifdef CAPSENSE_CONDUCTIVE_PLASTIC_IS_PULLED_UP_ON_KEYPRESS
             d = ~d;
         #endif