From 764a0b64a70bbacea1e4f01b11a92d69d3515111 Mon Sep 17 00:00:00 2001 From: Jin <3448324+jinhong-@users.noreply.github.com> Date: Sun, 7 Nov 2021 11:53:36 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8D=BB=20Preliminary=20fix=20for=20Max318?= =?UTF-8?q?65=20SPI=20(#22682)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Scott Lahteine --- Marlin/src/HAL/shared/Delay.h | 15 +++- Marlin/src/HAL/shared/Marduino.h | 2 +- Marlin/src/libs/MAX31865.cpp | 125 +++++++++++++++---------------- Marlin/src/libs/MAX31865.h | 11 ++- buildroot/tests/LPC1769 | 3 +- buildroot/tests/teensy41 | 5 +- 6 files changed, 90 insertions(+), 71 deletions(-) diff --git a/Marlin/src/HAL/shared/Delay.h b/Marlin/src/HAL/shared/Delay.h index 04df35d88d6a6..df07881f01d90 100644 --- a/Marlin/src/HAL/shared/Delay.h +++ b/Marlin/src/HAL/shared/Delay.h @@ -92,6 +92,12 @@ void calibrate_delay_loop(); #define DELAY_CYCLES(X) do { SmartDelay _smrtdly_X(X); } while(0) + #if GCC_VERSION <= 70000 + #define DELAY_CYCLES_VAR(X) DelayCycleFnc(X) + #else + #define DELAY_CYCLES_VAR DELAY_CYCLES + #endif + // For delay in microseconds, no smart delay selection is required, directly call the delay function // Teensy compiler is too old and does not accept smart delay compile-time / run-time selection correctly #define DELAY_US(x) DelayCycleFnc((x) * ((F_CPU) / 1000000UL)) @@ -200,9 +206,12 @@ void calibrate_delay_loop(); #endif #if ENABLED(DELAY_NS_ROUND_DOWN) - #define DELAY_NS(x) DELAY_CYCLES((x) * ((F_CPU) / 1000000UL) / 1000UL) // floor + #define _NS_TO_CYCLES(x) ( (x) * ((F_CPU) / 1000000UL) / 1000UL) // floor #elif ENABLED(DELAY_NS_ROUND_CLOSEST) - #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round + #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 500) / 1000UL) // round #else - #define DELAY_NS(x) DELAY_CYCLES(((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil" + #define _NS_TO_CYCLES(x) (((x) * ((F_CPU) / 1000000UL) + 999) / 1000UL) // "ceil" #endif + +#define DELAY_NS(x) DELAY_CYCLES(_NS_TO_CYCLES(x)) +#define DELAY_NS_VAR(x) DELAY_CYCLES_VAR(_NS_TO_CYCLES(x)) diff --git a/Marlin/src/HAL/shared/Marduino.h b/Marlin/src/HAL/shared/Marduino.h index 3b5a68a373201..0e2a021a3c4e9 100644 --- a/Marlin/src/HAL/shared/Marduino.h +++ b/Marlin/src/HAL/shared/Marduino.h @@ -39,7 +39,7 @@ #define DISABLED(V...) DO(DIS,&&,V) #undef _BV -#define _BV(b) (1UL << (b)) +#define _BV(b) (1 << (b)) #ifndef SBI #define SBI(A,B) (A |= _BV(B)) #endif diff --git a/Marlin/src/libs/MAX31865.cpp b/Marlin/src/libs/MAX31865.cpp index df0702b9fb58e..94048af2089cd 100644 --- a/Marlin/src/libs/MAX31865.cpp +++ b/Marlin/src/libs/MAX31865.cpp @@ -48,20 +48,17 @@ #if HAS_MAX31865 && !USE_ADAFRUIT_MAX31865 -//#include // TODO: switch to SPIclass/SoftSPI #include "MAX31865.h" +#ifdef TARGET_LPC1768 + #include +#endif + // The maximum speed the MAX31865 can do is 5 MHz SPISettings MAX31865::spiConfig = SPISettings( - #if defined(TARGET_LPC1768) - SPI_QUARTER_SPEED - #elif defined(ARDUINO_ARCH_STM32) - SPI_CLOCK_DIV4 - #else - 500000 - #endif - , MSBFIRST - , SPI_MODE_1 // CPOL0 CPHA1 + TERN(TARGET_LPC1768, SPI_QUARTER_SPEED, TERN(ARDUINO_ARCH_STM32, SPI_CLOCK_DIV4, 500000)), + MSBFIRST, + SPI_MODE1 // CPOL0 CPHA1 ); #ifndef LARGE_PINMAP @@ -93,7 +90,7 @@ SPISettings MAX31865::spiConfig = SPISettings( _sclk = _miso = _mosi = -1; } -#else +#else // LARGE_PINMAP /** * Create the interface object using software (bitbang) SPI for PIN values @@ -106,9 +103,7 @@ SPISettings MAX31865::spiConfig = SPISettings( * @param spi_clk the SPI clock pin to use * @param pin_mapping set to 1 for positive pin values */ - MAX31865::MAX31865(uint32_t spi_cs, uint32_t spi_mosi, - uint32_t spi_miso, uint32_t spi_clk, - uint8_t pin_mapping) { + MAX31865::MAX31865(uint32_t spi_cs, uint32_t spi_mosi, uint32_t spi_miso, uint32_t spi_clk, uint8_t pin_mapping) { _cs = spi_cs; _mosi = spi_mosi; _miso = spi_miso; @@ -130,14 +125,12 @@ SPISettings MAX31865::spiConfig = SPISettings( #endif // LARGE_PINMAP - /** * * Instance & Class methods * */ - /** * Initialize the SPI interface and set the number of RTD wires used * @@ -152,22 +145,13 @@ void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) { OUT_WRITE(_cs, HIGH); if (_sclk != TERN(LARGE_PINMAP, -1UL, -1)) { - // Define pin modes for Software SPI - #ifdef MAX31865_DEBUG - SERIAL_ECHOLN("Initializing MAX31865 Software SPI"); - #endif - - OUT_WRITE(_sclk, LOW); - SET_OUTPUT(_mosi); - SET_INPUT(_miso); + softSpiBegin(SPI_QUARTER_SPEED); // Define pin modes for Software SPI } else { - // Start and configure hardware SPI #ifdef MAX31865_DEBUG - SERIAL_ECHOLN("Initializing MAX31865 Hardware SPI"); + SERIAL_ECHOLNPGM("Initializing MAX31865 Hardware SPI"); #endif - - SPI.begin(); + SPI.begin(); // Start and configure hardware SPI } setWires(wires); @@ -176,25 +160,15 @@ void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) { clearFault(); #ifdef MAX31865_DEBUG_SPI - #ifndef LARGE_PINMAP - SERIAL_ECHOLNPGM( - "Regular begin call with _cs: ", _cs, - " _miso: ", _miso, - " _sclk: ", _sclk, - " _mosi: ", _mosi - ); - #else - SERIAL_ECHOLNPGM( - "LARGE_PINMAP begin call with _cs: ", _cs, - " _miso: ", _miso, - " _sclk: ", _sclk, - " _mosi: ", _mosi - ); - #endif // LARGE_PINMAP - - SERIAL_ECHOLNPGM("config: ", readRegister8(MAX31856_CONFIG_REG)); - SERIAL_EOL(); - #endif // MAX31865_DEBUG_SPI + SERIAL_ECHOLNPGM( + TERN(LARGE_PINMAP, "LARGE_PINMAP", "Regular") + " begin call with _cs: ", _cs, + " _miso: ", _miso, + " _sclk: ", _sclk, + " _mosi: ", _mosi, + " config: ", readRegister8(MAX31856_CONFIG_REG) + ); + #endif } /** @@ -371,7 +345,6 @@ float MAX31865::temperature(float Rrtd) { // private: // - /** * Set a value in the configuration register. * @@ -432,10 +405,15 @@ void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) { WRITE(_sclk, LOW); WRITE(_cs, LOW); - spixfer(addr); + + #ifdef TARGET_LPC1768 + DELAY_CYCLES(_spi_speed); + #endif + + spiTransfer(addr); while (n--) { - buffer[0] = spixfer(0xFF); + buffer[0] = spiTransfer(0xFF); #ifdef MAX31865_DEBUG_SPI SERIAL_ECHOLNPGM("buffer read ", n, " data: ", buffer[0]); #endif @@ -462,8 +440,12 @@ void MAX31865::writeRegister8(uint8_t addr, uint8_t data) { WRITE(_cs, LOW); - spixfer(addr | 0x80); // make sure top bit is set - spixfer(data); + #ifdef TARGET_LPC1768 + DELAY_CYCLES(_spi_speed); + #endif + + spiTransfer(addr | 0x80); // make sure top bit is set + spiTransfer(data); if (_sclk == TERN(LARGE_PINMAP, -1UL, -1)) SPI.endTransaction(); @@ -480,21 +462,38 @@ void MAX31865::writeRegister8(uint8_t addr, uint8_t data) { * @param x an 8-bit chunk of data to write * @return the 8-bit response */ -uint8_t MAX31865::spixfer(uint8_t x) { +uint8_t MAX31865::spiTransfer(uint8_t x) { if (_sclk == TERN(LARGE_PINMAP, -1UL, -1)) return SPI.transfer(x); - uint8_t reply = 0; - for (int i = 7; i >= 0; i--) { - reply <<= 1; - WRITE(_sclk, HIGH); - WRITE(_mosi, x & (1 << i)); - WRITE(_sclk, LOW); - if (READ(_miso)) - reply |= 1; - } + #ifdef TARGET_LPC1768 + return swSpiTransfer(x, _spi_speed, _sclk, _miso, _mosi); + #else + uint8_t reply = 0; + for (int i = 7; i >= 0; i--) { + WRITE(_sclk, HIGH); DELAY_NS_VAR(_spi_delay); + reply <<= 1; + WRITE(_mosi, x & _BV(i)); DELAY_NS_VAR(_spi_delay); + if (READ(_miso)) reply |= 1; + WRITE(_sclk, LOW); DELAY_NS_VAR(_spi_delay); + } + return reply; + #endif +} - return reply; +void MAX31865::softSpiBegin(const uint8_t spi_speed) { + #ifdef MAX31865_DEBUG + SERIAL_ECHOLNPGM("Initializing MAX31865 Software SPI"); + #endif + #ifdef TARGET_LPC1768 + swSpiBegin(_sclk, _miso, _mosi); + _spi_speed = swSpiInit(spi_speed, _sclk, _mosi); + #else + _spi_delay = (100UL << spi_speed) / 3; // Calculate delay in ns. Top speed is ~10MHz, or 100ns delay between bits. + OUT_WRITE(_sclk, LOW); + SET_OUTPUT(_mosi); + SET_INPUT(_miso); + #endif } #endif // HAS_MAX31865 && !USE_ADAFRUIT_MAX31865 diff --git a/Marlin/src/libs/MAX31865.h b/Marlin/src/libs/MAX31865.h index 5d50e870ecd2a..7610924c2313c 100644 --- a/Marlin/src/libs/MAX31865.h +++ b/Marlin/src/libs/MAX31865.h @@ -90,6 +90,13 @@ class MAX31865 { static SPISettings spiConfig; TERN(LARGE_PINMAP, uint32_t, uint8_t) _sclk, _miso, _mosi, _cs; + + #ifdef TARGET_LPC1768 + uint8_t _spi_speed; + #else + uint16_t _spi_delay; + #endif + float Rzero, Rref; void setConfig(uint8_t config, bool enable); @@ -99,7 +106,9 @@ class MAX31865 { uint16_t readRegister16(uint8_t addr); void writeRegister8(uint8_t addr, uint8_t reg); - uint8_t spixfer(uint8_t addr); + uint8_t spiTransfer(uint8_t addr); + + void softSpiBegin(const uint8_t spi_speed); public: #ifdef LARGE_PINMAP diff --git a/buildroot/tests/LPC1769 b/buildroot/tests/LPC1769 index f0dab630e5e53..3fe99734ca6b0 100755 --- a/buildroot/tests/LPC1769 +++ b/buildroot/tests/LPC1769 @@ -14,11 +14,12 @@ exec_test $1 $2 "Azteeg X5GT Example Configuration" "$3" restore_configs opt_set MOTHERBOARD BOARD_SMOOTHIEBOARD \ - EXTRUDERS 2 TEMP_SENSOR_1 -1 TEMP_SENSOR_BED 5 \ + EXTRUDERS 2 TEMP_SENSOR_0 -5 TEMP_SENSOR_1 -1 TEMP_SENSOR_BED 5 TEMP_0_CS_PIN P1_29 \ GRID_MAX_POINTS_X 16 \ NOZZLE_CLEAN_START_POINT "{ { 10, 10, 3 }, { 10, 10, 3 } }" \ NOZZLE_CLEAN_END_POINT "{ { 10, 20, 3 }, { 10, 20, 3 } }" opt_enable TFTGLCD_PANEL_SPI SDSUPPORT ADAPTIVE_FAN_SLOWING NO_FAN_SLOWING_IN_PID_TUNING \ + MAX31865_SENSOR_OHMS_0 MAX31865_CALIBRATION_OHMS_0 \ FIX_MOUNTED_PROBE AUTO_BED_LEVELING_BILINEAR G29_RETRY_AND_RECOVER Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE \ BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET LEVEL_CORNERS_USE_PROBE LEVEL_CORNERS_VERIFY_RAISED \ PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE SLOW_PWM_HEATERS PIDTEMPBED EEPROM_SETTINGS INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT \ diff --git a/buildroot/tests/teensy41 b/buildroot/tests/teensy41 index fd89512ea57bc..1affd7c89e125 100755 --- a/buildroot/tests/teensy41 +++ b/buildroot/tests/teensy41 @@ -15,12 +15,13 @@ exec_test $1 $2 "Teensy4.1 with default config" "$3" # restore_configs opt_set MOTHERBOARD BOARD_TEENSY41 \ - EXTRUDERS 2 TEMP_SENSOR_0 1 TEMP_SENSOR_1 5 TEMP_SENSOR_BED 1 \ + EXTRUDERS 2 TEMP_SENSOR_0 -5 TEMP_SENSOR_1 5 TEMP_SENSOR_BED 1 TEMP_0_CS_PIN 23 \ I2C_SLAVE_ADDRESS 63 \ GRID_MAX_POINTS_X 16 \ NOZZLE_CLEAN_START_POINT "{ { 10, 10, 3 }, { 10, 10, 3 } }" \ NOZZLE_CLEAN_END_POINT "{ { 10, 20, 3 }, { 10, 20, 3 } }" -opt_enable EXTENSIBLE_UI LCD_INFO_MENU SDSUPPORT SDCARD_SORT_ALPHA \ +opt_enable MAX31865_SENSOR_OHMS_0 MAX31865_CALIBRATION_OHMS_0 \ + EXTENSIBLE_UI LCD_INFO_MENU SDSUPPORT SDCARD_SORT_ALPHA \ FILAMENT_LCD_DISPLAY CALIBRATION_GCODE BAUD_RATE_GCODE \ FIX_MOUNTED_PROBE Z_SAFE_HOMING AUTO_BED_LEVELING_BILINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE \ BABYSTEPPING BABYSTEP_XY BABYSTEP_ZPROBE_OFFSET \