diff options
author | David Crocker <dcrocker@eschertech.com> | 2017-11-01 01:32:49 +0300 |
---|---|---|
committer | David Crocker <dcrocker@eschertech.com> | 2017-11-01 01:32:49 +0300 |
commit | 8127d85ade4cc0f924c901407c5388f85c4e2835 (patch) | |
tree | de3990006af586eb04312d8a14cda01049e7718e /src | |
parent | 2423233e4b5d16694c84f3a9c00c5e62d910a737 (diff) |
Interim commit 1.20b4+2
Use PDC to send SPI data to TMC2660 drivers, in preparation for
continuous polling using interrupts
Tidied up new MAX31865 support
Increased number of allowed HTTP headers to 30
FTP server now allowes arguments in LIST command
FTP server now allows TYPE command when passive port is open
Diffstat (limited to 'src')
-rw-r--r-- | src/Duet/EMAC/ethernet_phy.h | 2 | ||||
-rw-r--r-- | src/Duet/EMAC/ethernet_sam.c | 2 | ||||
-rw-r--r-- | src/Duet/EMAC/ethernet_sam.h | 2 | ||||
-rw-r--r-- | src/Duet/EMAC/ethernetif.c | 4 | ||||
-rw-r--r-- | src/Duet/Webserver.cpp | 24 | ||||
-rw-r--r-- | src/Duet/Webserver.h | 2 | ||||
-rw-r--r-- | src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h | 2 | ||||
-rw-r--r-- | src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp | 12 | ||||
-rw-r--r-- | src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h | 2 | ||||
-rw-r--r-- | src/DuetNG/DuetWiFi/Network.cpp | 6 | ||||
-rw-r--r-- | src/DuetNG/FtpResponder.cpp | 26 | ||||
-rw-r--r-- | src/DuetNG/HttpResponder.h | 2 | ||||
-rw-r--r-- | src/DuetNG/TMC2660.cpp | 269 | ||||
-rw-r--r-- | src/DuetNG/TMC2660.h | 3 | ||||
-rw-r--r-- | src/Heating/Sensors/RtdSensor31865.cpp | 20 | ||||
-rw-r--r-- | src/Heating/Sensors/RtdSensor31865.h | 1 | ||||
-rw-r--r-- | src/Platform.cpp | 1 | ||||
-rw-r--r-- | src/Version.h | 4 |
18 files changed, 254 insertions, 130 deletions
diff --git a/src/Duet/EMAC/ethernet_phy.h b/src/Duet/EMAC/ethernet_phy.h index bf9f5567..c3a8ee52 100644 --- a/src/Duet/EMAC/ethernet_phy.h +++ b/src/Duet/EMAC/ethernet_phy.h @@ -47,7 +47,7 @@ #define KSZ8051RNL_H_INCLUDED #include "Core.h" -#include "emac.h" +#include "emac/emac.h" #include "conf_eth.h" /// @cond 0 diff --git a/src/Duet/EMAC/ethernet_sam.c b/src/Duet/EMAC/ethernet_sam.c index 0cb0f1d8..c6c6d9eb 100644 --- a/src/Duet/EMAC/ethernet_sam.c +++ b/src/Duet/EMAC/ethernet_sam.c @@ -68,8 +68,6 @@ #include "lwip/src/include/netif/etharp.h" #include "ethernetif.h" -#include "emac.h" - /* Global variable containing MAC Config (hw addr, IP, GW, ...) */ struct netif gs_net_if; diff --git a/src/Duet/EMAC/ethernet_sam.h b/src/Duet/EMAC/ethernet_sam.h index 52274ef8..dbea615a 100644 --- a/src/Duet/EMAC/ethernet_sam.h +++ b/src/Duet/EMAC/ethernet_sam.h @@ -45,7 +45,7 @@ #define ETHERNET_SAM_H_INCLUDED #include "lwip/src/include/lwip/netif.h" -#include "emac.h" // for emac_dev_tx_cb_t +#include "emac/emac.h" // for emac_dev_tx_cb_t /// @cond 0 /**INDENT-OFF**/ diff --git a/src/Duet/EMAC/ethernetif.c b/src/Duet/EMAC/ethernetif.c index d250cc41..fc015976 100644 --- a/src/Duet/EMAC/ethernetif.c +++ b/src/Duet/EMAC/ethernetif.c @@ -55,8 +55,8 @@ #include "lwip/src/include/netif/etharp.h" #include "lwip/src/include/netif/ppp_oe.h" -#include "emac.h" -#include "rstc.h" +#include "emac/emac.h" +#include "rstc/rstc.h" #include "ethernet_phy.h" #include "ethernetif.h" diff --git a/src/Duet/Webserver.cpp b/src/Duet/Webserver.cpp index bbb431a3..0351e85a 100644 --- a/src/Duet/Webserver.cpp +++ b/src/Duet/Webserver.cpp @@ -2189,7 +2189,7 @@ void Webserver::FtpInterpreter::ProcessLine() network->SaveFTPConnection(); // list directory entries - if (StringEquals(clientMessage, "LIST")) + if (StringStartsWith(clientMessage, "LIST")) { if (network->AcquireDataTransaction()) { @@ -2223,6 +2223,26 @@ void Webserver::FtpInterpreter::ProcessLine() state = authenticated; } } + // switch transfer mode (sends response, but doesn't have any effects) + else if (StringStartsWith(clientMessage, "TYPE")) + { + for (size_t i = 4; i < clientPointer; i++) + { + if (clientMessage[i] == 'I') + { + SendReply(200, "Switching to Binary mode."); + break; + } + + if (clientMessage[i] == 'A') + { + SendReply(200, "Switching to ASCII mode."); + break; + } + } + + SendReply(500, "Unknown command."); + } // upload a file else if (StringStartsWith(clientMessage, "STOR")) { @@ -2282,7 +2302,6 @@ void Webserver::FtpInterpreter::ProcessLine() network->CloseDataPort(); state = authenticated; } - break; case doingPasvIO: @@ -2307,7 +2326,6 @@ void Webserver::FtpInterpreter::ProcessLine() network->CloseDataPort(); state = authenticated; } - break; } } diff --git a/src/Duet/Webserver.h b/src/Duet/Webserver.h index fdadd94d..796e7ac2 100644 --- a/src/Duet/Webserver.h +++ b/src/Duet/Webserver.h @@ -49,7 +49,7 @@ const size_t minHttpResponseSize = 768; // minimum number of bytes required fo const size_t maxCommandWords = 4; // max number of space-separated words in the command const size_t maxQualKeys = 5; // max number of key/value pairs in the qualifier -const size_t maxHeaders = 16; // max number of key/value pairs in the headers +const size_t maxHeaders = 30; // max number of key/value pairs in the headers const size_t maxHttpSessions = 8; // maximum number of simultaneous HTTP sessions const uint32_t httpSessionTimeout = 8000; // HTTP session timeout in milliseconds diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h index 805a9811..45bc9564 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/W5500/w5500.h @@ -51,7 +51,7 @@ #include <cstdint> #include <cstddef> #include "../wizchip_conf.h" -#include "spi.h" +#include "spi/spi.h" // The following functions are defined in Network.cpp and used by this module extern void SpiAssertSS(); diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp index acf875fa..dde6c49d 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.cpp @@ -15,14 +15,14 @@ #define USE_DMAC 0 // use general DMA controller #if USE_PDC -#include "pdc.h" +#include "pdc/pdc.h" #endif #if USE_DMAC -#include "dmac.h" +#include "dmac/dmac.h" #endif -#include "matrix.h" +#include "matrix/matrix.h" // Functions called by the W5500 module to transfer data to/from the W5500 via SPI const uint32_t SpiClockFrequency = 40000000; // tried 60MHz and we got some data corruption when uploading files, so try 40MHz instead @@ -33,8 +33,7 @@ static Pdc *spi_pdc; static inline void spi_rx_dma_enable() { - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN); - pdc_enable_transfer(spi_pdc, PERIPH_PTCR_TXTEN); // we have to transmit in order to receive + pdc_enable_transfer(spi_pdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); // we have to transmit in order to receive } static inline void spi_tx_dma_enable() @@ -44,8 +43,7 @@ static inline void spi_tx_dma_enable() static inline void spi_rx_dma_disable() { - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS); - pdc_disable_transfer(spi_pdc, PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive + pdc_disable_transfer(spi_pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); // we have to transmit in order to receive } static inline void spi_tx_dma_disable() diff --git a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h index 21a5eadc..eeea6be4 100644 --- a/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h +++ b/src/DuetNG/DuetEthernet/Wiznet/Ethernet/WizSpi.h @@ -8,7 +8,7 @@ #ifndef SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ #define SRC_DUETNG_DUETETHERNET_ETHERNET3_UTILITY_WIZSPI_H_ -#include "spi.h" +#include "spi/spi.h" namespace WizSpi { diff --git a/src/DuetNG/DuetWiFi/Network.cpp b/src/DuetNG/DuetWiFi/Network.cpp index b72e992d..f4c9a2d2 100644 --- a/src/DuetNG/DuetWiFi/Network.cpp +++ b/src/DuetNG/DuetWiFi/Network.cpp @@ -19,14 +19,14 @@ #define USE_DMAC 1 // use general DMA controller #if USE_PDC -#include "pdc.h" +#include "pds/pdc.h" #endif #if USE_DMAC -#include "dmac.h" +#include "dmac/dmac.h" #endif -#include "matrix.h" +#include "matrix/matrix.h" const uint32_t WifiResponseTimeoutMillis = 200; const uint32_t WiFiWaitReadyMillis = 100; diff --git a/src/DuetNG/FtpResponder.cpp b/src/DuetNG/FtpResponder.cpp index 0d5567e8..f849370b 100644 --- a/src/DuetNG/FtpResponder.cpp +++ b/src/DuetNG/FtpResponder.cpp @@ -523,18 +523,16 @@ void FtpResponder::ProcessLine() if (StringEquals(type, "I")) { outBuf->copy("200 Switching to Binary mode.\r\n"); - Commit(ResponderState::reading); } else if (StringEquals(type, "A")) { outBuf->copy("200 Switching to ASCII mode.\r\n"); - Commit(ResponderState::reading); } else { outBuf->copy("500 Unknown command.\r\n"); - Commit(ResponderState::reading); } + Commit(ResponderState::reading); } // enter passive mode mode else if (StringEquals(clientMessage, "PASV")) @@ -560,7 +558,7 @@ void FtpResponder::ProcessLine() Commit(ResponderState::waitingForPasvPort); } // PASV commands are not supported in this state - else if (StringEquals(clientMessage, "LIST") || StringStartsWith(clientMessage, "RETR") || StringStartsWith(clientMessage, "STOR")) + else if (StringStartsWith(clientMessage, "LIST") || StringStartsWith(clientMessage, "RETR") || StringStartsWith(clientMessage, "STOR")) { outBuf->copy("425 Use PASV first.\r\n"); Commit(ResponderState::reading); @@ -671,7 +669,7 @@ void FtpResponder::ProcessLine() case ResponderState::pasvPortOpened: // list directory entries - if (StringEquals(clientMessage, "LIST")) + if (StringStartsWith(clientMessage, "LIST")) { // send announcement via ftp main port outBuf->copy("150 Here comes the directory listing.\r\n"); @@ -693,6 +691,24 @@ void FtpResponder::ProcessLine() } while (massStorage->FindNext(fileInfo)); } } + // switch transfer mode (sends response, but doesn't have any effects) + else if (StringStartsWith(clientMessage, "TYPE")) + { + const char *type = GetParameter("TYPE"); + if (StringEquals(type, "I")) + { + outBuf->copy("200 Switching to Binary mode.\r\n"); + } + else if (StringEquals(type, "A")) + { + outBuf->copy("200 Switching to ASCII mode.\r\n"); + } + else + { + outBuf->copy("500 Unknown command.\r\n"); + } + Commit(ResponderState::pasvPortOpened); + } // upload a file else if (StringStartsWith(clientMessage, "STOR")) { diff --git a/src/DuetNG/HttpResponder.h b/src/DuetNG/HttpResponder.h index a2ce9403..a11f561a 100644 --- a/src/DuetNG/HttpResponder.h +++ b/src/DuetNG/HttpResponder.h @@ -34,7 +34,7 @@ private: static const uint16_t WebMessageLength = TCP_MSS; // maximum length of the web message we accept after decoding static const size_t MaxCommandWords = 4; // max number of space-separated words in the command static const size_t MaxQualKeys = 5; // max number of key/value pairs in the qualifier - static const size_t MaxHeaders = 16; // max number of key/value pairs in the headers + static const size_t MaxHeaders = 30; // max number of key/value pairs in the headers static const uint32_t HttpSessionTimeout = 8000; // HTTP session timeout in milliseconds enum class HttpParseState diff --git a/src/DuetNG/TMC2660.cpp b/src/DuetNG/TMC2660.cpp index 12f2f4fb..c1423d42 100644 --- a/src/DuetNG/TMC2660.cpp +++ b/src/DuetNG/TMC2660.cpp @@ -5,8 +5,9 @@ * Author: David */ -#include "RepRapFirmware.h" #include "TMC2660.h" +#include "sam/drivers/pdc/pdc.h" +#include "sam/drivers/usart/usart.h" const float MaximumMotorCurrent = 2400.0; @@ -14,7 +15,7 @@ static size_t numTmc2660Drivers; static bool driversPowered = false; -// Pin assignments for the second prototype, using USART1 SPI +// Pin assignments, using USART1 in SPI mode const Pin DriversClockPin = 15; // PB15/TIOA1 const Pin DriversMosiPin = 22; // PA13 const Pin DriversMisoPin = 21; // PA22 @@ -22,16 +23,13 @@ const Pin DriversSclkPin = 23; // PA23 const int ChopperControlRegisterMode = 999; // mode passed to get/set microstepping to indicate we want the chopper control register -#define USART_EXT_DRV USART1 -#define ID_USART_EXT_DRV ID_USART1 -#define TMC_CLOCK_TC TC0 -#define TMC_CLOCK_CHAN 1 -#define TMC_CLOCK_ID ID_TC1 // this is channel 1 on TC0 +#define USART_TMC_DRV USART1 +#define ID_USART_TMC_DRV ID_USART1 const uint32_t DriversSpiClockFrequency = 4000000; // 4MHz SPI clock const int StallGuardThreshold = 1; // Range is -64..63. Zero seems to be too sensitive. Higher values reduce sensitivity of stall detection. -// TMC2660 registers +// TMC2660 register addresses const uint32_t TMC_REG_DRVCTRL = 0; const uint32_t TMC_REG_CHOPCONF = 0x80000; const uint32_t TMC_REG_SMARTEN = 0xA0000; @@ -144,106 +142,169 @@ const uint32_t defaultSmartEnReg = //---------------------------------------------------------------------------------------------------------------------------------- // Private types and methods -struct TmcDriverState +class TmcDriverState { - uint32_t drvCtrlReg; - uint32_t chopConfReg; - uint32_t smartEnReg; - uint32_t sgcsConfReg; - uint32_t drvConfReg; - uint32_t lastReadValue; - uint32_t pin; - uint32_t configuredChopConfReg; - +public: void Init(uint32_t p_pin); void WriteAll(); void SetChopConf(uint32_t newVal); void SetMicrostepping(uint32_t shift, bool interpolate); void SetCurrent(float current); void Enable(bool en); - void SpiSendWord(uint32_t dataOut); - uint32_t ReadStatus(); + void UpdateRegister(unsigned int reg); void SetStallThreshold(int sgThreshold); void SetStallFilter(bool sgFilter); void SetCoolStep(uint16_t coolStepConfig); void AppendStallConfig(StringRef& reply); + + void Poll(); // Temporary function until we use interrupts to poll the drivers continuously + + unsigned int GetMicrostepping(int mode, bool& interpolation) const; // Get microstepping or chopper control register + uint32_t ReadStatus() const; + +private: + static void SetupDMA(uint32_t val); // Set up the PDC to send a register and receive the status + + uint32_t registers[5]; // the values we want the TMC2660 writable registers to have + + // Register numbers are in priority order, most urgent first + static constexpr unsigned int DriveControl = 0; // microstepping + static constexpr unsigned int StallGuardConfig = 1; // motor current and stall threshold + static constexpr unsigned int ChopperControl = 2; // enable/disable + static constexpr unsigned int DriveConfig = 3; // read register select, sense voltage high/low sensitivity + static constexpr unsigned int SmartEnable = 4; // coolstep configuration + + uint32_t lastReadValue; // the status word that we read most recently + uint32_t pin; // the pin number that drives the chip select pin of this driver + uint32_t configuredChopConfReg; // the configured chopper control register, in the Enabled state + uint32_t registersToUpdate; // bitmap of register values that have been updated but not yet sent to the driver chip + static constexpr uint32_t UpdateAllRegisters = (1u << ARRAY_SIZE(registers)) - 1; // bitmap for all registers }; +// PDC address for the USART +static Pdc * const usartPdc = usart_get_pdc_base(USART_TMC_DRV); + +// Words to send and receive driver SPI data from/to +static uint32_t spiDataOut = 0; +static uint32_t spiDataIn = 0; + +// Set up the PDC to send a register and receive the status +/*static*/ inline void TmcDriverState::SetupDMA(uint32_t val) +{ + // Ensure the PDC is disabled + pdc_disable_transfer(usartPdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS); + + // SPI sends data MSB first, but the firmware uses little-endian mode, so we need to reverse the byte order + spiDataOut = cpu_to_be32(val << 8); + + pdc_packet_t pdc_spi_packet; + pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(&spiDataOut); + pdc_spi_packet.ul_size = 3; + pdc_tx_init(usartPdc, &pdc_spi_packet, nullptr); + + pdc_spi_packet.ul_addr = reinterpret_cast<uint32_t>(&spiDataIn); + pdc_spi_packet.ul_size = 3; + pdc_rx_init(usartPdc, &pdc_spi_packet, nullptr); + + pdc_enable_transfer(usartPdc, PERIPH_PTCR_RXTEN | PERIPH_PTCR_TXTEN); +} + // Initialise the state of the driver. void TmcDriverState::Init(uint32_t p_pin) pre(!driversPowered) { - drvCtrlReg = defaultDrvCtrlReg; + registers[DriveControl] = defaultDrvCtrlReg; configuredChopConfReg = defaultChopConfReg; - chopConfReg = configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK; // disable driver at startup - smartEnReg = defaultSmartEnReg; - sgcsConfReg = defaultSgscConfReg; - drvConfReg = defaultDrvConfReg; + registers[ChopperControl] = configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK; // disable driver at startup + registers[SmartEnable] = defaultSmartEnReg; + registers[StallGuardConfig] = defaultSgscConfReg; + registers[DriveConfig] = defaultDrvConfReg; pin = p_pin; - // No point in calling WriteAll() here because the drivers are assumed to be not powered up. + registersToUpdate = UpdateAllRegisters; + // No point in calling WriteAll() here because the drivers may not be powered up yet } // Send an SPI control string. The drivers need 20 bits. We send and receive 24 because the USART only supports 5 to 9 bit transfers. // If the drivers are not powered up, don't attempt a transaction, and return 0xFFFFFFFF -void TmcDriverState::SpiSendWord( uint32_t dataOut) +void TmcDriverState::UpdateRegister(unsigned int reg) { if (driversPowered) { - USART_EXT_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX; // reset transmitter and receiver - digitalWrite(pin, LOW); // set CS low - delayMicroseconds(1); // allow some CS low setup time - USART_EXT_DRV->US_CR = US_CR_RXEN | US_CR_TXEN; // enable transmitter and receiver +#if 1 + // Code to use the PDC, ready for continuous interrupt-driven polling of all drivers + USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX; // reset transmitter and receiver + digitalWrite(pin, LOW); // set CS low + SetupDMA(registers[reg]); // set up the PDC + USART_TMC_DRV->US_CR = US_CR_RXEN | US_CR_TXEN; // enable transmitter and receiver + + // Wait for the transfer to complete + for (int j = 0; (USART_TMC_DRV->US_CSR & (US_CSR_ENDRX | US_CSR_ENDTX)) != (US_CSR_ENDRX | US_CSR_ENDTX) && j < 10000; ++j) + { + } + + // Finish the transfer + digitalWrite(pin, HIGH); // set CS high again + lastReadValue = be32_to_cpu(spiDataIn) >> 12; + registersToUpdate &= ~(1u << reg); +#else + // Code that doesn't use the PDC + USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX; // reset transmitter and receiver + digitalWrite(pin, LOW); // set CS low + delayMicroseconds(1); // allow some CS low setup time + USART_TMC_DRV->US_CR = US_CR_RXEN | US_CR_TXEN; // enable transmitter and receiver + uint32_t dataOut = registers[reg]; uint32_t dataIn = 0; for (int i = 0; i < 3; ++i) { - USART_EXT_DRV->US_THR = (dataOut >> 16) & 0x000000FFu; + USART_TMC_DRV->US_THR = (dataOut >> 16) & 0x000000FFu; dataOut <<= 8; dataIn <<= 8; - for (int j = 0; j < 10000 && (USART_EXT_DRV->US_CSR & (US_CSR_RXRDY | US_CSR_TXRDY)) != (US_CSR_RXRDY | US_CSR_TXRDY); ++j) + for (int j = 0; j < 10000 && (USART_TMC_DRV->US_CSR & (US_CSR_RXRDY | US_CSR_TXRDY)) != (US_CSR_RXRDY | US_CSR_TXRDY); ++j) { // nothing } - dataIn |= USART_EXT_DRV->US_RHR & 0x000000FF; + dataIn |= USART_TMC_DRV->US_RHR & 0x000000FF; } delayMicroseconds(1); - digitalWrite(pin, HIGH); // set CS high again - USART_EXT_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; // reset and disable transmitter and receiver - delayMicroseconds(1); // ensure it stays high for long enough before the next write + digitalWrite(pin, HIGH); // set CS high again + USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; // reset and disable transmitter and receiver + delayMicroseconds(1); // ensure it stays high for long enough before the next write lastReadValue = dataIn >> 4; +#endif } } -// Write all registers, if the drivers are powered up +// Write all registers. This is called when the drivers are known to be powered up. void TmcDriverState::WriteAll() { - SpiSendWord(chopConfReg); - SpiSendWord(sgcsConfReg); - SpiSendWord(drvConfReg); - SpiSendWord(drvCtrlReg); - SpiSendWord(smartEnReg); + UpdateRegister(ChopperControl); + UpdateRegister(StallGuardConfig); + UpdateRegister(DriveConfig); + UpdateRegister(DriveControl); + UpdateRegister(SmartEnable); } // Set the chopper control register void TmcDriverState::SetChopConf(uint32_t newVal) { configuredChopConfReg = (newVal & 0x0001FFFF) | TMC_REG_CHOPCONF; // save the new value - Enable((chopConfReg & TMC_CHOPCONF_TOFF_MASK) != 0); // send the new value, keeping the current Enable status + Enable((registers[ChopperControl] & TMC_CHOPCONF_TOFF_MASK) != 0); // send the new value, keeping the current Enable status } // Set the microstepping and microstep interpolation void TmcDriverState::SetMicrostepping(uint32_t shift, bool interpolate) { - drvCtrlReg &= ~TMC_DRVCTRL_MRES_MASK; - drvCtrlReg |= (shift << TMC_DRVCTRL_MRES_SHIFT) & TMC_DRVCTRL_MRES_MASK; + registers[DriveControl] &= ~TMC_DRVCTRL_MRES_MASK; + registers[DriveControl] |= (shift << TMC_DRVCTRL_MRES_SHIFT) & TMC_DRVCTRL_MRES_MASK; if (interpolate) { - drvCtrlReg |= TMC_DRVCTRL_INTPOL; + registers[DriveControl] |= TMC_DRVCTRL_INTPOL; } else { - drvCtrlReg &= ~TMC_DRVCTRL_INTPOL; + registers[DriveControl] &= ~TMC_DRVCTRL_INTPOL; } - SpiSendWord(drvCtrlReg); + registersToUpdate |= 1u << DriveControl; } // Set the motor current @@ -251,66 +312,97 @@ void TmcDriverState::SetCurrent(float current) { // The current sense resistor on the production Duet WiFi is 0.051 ohms. // This gives us a range of 101mA to 3.236A in 101mA steps in the high sensitivity range (VSENSE = 1) - drvConfReg |= TMC_DRVCONF_VSENSE; // this should always be set, but send it again just in case - SpiSendWord(drvConfReg); - const uint32_t iCurrent = static_cast<uint32_t>(constrain<float>(current, 100.0, MaximumMotorCurrent)); const uint32_t csBits = (32 * iCurrent - 1600)/3236; // formula checked by simulation on a spreadsheet - sgcsConfReg &= ~TMC_SGCSCONF_CS_MASK; - sgcsConfReg |= TMC_SGCSCONF_CS(csBits); - SpiSendWord(sgcsConfReg); + registers[StallGuardConfig] &= ~TMC_SGCSCONF_CS_MASK; + registers[StallGuardConfig] |= TMC_SGCSCONF_CS(csBits); + registersToUpdate |= 1u << StallGuardConfig; } // Enable or disable the driver. Also called from SetChopConf after the chopper control configuration has been changed. void TmcDriverState::Enable(bool en) { - chopConfReg = (en) ? configuredChopConfReg : (configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK); - SpiSendWord(chopConfReg); + registers[ChopperControl] = (en) ? configuredChopConfReg : (configuredChopConfReg & ~TMC_CHOPCONF_TOFF_MASK); + registersToUpdate |= 1u << ChopperControl; } // Read the status -uint32_t TmcDriverState::ReadStatus() +uint32_t TmcDriverState::ReadStatus() const { - // We need to send a command in order to get up-to-date status - SpiSendWord(smartEnReg); return lastReadValue & (TMC_RR_SG | TMC_RR_OT | TMC_RR_OTPW | TMC_RR_S2G | TMC_RR_OLA | TMC_RR_OLB | TMC_RR_STST); } void TmcDriverState::SetStallThreshold(int sgThreshold) { const uint32_t sgVal = ((uint32_t)constrain<int>(sgThreshold, -64, 63)) & 127; - sgcsConfReg = (sgcsConfReg & ~TMC_SGCSCONF_SGT_MASK) | (sgVal << TMC_SGCSCONF_SGT_SHIFT); - SpiSendWord(sgcsConfReg); + registers[StallGuardConfig] = (registers[StallGuardConfig] & ~TMC_SGCSCONF_SGT_MASK) | (sgVal << TMC_SGCSCONF_SGT_SHIFT); + registersToUpdate |= 1u << StallGuardConfig; } void TmcDriverState::SetStallFilter(bool sgFilter) { if (sgFilter) { - sgcsConfReg |= TMC_SGCSCONF_SGT_SFILT; + registers[StallGuardConfig] |= TMC_SGCSCONF_SGT_SFILT; } else { - sgcsConfReg &= ~TMC_SGCSCONF_SGT_SFILT; + registers[StallGuardConfig] &= ~TMC_SGCSCONF_SGT_SFILT; } - SpiSendWord(sgcsConfReg); + registersToUpdate |= 1u << StallGuardConfig; } void TmcDriverState::SetCoolStep(uint16_t coolStepConfig) { - smartEnReg = TMC_REG_SMARTEN | coolStepConfig; - SpiSendWord(smartEnReg); + registers[SmartEnable] = TMC_REG_SMARTEN | coolStepConfig; + registersToUpdate |= 1u << SmartEnable; } void TmcDriverState::AppendStallConfig(StringRef& reply) { - const bool filtered = ((sgcsConfReg & TMC_SGCSCONF_SGT_SFILT) != 0); - int threshold = (int)((sgcsConfReg & TMC_SGCSCONF_SGT_MASK) >> TMC_SGCSCONF_SGT_SHIFT); + const bool filtered = ((registers[StallGuardConfig] & TMC_SGCSCONF_SGT_SFILT) != 0); + int threshold = (int)((registers[StallGuardConfig] & TMC_SGCSCONF_SGT_MASK) >> TMC_SGCSCONF_SGT_SHIFT); if (threshold >= 64) { threshold -= 128; } - reply.catf("stall threshold %d, filter %s, coolstep %" PRIx32, threshold, ((filtered) ? "on" : "off"), smartEnReg & 0xFFFF); + reply.catf("stall threshold %d, filter %s, coolstep %" PRIx32, threshold, ((filtered) ? "on" : "off"), registers[SmartEnable] & 0xFFFF); +} + +// Get microstepping or chopper control register +unsigned int TmcDriverState::GetMicrostepping(int mode, bool& interpolation) const +{ + interpolation = (registers[DriveControl] & TMC_DRVCTRL_INTPOL) != 0; + if (mode == ChopperControlRegisterMode) + { + return configuredChopConfReg & TMC_DATA_MASK; + } + else + { + const uint32_t mresBits = (registers[DriveControl] & TMC_DRVCTRL_MRES_MASK) >> TMC_DRVCTRL_MRES_SHIFT; + return 256 >> mresBits; + } +} + +// Temporary function until we use interrupts to poll the drivers continuously +void TmcDriverState::Poll() +{ + if (registersToUpdate != 0) + { + for (unsigned int reg = 0; reg < 5; ++reg) + { + if ((registersToUpdate & (1u << reg)) != 0) + { + UpdateRegister(reg); + break; + } + } + } + else + { + // We need to send a command in order to retrieve the up-to-date status + UpdateRegister(SmartEnable); + } } static TmcDriverState driverStates[DRIVES]; @@ -348,7 +440,7 @@ namespace SmartDrivers #endif // Enable the clock to the USART - pmc_enable_periph_clk(ID_USART_EXT_DRV); + pmc_enable_periph_clk(ID_USART_TMC_DRV); // Set up the CS pins and set them all high // When this becomes the standard code, we must set up the STEP and DIR pins here too. @@ -358,16 +450,16 @@ namespace SmartDrivers } // Set USART_EXT_DRV in SPI mode, with data changing on the falling edge of the clock and captured on the rising edge - USART_EXT_DRV->US_IDR = ~0u; - USART_EXT_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; - USART_EXT_DRV->US_MR = US_MR_USART_MODE_SPI_MASTER + USART_TMC_DRV->US_IDR = ~0u; + USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS; + USART_TMC_DRV->US_MR = US_MR_USART_MODE_SPI_MASTER | US_MR_USCLKS_MCK | US_MR_CHRL_8_BIT | US_MR_CHMODE_NORMAL | US_MR_CPOL | US_MR_CLKO; - USART_EXT_DRV->US_BRGR = VARIANT_MCK/DriversSpiClockFrequency; // 1MHz SPI clock - USART_EXT_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA; + USART_TMC_DRV->US_BRGR = VARIANT_MCK/DriversSpiClockFrequency; // set SPI clock frequency + USART_TMC_DRV->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA; // We need a few microseconds of delay here for the USART to sort itself out, // otherwise the processor generates two short reset pulses on its own NRST pin, and resets itself. @@ -435,21 +527,7 @@ namespace SmartDrivers // Get microstepping or chopper control register unsigned int GetMicrostepping(size_t drive, int mode, bool& interpolation) { - if (drive < numTmc2660Drivers) - { - const uint32_t drvCtrl = driverStates[drive].drvCtrlReg; - interpolation = (drvCtrl & TMC_DRVCTRL_INTPOL) != 0; - if (mode == ChopperControlRegisterMode) - { - return driverStates[drive].configuredChopConfReg & TMC_DATA_MASK; - } - else - { - const uint32_t mresBits = (drvCtrl & TMC_DRVCTRL_MRES_MASK) >> TMC_DRVCTRL_MRES_SHIFT; - return 256 >> mresBits; - } - } - return 1; + return (drive < numTmc2660Drivers) ? driverStates[drive].GetMicrostepping(mode, interpolation) : 1; } // Flag the the drivers have been powered up. @@ -509,6 +587,15 @@ namespace SmartDrivers } } + // Temporary function, until we use interrupts to poll drivers continuously + void Poll(size_t drive) + { + if (driversPowered && drive < numTmc2660Drivers) + { + driverStates[drive].Poll(); + } + } + }; // end namespace // End diff --git a/src/DuetNG/TMC2660.h b/src/DuetNG/TMC2660.h index 91f4b40c..9ab762e7 100644 --- a/src/DuetNG/TMC2660.h +++ b/src/DuetNG/TMC2660.h @@ -8,6 +8,7 @@ #ifndef TMC2660_H_ #define TMC2660_H_ +#include "RepRapFirmware.h" #include "Pins.h" #include "Libraries/General/StringRef.h" @@ -34,6 +35,8 @@ namespace SmartDrivers void SetStallFilter(size_t drive, bool sgFilter); void SetCoolStep(size_t drive, uint16_t coolStepConfig); void AppendStallConfig(size_t drive, StringRef& reply); + + void Poll(size_t drive); // temporary function, until we use interrupts to poll drivers continuously }; #endif /* TMC2660_H_ */ diff --git a/src/Heating/Sensors/RtdSensor31865.cpp b/src/Heating/Sensors/RtdSensor31865.cpp index 07ca0474..25b17966 100644 --- a/src/Heating/Sensors/RtdSensor31865.cpp +++ b/src/Heating/Sensors/RtdSensor31865.cpp @@ -10,9 +10,6 @@ #include "Platform.h" #include "GCodes/GCodeBuffer.h" -short RRef = 400; // default value of the reference resistor -const short CelsiusMin = -200; // minimum temperature of the temp table below - const uint32_t MAX31865_Frequency = 4000000; // maximum for MAX31865 is also 5MHz // SPI modes: @@ -36,6 +33,8 @@ const uint32_t MinimumReadInterval = 100; // minimum interval between reads, in const uint8_t DefaultCr0 = 0b11000011; const uint8_t Cr0ReadMask = 0b11011101; // bits 1 and 5 auto clear, so ignore the value read +const uint16_t DefaultRef = 400; + // pt100rtd list of resistances v temperature // // DIN 43760 / IEC 751 resistance values (ohms) were multiplied by 100 and @@ -45,9 +44,12 @@ const uint8_t Cr0ReadMask = 0b11011101; // bits 1 and 5 auto clear, so ignore t // 1852 represents 18.52 ohms and corresponds to a temperature of -200C. // 10000 ==> 100.00 ohms @ 0C // 13851 ==> 138.51 ohms @ 100C + +const float CelsiusMin = -100.0; // starting temperature of the temp table below +const float CelsiusInterval = 10.0; + static const uint16_t tempTable[] = { - 1852, 2283, 2710, 3134, 3554, 3972, 4388, 4800, 5211, 5619, 6026, 6430, 6833, 7233, 7633, 8031, 8427, 8822, 9216, 9609, 10000, 10390, 10779, 11167, 11554, 11940, 12324, 12708, 13090, 13471, 13851, 14229, 14607, 14983, 15358, 15733, 16105, 16477, 16848, 17217, @@ -64,7 +66,7 @@ const size_t NumTempTableEntries = sizeof(tempTable)/sizeof(tempTable[0]); RtdSensor31865::RtdSensor31865(unsigned int channel) : SpiTemperatureSensor(channel, "PT100 (MAX31865)", channel - FirstRtdChannel, MAX31865_SpiMode, MAX31865_Frequency), - cr0(DefaultCr0) + rref(DefaultRef), cr0(DefaultCr0) { } @@ -91,13 +93,13 @@ bool RtdSensor31865::Configure(unsigned int mCode, unsigned int heater, GCodeBuf if (gb.Seen('R')) { seen = true; - RRef = (short)gb.GetIValue(); + rref = (uint16_t)gb.GetUIValue(); } if (!seen && !gb.Seen('X')) { CopyBasicHeaterDetails(heater, reply); - reply.catf(", reject %dHz, reference resistor: %d ohms", (cr0 & 0x01) ? 50 : 60, RRef); + reply.catf(", reject %dHz, reference resistor %u ohms", (cr0 & 0x01) ? 50 : 60, (unsigned int)rref); } } return false; @@ -190,7 +192,7 @@ TemperatureError RtdSensor31865::GetTemperature(float& t) } else { - const float ohmsx100 = ((rawVal >> 1) & 0x7FFF) * RRef / 32768.0 * 100; + const uint16_t ohmsx100 = (uint16_t)((((rawVal >> 1) & 0x7FFF) * rref * 100) >> 15); // Formally-verified binary search routine, adapted from one of the eCv examples size_t low = 0u, high = NumTempTableEntries; @@ -226,7 +228,7 @@ TemperatureError RtdSensor31865::GetTemperature(float& t) { const float temperatureFraction = (float)(ohmsx100 - tempTable[low - 1])/(float)(tempTable[low] - tempTable[low - 1]); - t = lastTemperature = 10 * (low - 1) + CelsiusMin + 10 * temperatureFraction; + t = lastTemperature = CelsiusInterval * (low - 1 + temperatureFraction) + CelsiusMin; //debugPrintf("raw %f low %u temp %f\n", ohmsx100, low, t); lastResult = TemperatureError::success; diff --git a/src/Heating/Sensors/RtdSensor31865.h b/src/Heating/Sensors/RtdSensor31865.h index 95c98d79..0047ccac 100644 --- a/src/Heating/Sensors/RtdSensor31865.h +++ b/src/Heating/Sensors/RtdSensor31865.h @@ -21,6 +21,7 @@ public: private: TemperatureError TryInitRtd() const; + uint16_t rref; // reference resistor in ohms uint8_t cr0; }; diff --git a/src/Platform.cpp b/src/Platform.cpp index cdd92697..09c38bed 100644 --- a/src/Platform.cpp +++ b/src/Platform.cpp @@ -1363,6 +1363,7 @@ void Platform::Spin() // Poll one TMC2660 for temperature warning or temperature shutdown if (enableValues[nextDriveToPoll] >= 0) // don't poll driver if it is flagged "no poll" { + SmartDrivers::Poll(nextDriveToPoll); const uint32_t stat = SmartDrivers::GetStatus(nextDriveToPoll); const DriversBitmap mask = MakeBitmap<DriversBitmap>(nextDriveToPoll); if (stat & TMC_RR_OT) diff --git a/src/Version.h b/src/Version.h index 0b23653e..354b23b3 100644 --- a/src/Version.h +++ b/src/Version.h @@ -9,11 +9,11 @@ #define SRC_VERSION_H_ #ifndef VERSION -# define VERSION "1.20beta4" +# define VERSION "1.20beta4+2" #endif #ifndef DATE -# define DATE "2017-10-28" +# define DATE "2017-10-31" #endif #define AUTHORS "reprappro, dc42, chrishamm, t3p3, dnewman" |