From 959a2d2527f478bc5e18b4e0ea695584cee3101c Mon Sep 17 00:00:00 2001 From: revilor Date: Wed, 3 Jan 2018 12:12:25 +0100 Subject: [PATCH] Add beginTransaction to HAL SPI (#9019) --- Marlin/src/HAL/HAL_AVR/HAL_spi_AVR.cpp | 80 ++++++++++++++++++- Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp | 13 +++ Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp | 7 ++ .../src/HAL/HAL_STM32F1/HAL_spi_Stm32f1.cpp | 7 ++ .../HAL/HAL_TEENSY35_36/HAL_spi_Teensy.cpp | 8 ++ Marlin/src/HAL/SPI.h | 10 +++ 6 files changed, 122 insertions(+), 3 deletions(-) diff --git a/Marlin/src/HAL/HAL_AVR/HAL_spi_AVR.cpp b/Marlin/src/HAL/HAL_AVR/HAL_spi_AVR.cpp index 59f40a365..ef0dc8b1a 100644 --- a/Marlin/src/HAL/HAL_AVR/HAL_spi_AVR.cpp +++ b/Marlin/src/HAL/HAL_AVR/HAL_spi_AVR.cpp @@ -1,4 +1,4 @@ -/** +/* * Marlin 3D Printer Firmware * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * @@ -94,7 +94,9 @@ void spiBegin (void) { SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1); SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X); } - //------------------------------------------------------------------------------ + + + //------------------------------------------------------------------------------ /** SPI receive a byte */ uint8_t spiRec(void) { SPDR = 0xFF; @@ -132,6 +134,72 @@ void spiBegin (void) { } while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ } } + + + /** begin spi transaction */ + void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + // Based on Arduino SPI library + // Clock settings are defined as follows. Note that this shows SPI2X + // inverted, so the bits form increasing numbers. Also note that + // fosc/64 appears twice + // SPR1 SPR0 ~SPI2X Freq + // 0 0 0 fosc/2 + // 0 0 1 fosc/4 + // 0 1 0 fosc/8 + // 0 1 1 fosc/16 + // 1 0 0 fosc/32 + // 1 0 1 fosc/64 + // 1 1 0 fosc/64 + // 1 1 1 fosc/128 + + // We find the fastest clock that is less than or equal to the + // given clock rate. The clock divider that results in clock_setting + // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the + // slowest (128 == 2 ^^ 7, so clock_div = 6). + uint8_t clockDiv; + + // When the clock is known at compiletime, use this if-then-else + // cascade, which the compiler knows how to completely optimize + // away. When clock is not known, use a loop instead, which generates + // shorter code. + if (__builtin_constant_p(spiClock)) { + if (spiClock >= F_CPU / 2) { + clockDiv = 0; + } else if (spiClock >= F_CPU / 4) { + clockDiv = 1; + } else if (spiClock >= F_CPU / 8) { + clockDiv = 2; + } else if (spiClock >= F_CPU / 16) { + clockDiv = 3; + } else if (spiClock >= F_CPU / 32) { + clockDiv = 4; + } else if (spiClock >= F_CPU / 64) { + clockDiv = 5; + } else { + clockDiv = 6; + } + } else { + uint32_t clockSetting = F_CPU / 2; + clockDiv = 0; + while (clockDiv < 6 && spiClock < clockSetting) { + clockSetting /= 2; + clockDiv++; + } + } + + // Compensate for the duplicate fosc/64 + if (clockDiv == 6) + clockDiv = 7; + + // Invert the SPI2X bit + clockDiv ^= 0x1; + + SPCR = _BV(SPE) | _BV(MSTR) | ((bitOrder == SPI_LSBFIRST) ? _BV(DORD) : 0) | + (dataMode << CPHA) | ((clockDiv >> 1) << SPR0); + SPSR = clockDiv | 0x01; + } + + //------------------------------------------------------------------------------ #else // SOFTWARE_SPI //------------------------------------------------------------------------------ @@ -144,6 +212,12 @@ void spiBegin (void) { UNUSED(spiRate); } + /** Begin SPI transaction, set clock, bit order, data mode */ + void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + // nothing to do + UNUSED(spiBeginTransaction); + } + //------------------------------------------------------------------------------ /** Soft SPI receive byte */ uint8_t spiRec() { @@ -206,7 +280,7 @@ void spiBegin (void) { spiSend(token); for (uint16_t i = 0; i < 512; i++) spiSend(buf[i]); - } + } #endif // SOFTWARE_SPI diff --git a/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp b/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp index 95123615c..2b9ec8038 100644 --- a/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp +++ b/Marlin/src/HAL/HAL_DUE/HAL_spi_Due.cpp @@ -571,6 +571,12 @@ WRITE(SCK_PIN, LOW); } + /** Begin SPI transaction, set clock, bit order, data mode */ + void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + // TODO: to be implemented + + } + #pragma GCC reset_options #else @@ -767,6 +773,13 @@ } spiSend(buf[511]); } + + /** Begin SPI transaction, set clock, bit order, data mode */ + void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + // TODO: to be implemented + + } + #endif // ENABLED(SOFTWARE_SPI) #endif // ARDUINO_ARCH_SAM diff --git a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp index 507ac61cf..eb8d5ba98 100644 --- a/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp +++ b/Marlin/src/HAL/HAL_LPC1768/HAL_spi.cpp @@ -299,6 +299,13 @@ PinCfg.Portnum = LPC1768_PIN_PORT(MISO_PIN); // Write from buffer to SPI void spiSendBlock(uint8_t token, const uint8_t* buf) { } + + /** Begin SPI transaction, set clock, bit order, data mode */ + void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + // TODO: to be implemented + + } + #endif // ENABLED(LPC_SOFTWARE_SPI) #endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/HAL_STM32F1/HAL_spi_Stm32f1.cpp b/Marlin/src/HAL/HAL_STM32F1/HAL_spi_Stm32f1.cpp index 87169c5a5..650938c13 100644 --- a/Marlin/src/HAL/HAL_STM32F1/HAL_spi_Stm32f1.cpp +++ b/Marlin/src/HAL/HAL_STM32F1/HAL_spi_Stm32f1.cpp @@ -164,6 +164,13 @@ void spiSendBlock(uint8_t token, const uint8_t* buf) { SPI.endTransaction(); } +/** Begin SPI transaction, set clock, bit order, data mode */ +void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + spiConfig = SPISettings(spiClock, bitOrder, dataMode); + + SPI.beginTransaction(spiConfig); +} + #endif // SOFTWARE_SPI #endif // __STM32F1__ diff --git a/Marlin/src/HAL/HAL_TEENSY35_36/HAL_spi_Teensy.cpp b/Marlin/src/HAL/HAL_TEENSY35_36/HAL_spi_Teensy.cpp index df6e0265f..25b3dc935 100644 --- a/Marlin/src/HAL/HAL_TEENSY35_36/HAL_spi_Teensy.cpp +++ b/Marlin/src/HAL/HAL_TEENSY35_36/HAL_spi_Teensy.cpp @@ -101,4 +101,12 @@ void spiSendBlock(uint8_t token, const uint8_t* buf) { } +/** Begin SPI transaction, set clock, bit order, data mode */ +void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { + spiConfig = SPISettings(spiClock, bitOrder, dataMode); + + SPI.beginTransaction(spiConfig); +} + + #endif diff --git a/Marlin/src/HAL/SPI.h b/Marlin/src/HAL/SPI.h index 632c50b9a..d8c67076c 100644 --- a/Marlin/src/HAL/SPI.h +++ b/Marlin/src/HAL/SPI.h @@ -55,6 +55,14 @@ #define SPI_SPEED_5 5 // Set SCK rate to 1/32 of max rate #define SPI_SPEED_6 6 // Set SCK rate to 1/64 of max rate +#define SPI_LSBFIRST 0 +#define SPI_MSBFIRST 1 + +#define SPI_DATAMODE_0 0x00 +#define SPI_DATAMODE_1 0x04 +#define SPI_DATAMODE_2 0x08 +#define SPI_DATAMODE_3 0x0C + // Standard SPI functions /** Initialise SPI bus */ void spiBegin(void); @@ -68,5 +76,7 @@ uint8_t spiRec(void); void spiRead(uint8_t* buf, uint16_t nbyte); /** Write token and then write from 512 byte buffer to SPI (for SD card) */ void spiSendBlock(uint8_t token, const uint8_t* buf); +/** Begin SPI transaction, set clock, bit order, data mode */ +void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode); #endif // _SPI_H_