From 5d7f2823c947264d3ff3bb4f057f8e050d6b4af1 Mon Sep 17 00:00:00 2001 From: Joel Challis Date: Thu, 22 Jul 2021 23:01:19 +0100 Subject: [PATCH] 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 --- keyboards/massdrop/alt/alt.c | 21 +++++++ keyboards/massdrop/alt/config.h | 19 +++--- keyboards/massdrop/alt/matrix.c | 76 ---------------------- keyboards/massdrop/alt/rules.mk | 3 - keyboards/massdrop/ctrl/config.h | 18 +++--- keyboards/massdrop/ctrl/ctrl.c | 21 +++++++ keyboards/massdrop/ctrl/matrix.c | 76 ---------------------- keyboards/massdrop/ctrl/rules.mk | 3 - tmk_core/common/arm_atsam/atomic_util.h | 37 +++++++++++ tmk_core/common/arm_atsam/gpio.h | 71 +++++++++++++++++++++ tmk_core/common/arm_atsam/pin_defs.h | 84 +++++++++++++++++++++++++ 11 files changed, 255 insertions(+), 174 deletions(-) create mode 100644 keyboards/massdrop/alt/alt.c delete mode 100644 keyboards/massdrop/alt/matrix.c create mode 100644 keyboards/massdrop/ctrl/ctrl.c delete mode 100644 keyboards/massdrop/ctrl/matrix.c create mode 100644 tmk_core/common/arm_atsam/atomic_util.h create mode 100644 tmk_core/common/arm_atsam/gpio.h create mode 100644 tmk_core/common/arm_atsam/pin_defs.h 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