forked from qmk/qmk_firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Split out arm_atsam shift register logic (qmk#14848)
- Loading branch information
Showing
8 changed files
with
287 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
/* | ||
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 "arm_atsam_protocol.h" | ||
|
||
#include "spi_master.h" | ||
#include "wait.h" | ||
#include "gpio.h" | ||
|
||
// #define SR_USE_BITBANG | ||
|
||
// Bodge for when spi_master is not available | ||
#ifdef SR_USE_BITBANG | ||
# define CLOCK_DELAY 10 | ||
|
||
void shift_init_impl(void) { | ||
setPinOutput(SR_EXP_RCLK_PIN); | ||
setPinOutput(SPI_DATAOUT_PIN); | ||
setPinOutput(SPI_SCLK_PIN); | ||
} | ||
|
||
void shift_out_impl(const uint8_t *data, uint16_t length) { | ||
writePinLow(SR_EXP_RCLK_PIN); | ||
for (uint16_t i = 0; i < length; i++) { | ||
uint8_t val = data[i]; | ||
|
||
// shift out lsb first | ||
for (uint8_t bit = 0; bit < 8; bit++) { | ||
writePin(SPI_DATAOUT_PIN, !!(val & (1 << bit))); | ||
writePin(SPI_SCLK_PIN, true); | ||
wait_us(CLOCK_DELAY); | ||
|
||
writePin(SPI_SCLK_PIN, false); | ||
wait_us(CLOCK_DELAY); | ||
} | ||
} | ||
writePinHigh(SR_EXP_RCLK_PIN); | ||
return SPI_STATUS_SUCCESS; | ||
} | ||
|
||
#else | ||
|
||
void shift_init_impl(void) { spi_init(); } | ||
|
||
void shift_out_impl(const uint8_t *data, uint16_t length) { | ||
spi_start(SR_EXP_RCLK_PIN, true, 0, 0); | ||
|
||
spi_transmit(data, length); | ||
|
||
spi_stop(); | ||
} | ||
#endif | ||
|
||
// *************************************************************** | ||
|
||
void shift_out(const uint8_t *data, uint16_t length) { shift_out_impl(data, length); } | ||
|
||
void shift_enable(void) { | ||
setPinOutput(SR_EXP_OE_PIN); | ||
writePinLow(SR_EXP_OE_PIN); | ||
} | ||
|
||
void shift_disable(void) { | ||
setPinOutput(SR_EXP_OE_PIN); | ||
writePinHigh(SR_EXP_OE_PIN); | ||
} | ||
|
||
void shift_init(void) { | ||
shift_disable(); | ||
shift_init_impl(); | ||
} | ||
|
||
// *************************************************************** | ||
|
||
sr_exp_t sr_exp_data; | ||
|
||
void SR_EXP_WriteData(void) { | ||
uint8_t data[2] = { | ||
sr_exp_data.reg & 0xFF, // Shift in bits 7-0 | ||
(sr_exp_data.reg >> 8) & 0xFF, // Shift in bits 15-8 | ||
}; | ||
shift_out(data, 2); | ||
} | ||
|
||
void SR_EXP_Init(void) { | ||
shift_init(); | ||
|
||
sr_exp_data.reg = 0; | ||
sr_exp_data.bit.HUB_CONNECT = 0; | ||
sr_exp_data.bit.HUB_RESET_N = 0; | ||
sr_exp_data.bit.S_UP = 0; | ||
sr_exp_data.bit.E_UP_N = 1; | ||
sr_exp_data.bit.S_DN1 = 1; | ||
sr_exp_data.bit.E_DN1_N = 1; | ||
sr_exp_data.bit.E_VBUS_1 = 0; | ||
sr_exp_data.bit.E_VBUS_2 = 0; | ||
sr_exp_data.bit.SRC_1 = 1; | ||
sr_exp_data.bit.SRC_2 = 1; | ||
sr_exp_data.bit.IRST = 1; | ||
sr_exp_data.bit.SDB_N = 0; | ||
SR_EXP_WriteData(); | ||
|
||
shift_enable(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
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 "arm_atsam_protocol.h" | ||
#include "spi_master.h" | ||
#include "gpio.h" | ||
|
||
/* Determine bits to set for mux selection */ | ||
#if SPI_DATAOUT_PIN % 2 == 0 | ||
# define SPI_DATAOUT_MUX_SEL PMUXE | ||
#else | ||
# define SPI_DATAOUT_MUX_SEL PMUXO | ||
#endif | ||
|
||
/* Determine bits to set for mux selection */ | ||
#if SPI_SCLK_PIN % 2 == 0 | ||
# define SPI_SCLK_MUX_SEL PMUXE | ||
#else | ||
# define SPI_SCLK_MUX_SEL PMUXO | ||
#endif | ||
|
||
static pin_t currentSelectPin = NO_PIN; | ||
|
||
__attribute__((weak)) void spi_init(void) { | ||
static bool is_initialised = false; | ||
if (!is_initialised) { | ||
is_initialised = true; | ||
|
||
DBGC(DC_SPI_INIT_BEGIN); | ||
|
||
CLK_set_spi_freq(CHAN_SERCOM_SPI, FREQ_SPI_DEFAULT); | ||
|
||
// Set up MCU SPI pins | ||
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 | ||
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 | ||
PORT->Group[SAMD_PORT(SPI_DATAOUT_PIN)].PINCFG[SAMD_PIN(SPI_DATAOUT_PIN)].bit.PMUXEN = 1; // MUX Enable | ||
PORT->Group[SAMD_PORT(SPI_SCLK_PIN)].PINCFG[SAMD_PIN(SPI_SCLK_PIN)].bit.PMUXEN = 1; // MUX Enable | ||
|
||
DBGC(DC_SPI_INIT_COMPLETE); | ||
} | ||
} | ||
|
||
bool spi_start(pin_t csPin, bool lsbFirst, uint8_t mode, uint16_t divisor) { | ||
if (currentSelectPin != NO_PIN || csPin == NO_PIN) { | ||
return false; | ||
} | ||
|
||
currentSelectPin = csPin; | ||
setPinOutput(currentSelectPin); | ||
writePinLow(currentSelectPin); | ||
|
||
SPI_SERCOM->SPI.CTRLA.bit.DORD = lsbFirst; // Data Order - LSB is transferred first | ||
SPI_SERCOM->SPI.CTRLA.bit.CPOL = 1; // Clock Polarity - SCK high when idle. Leading edge of cycle is falling. Trailing rising. | ||
SPI_SERCOM->SPI.CTRLA.bit.CPHA = 1; // Clock Phase - Leading Edge Falling, change, Trailing Edge - Rising, sample | ||
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.) | ||
SPI_SERCOM->SPI.CTRLA.bit.DOPO = 0; // Data Output PAD[0], Serial Clock PAD[1] | ||
SPI_SERCOM->SPI.CTRLA.bit.MODE = 3; // Operating Mode - Master operation | ||
|
||
SPI_SERCOM->SPI.CTRLA.bit.ENABLE = 1; // Enable - Peripheral is enabled or being enabled | ||
while (SPI_SERCOM->SPI.SYNCBUSY.bit.ENABLE) { | ||
DBGC(DC_SPI_SYNC_ENABLING); | ||
} | ||
return true; | ||
} | ||
|
||
spi_status_t spi_transmit(const uint8_t *data, uint16_t length) { | ||
while (!(SPI_SERCOM->SPI.INTFLAG.bit.DRE)) { | ||
DBGC(DC_SPI_WRITE_DRE); | ||
} | ||
|
||
for (uint16_t i = 0; i < length; i++) { | ||
SPI_SERCOM->SPI.DATA.bit.DATA = data[i]; | ||
while (!(SPI_SERCOM->SPI.INTFLAG.bit.TXC)) { | ||
DBGC(DC_SPI_WRITE_TXC_1); | ||
} | ||
} | ||
|
||
return SPI_STATUS_SUCCESS; | ||
} | ||
|
||
void spi_stop(void) { | ||
if (currentSelectPin != NO_PIN) { | ||
setPinOutput(currentSelectPin); | ||
writePinHigh(currentSelectPin); | ||
currentSelectPin = NO_PIN; | ||
} | ||
} | ||
|
||
// Not implemented yet.... | ||
|
||
spi_status_t spi_write(uint8_t data); | ||
|
||
spi_status_t spi_read(void); | ||
|
||
spi_status_t spi_receive(uint8_t *data, uint16_t length); |
Oops, something went wrong.