diff options
| -rw-r--r-- | keyboards/massdrop/alt/config.h | 18 | ||||
| -rw-r--r-- | keyboards/massdrop/ctrl/config.h | 18 | ||||
| -rw-r--r-- | tmk_core/common/arm_atsam/gpio.h | 8 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam.mk | 3 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/arm_atsam_protocol.h | 2 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/shift_register.c | 118 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/shift_register.h (renamed from tmk_core/protocol/arm_atsam/spi.h) | 25 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/spi.c | 92 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/spi_master.c | 109 | ||||
| -rw-r--r-- | tmk_core/protocol/arm_atsam/spi_master.h | 48 |
10 files changed, 301 insertions, 140 deletions
diff --git a/keyboards/massdrop/alt/config.h b/keyboards/massdrop/alt/config.h index d28094c49..085e1aebb 100644 --- a/keyboards/massdrop/alt/config.h +++ b/keyboards/massdrop/alt/config.h | |||
| @@ -50,22 +50,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 50 | /* This Shift Register expands available hardware output lines to control additional peripherals */ | 50 | /* This Shift Register expands available hardware output lines to control additional peripherals */ |
| 51 | /* It uses four lines from the MCU to provide 16 output lines */ | 51 | /* It uses four lines from the MCU to provide 16 output lines */ |
| 52 | /* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */ | 52 | /* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */ |
| 53 | #define SR_EXP_RCLK_PORT PB | 53 | #define SR_EXP_RCLK_PIN B14 |
| 54 | #define SR_EXP_RCLK_PIN 14 | ||
| 55 | /* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */ | 54 | /* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */ |
| 56 | #define SR_EXP_OE_N_PORT PB | 55 | #define SR_EXP_OE_PIN B15 |
| 57 | #define SR_EXP_OE_N_PIN 15 | ||
| 58 | /* SERCOM port to use for Shift Register SPI */ | 56 | /* SERCOM port to use for Shift Register SPI */ |
| 59 | /* DATAOUT and SCLK must be configured to use hardware pins of this port */ | 57 | /* DATAOUT and SCLK must be configured to use hardware pins of this port */ |
| 60 | #define SR_EXP_SERCOM SERCOM2 | 58 | #define SPI_SERCOM SERCOM2 |
| 61 | /* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */ | 59 | /* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */ |
| 62 | #define SR_EXP_DATAOUT_PORT PA | 60 | #define SPI_DATAOUT_PIN A12 |
| 63 | #define SR_EXP_DATAOUT_PIN 12 | 61 | #define SPI_DATAOUT_MUX 2 |
| 64 | #define SR_EXP_DATAOUT_MUX 2 | ||
| 65 | /* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */ | 62 | /* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */ |
| 66 | #define SR_EXP_SCLK_PORT PA | 63 | #define SPI_SCLK_PIN A13 |
| 67 | #define SR_EXP_SCLK_PIN 13 | 64 | #define SPI_SCLK_MUX 2 |
| 68 | #define SR_EXP_SCLK_MUX 2 | ||
| 69 | 65 | ||
| 70 | /* Debug LED (Small LED Located near MCU) */ | 66 | /* Debug LED (Small LED Located near MCU) */ |
| 71 | #define DEBUG_LED_ENABLE 1 | 67 | #define DEBUG_LED_ENABLE 1 |
diff --git a/keyboards/massdrop/ctrl/config.h b/keyboards/massdrop/ctrl/config.h index 3dbd9b887..aefb90044 100644 --- a/keyboards/massdrop/ctrl/config.h +++ b/keyboards/massdrop/ctrl/config.h | |||
| @@ -49,22 +49,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 49 | /* This Shift Register expands available hardware output lines to control additional peripherals */ | 49 | /* This Shift Register expands available hardware output lines to control additional peripherals */ |
| 50 | /* It uses four lines from the MCU to provide 16 output lines */ | 50 | /* It uses four lines from the MCU to provide 16 output lines */ |
| 51 | /* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */ | 51 | /* Shift Register Clock configuration (MCU to ShiftRegister.RCLK) */ |
| 52 | #define SR_EXP_RCLK_PORT PB | 52 | #define SR_EXP_RCLK_PIN B14 |
| 53 | #define SR_EXP_RCLK_PIN 14 | ||
| 54 | /* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */ | 53 | /* Shift Register Output Enable configuration (MCU to ShiftRegister.OE_N) */ |
| 55 | #define SR_EXP_OE_N_PORT PB | 54 | #define SR_EXP_OE_PIN B15 |
| 56 | #define SR_EXP_OE_N_PIN 15 | ||
| 57 | /* SERCOM port to use for Shift Register SPI */ | 55 | /* SERCOM port to use for Shift Register SPI */ |
| 58 | /* DATAOUT and SCLK must be configured to use hardware pins of this port */ | 56 | /* DATAOUT and SCLK must be configured to use hardware pins of this port */ |
| 59 | #define SR_EXP_SERCOM SERCOM2 | 57 | #define SPI_SERCOM SERCOM2 |
| 60 | /* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */ | 58 | /* Shift Register SPI Data Out configuration (MCU.SERCOMx.PAD[0] to ShiftRegister.SER) */ |
| 61 | #define SR_EXP_DATAOUT_PORT PA | 59 | #define SPI_DATAOUT_PIN A12 |
| 62 | #define SR_EXP_DATAOUT_PIN 12 | 60 | #define SPI_DATAOUT_MUX 2 |
| 63 | #define SR_EXP_DATAOUT_MUX 2 | ||
| 64 | /* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */ | 61 | /* Shift Register SPI Serial Clock configuration (MCU.SERCOMx.PAD[1] to ShiftRegister.SRCLK) */ |
| 65 | #define SR_EXP_SCLK_PORT PA | 62 | #define SPI_SCLK_PIN A13 |
| 66 | #define SR_EXP_SCLK_PIN 13 | 63 | #define SPI_SCLK_MUX 2 |
| 67 | #define SR_EXP_SCLK_MUX 2 | ||
| 68 | 64 | ||
| 69 | /* Debug LED (Small LED Located near MCU) */ | 65 | /* Debug LED (Small LED Located near MCU) */ |
| 70 | #define DEBUG_LED_ENABLE 1 | 66 | #define DEBUG_LED_ENABLE 1 |
diff --git a/tmk_core/common/arm_atsam/gpio.h b/tmk_core/common/arm_atsam/gpio.h index c2d5a3088..915ed0ef4 100644 --- a/tmk_core/common/arm_atsam/gpio.h +++ b/tmk_core/common/arm_atsam/gpio.h | |||
| @@ -64,7 +64,13 @@ typedef uint8_t pin_t; | |||
| 64 | PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ | 64 | PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ |
| 65 | } while (0) | 65 | } while (0) |
| 66 | 66 | ||
| 67 | #define writePin(pin, level) ((level) ? (writePinHigh(pin)) : (writePinLow(pin))) | 67 | #define writePin(pin, level) \ |
| 68 | do { \ | ||
| 69 | if (level) \ | ||
| 70 | PORT->Group[SAMD_PORT(pin)].OUTSET.reg = SAMD_PIN_MASK(pin); \ | ||
| 71 | else \ | ||
| 72 | PORT->Group[SAMD_PORT(pin)].OUTCLR.reg = SAMD_PIN_MASK(pin); \ | ||
| 73 | } while (0) | ||
| 68 | 74 | ||
| 69 | #define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) | 75 | #define readPin(pin) ((PORT->Group[SAMD_PORT(pin)].IN.reg & SAMD_PIN_MASK(pin)) != 0) |
| 70 | 76 | ||
diff --git a/tmk_core/protocol/arm_atsam.mk b/tmk_core/protocol/arm_atsam.mk index 5bb45d658..e3b550596 100644 --- a/tmk_core/protocol/arm_atsam.mk +++ b/tmk_core/protocol/arm_atsam.mk | |||
| @@ -9,7 +9,8 @@ ifeq ($(RGB_MATRIX_DRIVER),custom) | |||
| 9 | SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c | 9 | SRC += $(ARM_ATSAM_DIR)/md_rgb_matrix.c |
| 10 | endif | 10 | endif |
| 11 | SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c | 11 | SRC += $(ARM_ATSAM_DIR)/main_arm_atsam.c |
| 12 | SRC += $(ARM_ATSAM_DIR)/spi.c | 12 | SRC += $(ARM_ATSAM_DIR)/shift_register.c |
| 13 | SRC += $(ARM_ATSAM_DIR)/spi_master.c | ||
| 13 | SRC += $(ARM_ATSAM_DIR)/startup.c | 14 | SRC += $(ARM_ATSAM_DIR)/startup.c |
| 14 | 15 | ||
| 15 | SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c | 16 | SRC += $(ARM_ATSAM_DIR)/usb/main_usb.c |
diff --git a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h index d126c66e7..c3eab39fb 100644 --- a/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h +++ b/tmk_core/protocol/arm_atsam/arm_atsam_protocol.h | |||
| @@ -27,7 +27,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
| 27 | #include "wait.h" | 27 | #include "wait.h" |
| 28 | #include "adc.h" | 28 | #include "adc.h" |
| 29 | #include "i2c_master.h" | 29 | #include "i2c_master.h" |
| 30 | #include "spi.h" | 30 | #include "shift_register.h" |
| 31 | 31 | ||
| 32 | #include "./usb/usb2422.h" | 32 | #include "./usb/usb2422.h" |
| 33 | 33 | ||
diff --git a/tmk_core/protocol/arm_atsam/shift_register.c b/tmk_core/protocol/arm_atsam/shift_register.c new file mode 100644 index 000000000..8d63af1b5 --- /dev/null +++ b/tmk_core/protocol/arm_atsam/shift_register.c | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Massdrop Inc. | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "arm_atsam_protocol.h" | ||
| 19 | |||
| 20 | #include "spi_master.h" | ||
| 21 | #include "wait.h" | ||
| 22 | #include "gpio.h" | ||
| 23 | |||
| 24 | // #define SR_USE_BITBANG | ||
| 25 | |||
| 26 | // Bodge for when spi_master is not available | ||
| 27 | #ifdef SR_USE_BITBANG | ||
| 28 | # define CLOCK_DELAY 10 | ||
| 29 | |||
| 30 | void shift_init_impl(void) { | ||
| 31 | setPinOutput(SR_EXP_RCLK_PIN); | ||
| 32 | setPinOutput(SPI_DATAOUT_PIN); | ||
| 33 | setPinOutput(SPI_SCLK_PIN); | ||
| 34 | } | ||
| 35 | |||
| 36 | void shift_out_impl(const uint8_t *data, uint16_t length) { | ||
| 37 | writePinLow(SR_EXP_RCLK_PIN); | ||
| 38 | for (uint16_t i = 0; i < length; i++) { | ||
| 39 | uint8_t val = data[i]; | ||
| 40 | |||
| 41 | // shift out lsb first | ||
| 42 | for (uint8_t bit = 0; bit < 8; bit++) { | ||
| 43 | writePin(SPI_DATAOUT_PIN, !!(val & (1 << bit))); | ||
| 44 | writePin(SPI_SCLK_PIN, true); | ||
| 45 | wait_us(CLOCK_DELAY); | ||
| 46 | |||
| 47 | writePin(SPI_SCLK_PIN, false); | ||
| 48 | wait_us(CLOCK_DELAY); | ||
| 49 | } | ||
| 50 | } | ||
| 51 | writePinHigh(SR_EXP_RCLK_PIN); | ||
| 52 | return SPI_STATUS_SUCCESS; | ||
| 53 | } | ||
| 54 | |||
| 55 | #else | ||
| 56 | |||
| 57 | void shift_init_impl(void) { spi_init(); } | ||
| 58 | |||
| 59 | void shift_out_impl(const uint8_t *data, uint16_t length) { | ||
| 60 | spi_start(SR_EXP_RCLK_PIN, true, 0, 0); | ||
| 61 | |||
| 62 | spi_transmit(data, length); | ||
| 63 | |||
| 64 | spi_stop(); | ||
| 65 | } | ||
| 66 | #endif | ||
| 67 | |||
| 68 | // *************************************************************** | ||
| 69 | |||
| 70 | void shift_out(const uint8_t *data, uint16_t length) { shift_out_impl(data, length); } | ||
| 71 | |||
| 72 | void shift_enable(void) { | ||
| 73 | setPinOutput(SR_EXP_OE_PIN); | ||
| 74 | writePinLow(SR_EXP_OE_PIN); | ||
| 75 | } | ||
| 76 | |||
| 77 | void shift_disable(void) { | ||
| 78 | setPinOutput(SR_EXP_OE_PIN); | ||
| 79 | writePinHigh(SR_EXP_OE_PIN); | ||
| 80 | } | ||
| 81 | |||
| 82 | void shift_init(void) { | ||
| 83 | shift_disable(); | ||
| 84 | shift_init_impl(); | ||
| 85 | } | ||
| 86 | |||
| 87 | // *************************************************************** | ||
| 88 | |||
| 89 | sr_exp_t sr_exp_data; | ||
| 90 | |||
| 91 | void SR_EXP_WriteData(void) { | ||
| 92 | uint8_t data[2] = { | ||
| 93 | sr_exp_data.reg & 0xFF, // Shift in bits 7-0 | ||
| 94 | (sr_exp_data.reg >> 8) & 0xFF, // Shift in bits 15-8 | ||
| 95 | }; | ||
| 96 | shift_out(data, 2); | ||
| 97 | } | ||
| 98 | |||
| 99 | void SR_EXP_Init(void) { | ||
| 100 | shift_init(); | ||
| 101 | |||
| 102 | sr_exp_data.reg = 0; | ||
| 103 | sr_exp_data.bit.HUB_CONNECT = 0; | ||
| 104 | sr_exp_data.bit.HUB_RESET_N = 0; | ||
| 105 | sr_exp_data.bit.S_UP = 0; | ||
| 106 | sr_exp_data.bit.E_UP_N = 1; | ||
| 107 | sr_exp_data.bit.S_DN1 = 1; | ||
| 108 | sr_exp_data.bit.E_DN1_N = 1; | ||
| 109 | sr_exp_data.bit.E_VBUS_1 = 0; | ||
| 110 | sr_exp_data.bit.E_VBUS_2 = 0; | ||
| 111 | sr_exp_data.bit.SRC_1 = 1; | ||
| 112 | sr_exp_data.bit.SRC_2 = 1; | ||
| 113 | sr_exp_data.bit.IRST = 1; | ||
| 114 | sr_exp_data.bit.SDB_N = 0; | ||
| 115 | SR_EXP_WriteData(); | ||
| 116 | |||
| 117 | shift_enable(); | ||
| 118 | } | ||
diff --git a/tmk_core/protocol/arm_atsam/spi.h b/tmk_core/protocol/arm_atsam/shift_register.h index dcd45f31a..56a8c7f71 100644 --- a/tmk_core/protocol/arm_atsam/spi.h +++ b/tmk_core/protocol/arm_atsam/shift_register.h | |||
| @@ -15,28 +15,9 @@ You should have received a copy of the GNU General Public License | |||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #ifndef _SPI_H_ | 18 | #pragma once |
| 19 | #define _SPI_H_ | ||
| 20 | 19 | ||
| 21 | /* Macros for Shift Register control */ | 20 | #include <stdint.h> |
| 22 | #define SR_EXP_RCLK_LO PORT->Group[SR_EXP_RCLK_PORT].OUTCLR.reg = (1 << SR_EXP_RCLK_PIN) | ||
| 23 | #define SR_EXP_RCLK_HI PORT->Group[SR_EXP_RCLK_PORT].OUTSET.reg = (1 << SR_EXP_RCLK_PIN) | ||
| 24 | #define SR_EXP_OE_N_ENA PORT->Group[SR_EXP_OE_N_PORT].OUTCLR.reg = (1 << SR_EXP_OE_N_PIN) | ||
| 25 | #define SR_EXP_OE_N_DIS PORT->Group[SR_EXP_OE_N_PORT].OUTSET.reg = (1 << SR_EXP_OE_N_PIN) | ||
| 26 | |||
| 27 | /* Determine bits to set for mux selection */ | ||
| 28 | #if SR_EXP_DATAOUT_PIN % 2 == 0 | ||
| 29 | # define SR_EXP_DATAOUT_MUX_SEL PMUXE | ||
| 30 | #else | ||
| 31 | # define SR_EXP_DATAOUT_MUX_SEL PMUXO | ||
| 32 | #endif | ||
| 33 | |||
| 34 | /* Determine bits to set for mux selection */ | ||
| 35 | #if SR_EXP_SCLK_PIN % 2 == 0 | ||
| 36 | # define SR_EXP_SCLK_MUX_SEL PMUXE | ||
| 37 | #else | ||
| 38 | # define SR_EXP_SCLK_MUX_SEL PMUXO | ||
| 39 | #endif | ||
| 40 | 21 | ||
| 41 | /* Data structure to define Shift Register output expander hardware */ | 22 | /* Data structure to define Shift Register output expander hardware */ |
| 42 | /* This structure gets shifted into registers LSB first */ | 23 | /* This structure gets shifted into registers LSB first */ |
| @@ -66,5 +47,3 @@ extern sr_exp_t sr_exp_data; | |||
| 66 | 47 | ||
| 67 | void SR_EXP_WriteData(void); | 48 | void SR_EXP_WriteData(void); |
| 68 | void SR_EXP_Init(void); | 49 | void SR_EXP_Init(void); |
| 69 | |||
| 70 | #endif //_SPI_H_ | ||
diff --git a/tmk_core/protocol/arm_atsam/spi.c b/tmk_core/protocol/arm_atsam/spi.c deleted file mode 100644 index 3b118bc1f..000000000 --- a/tmk_core/protocol/arm_atsam/spi.c +++ /dev/null | |||
| @@ -1,92 +0,0 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Massdrop Inc. | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "arm_atsam_protocol.h" | ||
| 19 | |||
| 20 | sr_exp_t sr_exp_data; | ||
| 21 | |||
| 22 | void SR_EXP_WriteData(void) { | ||
| 23 | SR_EXP_RCLK_LO; | ||
| 24 | |||
| 25 | while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.DRE)) { | ||
| 26 | DBGC(DC_SPI_WRITE_DRE); | ||
| 27 | } | ||
| 28 | |||
| 29 | SR_EXP_SERCOM->SPI.DATA.bit.DATA = sr_exp_data.reg & 0xFF; // Shift in bits 7-0 | ||
| 30 | while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { | ||
| 31 | DBGC(DC_SPI_WRITE_TXC_1); | ||
| 32 | } | ||
| 33 | |||
| 34 | SR_EXP_SERCOM->SPI.DATA.bit.DATA = (sr_exp_data.reg >> 8) & 0xFF; // Shift in bits 15-8 | ||
| 35 | while (!(SR_EXP_SERCOM->SPI.INTFLAG.bit.TXC)) { | ||
| 36 | DBGC(DC_SPI_WRITE_TXC_2); | ||
| 37 | } | ||
| 38 | |||
| 39 | SR_EXP_RCLK_HI; | ||
| 40 | } | ||
| 41 | |||
| 42 | void SR_EXP_Init(void) { | ||
| 43 | DBGC(DC_SPI_INIT_BEGIN); | ||
| 44 | |||
| 45 | CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT); | ||
| 46 | |||
| 47 | // Set up MCU Shift Register pins | ||
| 48 | PORT->Group[SR_EXP_RCLK_PORT].DIRSET.reg = (1 << SR_EXP_RCLK_PIN); | ||
| 49 | PORT->Group[SR_EXP_OE_N_PORT].DIRSET.reg = (1 << SR_EXP_OE_N_PIN); | ||
| 50 | |||
| 51 | // Set up MCU SPI pins | ||
| 52 | PORT->Group[SR_EXP_DATAOUT_PORT].PMUX[SR_EXP_DATAOUT_PIN / 2].bit.SR_EXP_DATAOUT_MUX_SEL = SR_EXP_DATAOUT_MUX; // MUX select for sercom | ||
| 53 | PORT->Group[SR_EXP_SCLK_PORT].PMUX[SR_EXP_SCLK_PIN / 2].bit.SR_EXP_SCLK_MUX_SEL = SR_EXP_SCLK_MUX; // MUX select for sercom | ||
| 54 | PORT->Group[SR_EXP_DATAOUT_PORT].PINCFG[SR_EXP_DATAOUT_PIN].bit.PMUXEN = 1; // MUX Enable | ||
| 55 | PORT->Group[SR_EXP_SCLK_PORT].PINCFG[SR_EXP_SCLK_PIN].bit.PMUXEN = 1; // MUX Enable | ||
| 56 | |||
| 57 | // Initialize Shift Register | ||
| 58 | SR_EXP_OE_N_DIS; | ||
| 59 | SR_EXP_RCLK_HI; | ||
| 60 | |||
| 61 | SR_EXP_SERCOM->SPI.CTRLA.bit.DORD = 1; // Data Order - LSB is transferred first | ||
| 62 | SR_EXP_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising. | ||
| 63 | SR_EXP_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample | ||
| 64 | SR_EXP_SERCOM->SPI.CTRLA.bit.DIPO = 3; // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.) | ||
| 65 | SR_EXP_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1] | ||
| 66 | SR_EXP_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation | ||
| 67 | |||
| 68 | SR_EXP_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled | ||
| 69 | while (SR_EXP_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { | ||
| 70 | DBGC(DC_SPI_SYNC_ENABLING); | ||
| 71 | } | ||
| 72 | |||
| 73 | sr_exp_data.reg = 0; | ||
| 74 | sr_exp_data.bit.HUB_CONNECT = 0; | ||
| 75 | sr_exp_data.bit.HUB_RESET_N = 0; | ||
| 76 | sr_exp_data.bit.S_UP = 0; | ||
| 77 | sr_exp_data.bit.E_UP_N = 1; | ||
| 78 | sr_exp_data.bit.S_DN1 = 1; | ||
| 79 | sr_exp_data.bit.E_DN1_N = 1; | ||
| 80 | sr_exp_data.bit.E_VBUS_1 = 0; | ||
| 81 | sr_exp_data.bit.E_VBUS_2 = 0; | ||
| 82 | sr_exp_data.bit.SRC_1 = 1; | ||
| 83 | sr_exp_data.bit.SRC_2 = 1; | ||
| 84 | sr_exp_data.bit.IRST = 1; | ||
| 85 | sr_exp_data.bit.SDB_N = 0; | ||
| 86 | SR_EXP_WriteData(); | ||
| 87 | |||
| 88 | // Enable Shift Register output | ||
| 89 | SR_EXP_OE_N_ENA; | ||
| 90 | |||
| 91 | DBGC(DC_SPI_INIT_COMPLETE); | ||
| 92 | } | ||
diff --git a/tmk_core/protocol/arm_atsam/spi_master.c b/tmk_core/protocol/arm_atsam/spi_master.c new file mode 100644 index 000000000..9781d45b1 --- /dev/null +++ b/tmk_core/protocol/arm_atsam/spi_master.c | |||
| @@ -0,0 +1,109 @@ | |||
| 1 | /* | ||
| 2 | Copyright 2018 Massdrop Inc. | ||
| 3 | |||
| 4 | This program is free software: you can redistribute it and/or modify | ||
| 5 | it under the terms of the GNU General Public License as published by | ||
| 6 | the Free Software Foundation, either version 2 of the License, or | ||
| 7 | (at your option) any later version. | ||
| 8 | |||
| 9 | This program is distributed in the hope that it will be useful, | ||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | GNU General Public License for more details. | ||
| 13 | |||
| 14 | You should have received a copy of the GNU General Public License | ||
| 15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "arm_atsam_protocol.h" | ||
| 19 | #include "spi_master.h" | ||
| 20 | #include "gpio.h" | ||
| 21 | |||
| 22 | /* Determine bits to set for mux selection */ | ||
| 23 | #if SPI_DATAOUT_PIN % 2 == 0 | ||
| 24 | # define SPI_DATAOUT_MUX_SEL PMUXE | ||
| 25 | #else | ||
| 26 | # define SPI_DATAOUT_MUX_SEL PMUXO | ||
| 27 | #endif | ||
| 28 | |||
| 29 | /* Determine bits to set for mux selection */ | ||
| 30 | #if SPI_SCLK_PIN % 2 == 0 | ||
| 31 | # define SPI_SCLK_MUX_SEL PMUXE | ||
| 32 | #else | ||
| 33 | # define SPI_SCLK_MUX_SEL PMUXO | ||
| 34 | #endif | ||
| 35 | |||
| 36 | static pin_t currentSelectPin = NO_PIN; | ||
| 37 | |||
| 38 | __attribute__((weak)) void spi_init(void) { | ||
| 39 | static bool is_initialised = false; | ||
| 40 | if (!is_initialised) { | ||
| 41 | is_initialised = true; | ||
| 42 | |||
| 43 | DBGC(DC_SPI_INIT_BEGIN); | ||
| 44 | |||
| 45 | CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT); | ||
| 46 | |||
| 47 | // Set up MCU SPI pins | ||
| 48 | PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PMUX[SAMD_PIN(SPI_DATAOUT_PIN) / 2].bit.SPI_DATAOUT_MUX_SEL = SPI_DATAOUT_MUX; // MUX select for sercom | ||
| 49 | PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PMUX[SAMD_PIN(SPI_SCLK_PIN) / 2].bit.SPI_SCLK_MUX_SEL = SPI_SCLK_MUX; // MUX select for sercom | ||
| 50 | PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PINCFG[SAMD_PIN(SPI_DATAOUT_PIN)].bit.PMUXEN = 1; // MUX Enable | ||
| 51 | PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PINCFG[SAMD_PIN(SPI_SCLK_PIN)].bit.PMUXEN = 1; // MUX Enable | ||
| 52 | |||
| 53 | DBGC(DC_SPI_INIT_COMPLETE); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | bool spi_start(pin_t csPin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | ||
| 58 | if (currentSelectPin != NO_PIN || csPin == NO_PIN) { | ||
| 59 | return false; | ||
| 60 | } | ||
| 61 | |||
| 62 | currentSelectPin = csPin; | ||
| 63 | setPinOutput(currentSelectPin); | ||
| 64 | writePinLow(currentSelectPin); | ||
| 65 | |||
| 66 | SPI_SERCOM->SPI.CTRLA.bit.DORD = lsbFirst; // Data Order - LSB is transferred first | ||
| 67 | SPI_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising. | ||
| 68 | SPI_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample | ||
| 69 | SPI_SERCOM->SPI.CTRLA.bit.DIPO = 3; // Data In Pinout - SERCOM PAD[3] is used as data input (Configure away from DOPO. Not using input.) | ||
| 70 | SPI_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1] | ||
| 71 | SPI_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation | ||
| 72 | |||
| 73 | SPI_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled | ||
| 74 | while (SPI_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { | ||
| 75 | DBGC(DC_SPI_SYNC_ENABLING); | ||
| 76 | } | ||
| 77 | return true; | ||
| 78 | } | ||
| 79 | |||
| 80 | spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { | ||
| 81 | while (!(SPI_SERCOM->SPI.INTFLAG.bit.DRE)) { | ||
| 82 | DBGC(DC_SPI_WRITE_DRE); | ||
| 83 | } | ||
| 84 | |||
| 85 | for (uint16_t i = 0; i < length; i++) { | ||
| 86 | SPI_SERCOM->SPI.DATA.bit.DATA = data[i]; | ||
| 87 | while (!(SPI_SERCOM->SPI.INTFLAG.bit.TXC)) { | ||
| 88 | DBGC(DC_SPI_WRITE_TXC_1); | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | return SPI_STATUS_SUCCESS; | ||
| 93 | } | ||
| 94 | |||
| 95 | void spi_stop(void) { | ||
| 96 | if (currentSelectPin != NO_PIN) { | ||
| 97 | setPinOutput(currentSelectPin); | ||
| 98 | writePinHigh(currentSelectPin); | ||
| 99 | currentSelectPin = NO_PIN; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | // Not implemented yet.... | ||
| 104 | |||
| 105 | spi_status_t spi_write(uint8_t data); | ||
| 106 | |||
| 107 | spi_status_t spi_read(void); | ||
| 108 | |||
| 109 | spi_status_t spi_receive(uint8_t *data, uint16_t length); | ||
diff --git a/tmk_core/protocol/arm_atsam/spi_master.h b/tmk_core/protocol/arm_atsam/spi_master.h new file mode 100644 index 000000000..26c55128b --- /dev/null +++ b/tmk_core/protocol/arm_atsam/spi_master.h | |||
| @@ -0,0 +1,48 @@ | |||
| 1 | /* Copyright 2021 QMK | ||
| 2 | * | ||
| 3 | * This program is free software: you can redistribute it and/or modify | ||
| 4 | * it under the terms of the GNU General Public License as published by | ||
| 5 | * the Free Software Foundation, either version 3 of the License, or | ||
| 6 | * (at your option) any later version. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * You should have received a copy of the GNU General Public License | ||
| 14 | * along with this program. If not, see <https://www.gnu.org/licenses/>. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #pragma once | ||
| 18 | |||
| 19 | #include <stdbool.h> | ||
| 20 | |||
| 21 | typedef int16_t spi_status_t; | ||
| 22 | |||
| 23 | #define SPI_STATUS_SUCCESS (0) | ||
| 24 | #define SPI_STATUS_ERROR (-1) | ||
| 25 | #define SPI_STATUS_TIMEOUT (-2) | ||
| 26 | |||
| 27 | #define SPI_TIMEOUT_IMMEDIATE (0) | ||
| 28 | #define SPI_TIMEOUT_INFINITE (0xFFFF) | ||
| 29 | |||
| 30 | #ifdef __cplusplus | ||
| 31 | extern "C" { | ||
| 32 | #endif | ||
| 33 | void spi_init(void); | ||
| 34 | |||
| 35 | bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); | ||
| 36 | |||
| 37 | spi_status_t spi_write(uint8_t data); | ||
| 38 | |||
| 39 | spi_status_t spi_read(void); | ||
| 40 | |||
| 41 | spi_status_t spi_transmit(const uint8_t *data, uint16_t length); | ||
| 42 | |||
| 43 | spi_status_t spi_receive(uint8_t *data, uint16_t length); | ||
| 44 | |||
| 45 | void spi_stop(void); | ||
| 46 | #ifdef __cplusplus | ||
| 47 | } | ||
| 48 | #endif | ||
