diff --git a/keyboards/massdrop/alt/alt.c b/keyboards/massdrop/alt/alt.c
new file mode 100644
index 000000000..81dd66b3c
--- /dev/null
+++ b/keyboards/massdrop/alt/alt.c
@@ -0,0 +1,21 @@
+/*
+Copyright 2021 Massdrop Inc.
+
+This program 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 2 of the License, or
+(at your option) any later version.
+
+This program 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.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+#include "alt.h"
+
+/* Temporary solution for matrix delay */
+void matrix_output_select_delay(void) { matrix_io_delay(); }
+void matrix_output_unselect_delay(void) { }
diff --git a/keyboards/massdrop/alt/config.h b/keyboards/massdrop/alt/config.h
index d8389fc00..d28094c49 100644
--- a/keyboards/massdrop/alt/config.h
+++ b/keyboards/massdrop/alt/config.h
@@ -32,18 +32,21 @@ along with this program. If not, see .
#define MATRIX_ROWS 5
#define MATRIX_COLS 15
+
+#define MATRIX_ROW_PINS { A00, A01, A02, A03, A04 }
+#define MATRIX_COL_PINS { B04, B05, B06, B07, B08, B09, B10, B11, B12, B13, A05, A06, A07, A10, A11 }
+#define UNUSED_PINS
+
+/* COL2ROW, ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Temporary solution for matrix delay */
+#define IGNORE_ATOMIC_BLOCK
+
/* MCU Port name definitions */
#define PA 0
#define PB 1
-/* Port and Pin definition of key row hardware configuration */
-#define MATRIX_ROW_PORTS PA, PA, PA, PA, PA
-#define MATRIX_ROW_PINS 0, 1, 2, 3, 4
-
-/* Port and Pin definition of key column hardware configuration */
-#define MATRIX_COL_PORTS PB, PB, PB, PB, PB, PB, PB, PB, PB, PB, PA, PA, PA, PA, PA
-#define MATRIX_COL_PINS 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 5, 6, 7, 10, 11
-
/* This Shift Register expands available hardware output lines to control additional peripherals */
/* It uses four lines from the MCU to provide 16 output lines */
/* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */
diff --git a/keyboards/massdrop/alt/matrix.c b/keyboards/massdrop/alt/matrix.c
deleted file mode 100644
index 181f223e4..000000000
--- a/keyboards/massdrop/alt/matrix.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Copyright 2018 Massdrop Inc.
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-#include "alt.h"
-#include "d51_util.h"
-
-const uint8_t row_ports[] = {MATRIX_ROW_PORTS};
-const uint8_t row_pins[] = {MATRIX_ROW_PINS};
-const uint8_t col_ports[] = {MATRIX_COL_PORTS};
-const uint8_t col_pins[] = {MATRIX_COL_PINS};
-uint32_t row_masks[2]; // NOTE: If more than PA PB used in the future, adjust code to accommodate
-
-void matrix_init_custom(void) {
- row_masks[PA] = 0;
- row_masks[PB] = 0;
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- PORT->Group[row_ports[row]].DIRCLR.reg = 1 << row_pins[row]; // Input
- PORT->Group[row_ports[row]].OUTCLR.reg = 1 << row_pins[row]; // Low
- PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.INEN = 1; // Input Enable,
- PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.PULLEN = 1; // Pull Enable
- row_masks[row_ports[row]] |= 1 << row_pins[row]; // Add pin to proper row mask
- }
-
- for (uint8_t col = 0; col < MATRIX_COLS; col++) {
- PORT->Group[col_ports[col]].DIRSET.reg = 1 << col_pins[col]; // Output
- PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; // Low
- }
-}
-
-bool matrix_scan_custom(matrix_row_t current_matrix[]) {
- matrix_row_t raw[MATRIX_ROWS] = {0};
- uint32_t scans[2]; // PA PB
-
- for (uint8_t col = 0; col < MATRIX_COLS; col++) {
- PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; // Set col output
-
- matrix_io_delay(); // Delay for output
-
- scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; // Read PA row pins data
- scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; // Read PB row pins data
-
- PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; // Clear col output
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- // Move scan bits from scans array into proper row bit locations
- if (scans[row_ports[row]] & (1 << row_pins[row])) {
- raw[row] |= 1 << col;
- }
- }
- }
-
- bool changed = false;
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- if (current_matrix[row] != raw[row]) {
- current_matrix[row] = raw[row];
- changed = true;
- }
- }
-
- return changed;
-}
diff --git a/keyboards/massdrop/alt/rules.mk b/keyboards/massdrop/alt/rules.mk
index 86403d830..3921d57ab 100644
--- a/keyboards/massdrop/alt/rules.mk
+++ b/keyboards/massdrop/alt/rules.mk
@@ -1,13 +1,10 @@
# project specific files
-SRC = matrix.c
SRC += config_led.c
#For platform and packs
ARM_ATSAM = SAMD51J18A
MCU = cortex-m4
-CUSTOM_MATRIX = lite
-
# Build Options
# comment out to disable the options.
#
diff --git a/keyboards/massdrop/ctrl/config.h b/keyboards/massdrop/ctrl/config.h
index 215a2e1b1..3dbd9b887 100644
--- a/keyboards/massdrop/ctrl/config.h
+++ b/keyboards/massdrop/ctrl/config.h
@@ -32,18 +32,20 @@ along with this program. If not, see .
#define MATRIX_ROWS 11
#define MATRIX_COLS 8
+#define MATRIX_ROW_PINS { B04, B05, B06, B07, B08, B09, A10, A11, B10, B11, B12 }
+#define MATRIX_COL_PINS { A00, A01, A02, A03, A04, A05, A06, A07 }
+#define UNUSED_PINS
+
+/* COL2ROW, ROW2COL */
+#define DIODE_DIRECTION COL2ROW
+
+/* Temporary solution for matrix delay */
+#define IGNORE_ATOMIC_BLOCK
+
/* MCU Port name definitions */
#define PA 0
#define PB 1
-/* Port and Pin definition of key row hardware configuration */
-#define MATRIX_ROW_PORTS PB, PB, PB, PB, PB, PB, PA, PA, PB, PB, PB
-#define MATRIX_ROW_PINS 4, 5, 6, 7, 8, 9, 10, 11, 10, 11, 12
-
-/* Port and Pin definition of key column hardware configuration */
-#define MATRIX_COL_PORTS PA, PA, PA, PA, PA, PA, PA, PA
-#define MATRIX_COL_PINS 0, 1, 2, 3, 4, 5, 6, 7
-
/* This Shift Register expands available hardware output lines to control additional peripherals */
/* It uses four lines from the MCU to provide 16 output lines */
/* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */
diff --git a/keyboards/massdrop/ctrl/ctrl.c b/keyboards/massdrop/ctrl/ctrl.c
new file mode 100644
index 000000000..b50f1cb59
--- /dev/null
+++ b/keyboards/massdrop/ctrl/ctrl.c
@@ -0,0 +1,21 @@
+/*
+Copyright 2021 Massdrop Inc.
+
+This program 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 2 of the License, or
+(at your option) any later version.
+
+This program 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.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see .
+*/
+#include "ctrl.h"
+
+/* Temporary solution for matrix delay */
+void matrix_output_select_delay(void) { matrix_io_delay(); }
+void matrix_output_unselect_delay(void) { }
diff --git a/keyboards/massdrop/ctrl/matrix.c b/keyboards/massdrop/ctrl/matrix.c
deleted file mode 100644
index a542d18c2..000000000
--- a/keyboards/massdrop/ctrl/matrix.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
-Copyright 2018 Massdrop Inc.
-
-This program 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 2 of the License, or
-(at your option) any later version.
-
-This program 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.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-*/
-
-#include "ctrl.h"
-#include "d51_util.h"
-
-const uint8_t row_ports[] = {MATRIX_ROW_PORTS};
-const uint8_t row_pins[] = {MATRIX_ROW_PINS};
-const uint8_t col_ports[] = {MATRIX_COL_PORTS};
-const uint8_t col_pins[] = {MATRIX_COL_PINS};
-uint32_t row_masks[2]; // NOTE: If more than PA PB used in the future, adjust code to accommodate
-
-void matrix_init_custom(void) {
- row_masks[PA] = 0;
- row_masks[PB] = 0;
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- PORT->Group[row_ports[row]].DIRCLR.reg = 1 << row_pins[row]; // Input
- PORT->Group[row_ports[row]].OUTCLR.reg = 1 << row_pins[row]; // Low
- PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.INEN = 1; // Input Enable,
- PORT->Group[row_ports[row]].PINCFG[row_pins[row]].bit.PULLEN = 1; // Pull Enable
- row_masks[row_ports[row]] |= 1 << row_pins[row]; // Add pin to proper row mask
- }
-
- for (uint8_t col = 0; col < MATRIX_COLS; col++) {
- PORT->Group[col_ports[col]].DIRSET.reg = 1 << col_pins[col]; // Output
- PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; // Low
- }
-}
-
-bool matrix_scan_custom(matrix_row_t current_matrix[]) {
- matrix_row_t raw[MATRIX_ROWS] = {0};
- uint32_t scans[2]; // PA PB
-
- for (uint8_t col = 0; col < MATRIX_COLS; col++) {
- PORT->Group[col_ports[col]].OUTSET.reg = 1 << col_pins[col]; // Set col output
-
- matrix_io_delay(); // Delay for output
-
- scans[PA] = PORT->Group[PA].IN.reg & row_masks[PA]; // Read PA row pins data
- scans[PB] = PORT->Group[PB].IN.reg & row_masks[PB]; // Read PB row pins data
-
- PORT->Group[col_ports[col]].OUTCLR.reg = 1 << col_pins[col]; // Clear col output
-
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- // Move scan bits from scans array into proper row bit locations
- if (scans[row_ports[row]] & (1 << row_pins[row])) {
- raw[row] |= 1 << col;
- }
- }
- }
-
- bool changed = false;
- for (uint8_t row = 0; row < MATRIX_ROWS; row++) {
- if (current_matrix[row] != raw[row]) {
- current_matrix[row] = raw[row];
- changed = true;
- }
- }
-
- return changed;
-}
diff --git a/keyboards/massdrop/ctrl/rules.mk b/keyboards/massdrop/ctrl/rules.mk
index f58042b75..ad79bbf91 100644
--- a/keyboards/massdrop/ctrl/rules.mk
+++ b/keyboards/massdrop/ctrl/rules.mk
@@ -1,13 +1,10 @@
# project specific files
-SRC = matrix.c
SRC += config_led.c
#For platform and packs
ARM_ATSAM = SAMD51J18A
MCU = cortex-m4
-CUSTOM_MATRIX = lite
-
# Build Options
# comment out to disable the options.
#
diff --git a/tmk_core/common/arm_atsam/atomic_util.h b/tmk_core/common/arm_atsam/atomic_util.h
new file mode 100644
index 000000000..848542d23
--- /dev/null
+++ b/tmk_core/common/arm_atsam/atomic_util.h
@@ -0,0 +1,37 @@
+/* Copyright 2021 QMK
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "samd51j18a.h"
+
+static __inline__ uint8_t __interrupt_disable__(void) {
+ __disable_irq();
+
+ return 1;
+}
+
+static __inline__ void __interrupt_enable__(const uint8_t *__s) {
+ __enable_irq();
+
+ __asm__ volatile("" ::: "memory");
+ (void)__s;
+}
+
+#define ATOMIC_BLOCK(type) for (type, __ToDo = __interrupt_disable__(); __ToDo; __ToDo = 0)
+#define ATOMIC_FORCEON uint8_t sreg_save __attribute__((__cleanup__(__interrupt_enable__))) = 0
+
+#define ATOMIC_BLOCK_RESTORESTATE _Static_assert(0, "ATOMIC_BLOCK_RESTORESTATE not implemented")
+#define ATOMIC_BLOCK_FORCEON ATOMIC_BLOCK(ATOMIC_FORCEON)
diff --git a/tmk_core/common/arm_atsam/gpio.h b/tmk_core/common/arm_atsam/gpio.h
new file mode 100644
index 000000000..c2d5a3088
--- /dev/null
+++ b/tmk_core/common/arm_atsam/gpio.h
@@ -0,0 +1,71 @@
+/* Copyright 2021 QMK
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "stdint.h"
+#include "samd51j18a.h"
+
+#include "pin_defs.h"
+
+typedef uint8_t pin_t;
+
+#define SAMD_PORT(pin) ((pin & 0x20) >> 5)
+#define SAMD_PIN(pin) (pin & 0x1f)
+#define SAMD_PIN_MASK(pin) (1 << (pin & 0x1f))
+
+#define setPinInput(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \
+ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
+ } while (0)
+
+#define setPinInputHigh(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
+ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
+ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \
+ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
+ } while (0)
+
+#define setPinInputLow(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].DIRCLR.reg = SAMD_PIN_MASK(pin); \
+ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
+ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.INEN = 1; \
+ PORT->Group[SAMD_PORT(pin)].PINCFG[SAMD_PIN(pin)].bit.PULLEN = 1; \
+ } while (0)
+
+#define setPinOutput(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].DIRSET.reg = SAMD_PIN_MASK(pin); \
+ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
+ } while (0)
+
+#define writePinHigh(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \
+ } while (0)
+
+#define writePinLow(pin) \
+ do { \
+ PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \
+ } while (0)
+
+#define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin)))
+
+#define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0)
+
+#define togglePin(pin) (PORT->Group[SAMD_PORT(pin)].OUTTGL.reg = SAMD_PIN_MASK(pin))
diff --git a/tmk_core/common/arm_atsam/pin_defs.h b/tmk_core/common/arm_atsam/pin_defs.h
new file mode 100644
index 000000000..5b50b2391
--- /dev/null
+++ b/tmk_core/common/arm_atsam/pin_defs.h
@@ -0,0 +1,84 @@
+/* Copyright 2021 QMK
+ *
+ * This program 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.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+#pragma once
+
+#include "samd51j18a.h"
+
+#define A00 PIN_PA00
+#define A01 PIN_PA01
+#define A02 PIN_PA02
+#define A03 PIN_PA03
+#define A04 PIN_PA04
+#define A05 PIN_PA05
+#define A06 PIN_PA06
+#define A07 PIN_PA07
+#define A08 PIN_PA08
+#define A09 PIN_PA09
+#define A10 PIN_PA10
+#define A11 PIN_PA11
+#define A12 PIN_PA12
+#define A13 PIN_PA13
+#define A14 PIN_PA14
+#define A15 PIN_PA15
+#define A16 PIN_PA16
+#define A17 PIN_PA17
+#define A18 PIN_PA18
+#define A19 PIN_PA19
+#define A20 PIN_PA20
+#define A21 PIN_PA21
+#define A22 PIN_PA22
+#define A23 PIN_PA23
+#define A24 PIN_PA24
+#define A25 PIN_PA25
+#define A26 PIN_PA26
+#define A27 PIN_PA27
+#define A28 PIN_PA28
+#define A29 PIN_PA29
+#define A30 PIN_PA30
+#define A31 PIN_PA31
+
+#define B00 PIN_PB00
+#define B01 PIN_PB01
+#define B02 PIN_PB02
+#define B03 PIN_PB03
+#define B04 PIN_PB04
+#define B05 PIN_PB05
+#define B06 PIN_PB06
+#define B07 PIN_PB07
+#define B08 PIN_PB08
+#define B09 PIN_PB09
+#define B10 PIN_PB10
+#define B11 PIN_PB11
+#define B12 PIN_PB12
+#define B13 PIN_PB13
+#define B14 PIN_PB14
+#define B15 PIN_PB15
+#define B16 PIN_PB16
+#define B17 PIN_PB17
+#define B18 PIN_PB18
+#define B19 PIN_PB19
+#define B20 PIN_PB20
+#define B21 PIN_PB21
+#define B22 PIN_PB22
+#define B23 PIN_PB23
+#define B24 PIN_PB24
+#define B25 PIN_PB25
+#define B26 PIN_PB26
+#define B27 PIN_PB27
+#define B28 PIN_PB28
+#define B29 PIN_PB29
+#define B30 PIN_PB30
+#define B31 PIN_PB31