Browse Source

Implement GPIO abstraction for atsam (#13567)

* Implement GPIO abstraction for atsam

* Convert Drop boards to normal matrix config

* Work round pin conflicts and matrix delay
Joel Challis 3 years ago
parent
commit
5d7f2823c9

+ 21 - 0
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 <http://www.gnu.org/licenses/>.
+*/
+#include "alt.h"
+
+/* Temporary solution for matrix delay */
+void matrix_output_select_delay(void) { matrix_io_delay(); }
+void matrix_output_unselect_delay(void) { }

+ 11 - 8
keyboards/massdrop/alt/config.h

@@ -32,18 +32,21 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #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) */

+ 0 - 76
keyboards/massdrop/alt/matrix.c

@@ -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 <http://www.gnu.org/licenses/>.
-*/
-
-#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;
-}

+ 0 - 3
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.
 #

+ 10 - 8
keyboards/massdrop/ctrl/config.h

@@ -32,18 +32,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #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) */

+ 21 - 0
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 <http://www.gnu.org/licenses/>.
+*/
+#include "ctrl.h"
+
+/* Temporary solution for matrix delay */
+void matrix_output_select_delay(void) { matrix_io_delay(); }
+void matrix_output_unselect_delay(void) { }

+ 0 - 76
keyboards/massdrop/ctrl/matrix.c

@@ -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 <http://www.gnu.org/licenses/>.
-*/
-
-#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;
-}

+ 0 - 3
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.
 #

+ 37 - 0
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 <http://www.gnu.org/licenses/>.
+ */
+#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)

+ 71 - 0
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 <http://www.gnu.org/licenses/>.
+ */
+#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))

+ 84 - 0
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 <http://www.gnu.org/licenses/>.
+ */
+#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