diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml
index 9624733838..41b3047485 100644
--- a/.github/workflows/test-builds.yml
+++ b/.github/workflows/test-builds.yml
@@ -83,6 +83,7 @@ jobs:
- STM32F103RET6_creality
- LERDGEX
- mks_robin_nano35
+ - mks_robin_nano35_stm32
- NUCLEO_F767ZI
# Put lengthy tests last
diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
index b800721c5a..16ac789fc0 100644
--- a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
@@ -127,11 +127,9 @@
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
}
- void spiSend(uint32_t chan, byte b) {
- }
+ void spiSend(uint32_t chan, byte b) {}
- void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
- }
+ void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {}
// Read single byte from SPI
uint8_t spiRec() { return doio(0xFF); }
@@ -143,9 +141,7 @@
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
}
- uint8_t spiTransfer(uint8_t b) {
- return doio(b);
- }
+ uint8_t spiTransfer(uint8_t b) { return doio(b); }
// Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t* buf) {
@@ -201,6 +197,15 @@ SPIClass::SPIClass(uint8_t device) {
GPDMA_Init();
}
+SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
+ #if BOARD_NR_SPI >= 1
+ if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
+ #endif
+ #if BOARD_NR_SPI >= 2
+ if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
+ #endif
+}
+
void SPIClass::begin() {
// Init the SPI pins in the first begin call
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
@@ -331,25 +336,15 @@ void SPIClass::read(uint8_t *buf, uint32_t len) {
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
}
-void SPIClass::setClock(uint32_t clock) {
- _currentSetting->clock = clock;
-}
+void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
-void SPIClass::setModule(uint8_t device) {
- _currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
-}
+void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
-void SPIClass::setBitOrder(uint8_t bitOrder) {
- _currentSetting->bitOrder = bitOrder;
-}
+void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
-void SPIClass::setDataMode(uint8_t dataMode) {
- _currentSetting->dataMode = dataMode;
-}
+void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
-void SPIClass::setDataSize(uint32_t ds) {
- _currentSetting->dataSize = ds;
-}
+void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
/**
* Set up/tear down
diff --git a/Marlin/src/HAL/LPC1768/MarlinSPI.h b/Marlin/src/HAL/LPC1768/MarlinSPI.h
new file mode 100644
index 0000000000..fab245f904
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/MarlinSPI.h
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 3 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 .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/LPC1768/include/SPI.h b/Marlin/src/HAL/LPC1768/include/SPI.h
index ffcd87fe96..ecd91f6a3b 100644
--- a/Marlin/src/HAL/LPC1768/include/SPI.h
+++ b/Marlin/src/HAL/LPC1768/include/SPI.h
@@ -126,6 +126,11 @@ public:
*/
SPIClass(uint8_t spiPortNumber);
+ /**
+ * Init using pins
+ */
+ SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)-1);
+
/**
* Select and configure the current selected SPI device to use
*/
diff --git a/Marlin/src/HAL/STM32/MarlinSPI.cpp b/Marlin/src/HAL/STM32/MarlinSPI.cpp
new file mode 100644
index 0000000000..fd05b1aeb4
--- /dev/null
+++ b/Marlin/src/HAL/STM32/MarlinSPI.cpp
@@ -0,0 +1,161 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 3 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 .
+ *
+ */
+
+#include "MarlinSPI.h"
+
+static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, uint32_t dataSize) {
+ spi_init(obj, speed, mode, msb);
+ // spi_init set 8bit always
+ // TODO: copy the code from spi_init and handle data size, to avoid double init always!!
+ if (dataSize != SPI_DATASIZE_8BIT) {
+ obj->handle.Init.DataSize = dataSize;
+ HAL_SPI_Init(&obj->handle);
+ __HAL_SPI_ENABLE(&obj->handle);
+ }
+}
+
+void MarlinSPI::setClockDivider(uint8_t _div) {
+ _speed = spi_getClkFreq(&_spi);// / _div;
+ _clockDivider = _div;
+}
+
+void MarlinSPI::begin(void) {
+ //TODO: only call spi_init if any parameter changed!!
+ spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
+}
+
+void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
+ _dmaHandle.Init.Direction = direction;
+ _dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
+ _dmaHandle.Init.Mode = DMA_NORMAL;
+ _dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
+ _dmaHandle.Init.MemInc = minc ? DMA_MINC_ENABLE : DMA_MINC_DISABLE;
+
+ if (_dataSize == DATA_SIZE_8BIT) {
+ _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
+ _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
+ }
+ else {
+ _dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
+ _dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
+ }
+ #ifdef STM32F4xx
+ _dmaHandle.Init.Channel = DMA_CHANNEL_3;
+ _dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
+ #endif
+
+ // start DMA hardware
+ // TODO: check if hardware is already enabled
+ #ifdef SPI1_BASE
+ if (_spiHandle.Instance == SPI1) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel3 : DMA1_Channel2;
+ #elif defined(STM32F4xx)
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ _dmaHandle.Instance = DMA2_Stream3;
+ #endif
+ }
+ #endif
+ #ifdef SPI2_BASE
+ if (_spiHandle.Instance == SPI2) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA1_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA1_Channel5 : DMA1_Channel4;
+ #elif defined(STM32F4xx)
+ //TODO: f4 dma config
+ #endif
+ }
+ #endif
+ #ifdef SPI3_BASE
+ if (_spiHandle.Instance == SPI3) {
+ #ifdef STM32F1xx
+ __HAL_RCC_DMA2_CLK_ENABLE();
+ _dmaHandle.Instance = (direction == DMA_MEMORY_TO_PERIPH) ? DMA2_Channel2 : DMA2_Channel1;
+ #elif defined(STM32F4xx)
+ //TODO: f4 dma config
+ #endif
+ }
+ #endif
+
+ HAL_DMA_Init(&_dmaHandle);
+}
+
+byte MarlinSPI::transfer(uint8_t _data) {
+ uint8_t rxData = 0xFF;
+ HAL_SPI_TransmitReceive(&_spi.handle, &_data, &rxData, 1, HAL_MAX_DELAY);
+ return rxData;
+}
+
+uint8_t MarlinSPI::dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length) {
+ const uint8_t ff = 0xFF;
+
+ //if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE) //only enable if disabled
+ __HAL_SPI_ENABLE(&_spi.handle);
+
+ if (receiveBuf) {
+ setupDma(_spi.handle, _dmaRx, DMA_PERIPH_TO_MEMORY, true);
+ HAL_DMA_Start(&_dmaRx, (uint32_t)&(_spi.handle.Instance->DR), (uint32_t)receiveBuf, length);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_RXDMAEN); /* Enable Rx DMA Request */
+ }
+
+ // check for 2 lines transfer
+ bool mincTransmit = true;
+ if (transmitBuf == nullptr && _spi.handle.Init.Direction == SPI_DIRECTION_2LINES && _spi.handle.Init.Mode == SPI_MODE_MASTER) {
+ transmitBuf = &ff;
+ mincTransmit = false;
+ }
+
+ if (transmitBuf) {
+ setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, mincTransmit);
+ HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
+ }
+
+ if (transmitBuf) {
+ HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaTx);
+ HAL_DMA_DeInit(&_dmaTx);
+ }
+
+ // while ((_spi.handle.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
+
+ if (receiveBuf) {
+ HAL_DMA_PollForTransfer(&_dmaRx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaRx);
+ HAL_DMA_DeInit(&_dmaRx);
+ }
+
+ return 1;
+}
+
+uint8_t MarlinSPI::dmaSend(const void * transmitBuf, uint16_t length, bool minc) {
+ setupDma(_spi.handle, _dmaTx, DMA_MEMORY_TO_PERIPH, minc);
+ HAL_DMA_Start(&_dmaTx, (uint32_t)transmitBuf, (uint32_t)&(_spi.handle.Instance->DR), length);
+ __HAL_SPI_ENABLE(&_spi.handle);
+ SET_BIT(_spi.handle.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
+ HAL_DMA_PollForTransfer(&_dmaTx, HAL_DMA_FULL_TRANSFER, HAL_MAX_DELAY);
+ HAL_DMA_Abort(&_dmaTx);
+ // DeInit objects
+ HAL_DMA_DeInit(&_dmaTx);
+ return 1;
+}
diff --git a/Marlin/src/HAL/STM32/MarlinSPI.h b/Marlin/src/HAL/STM32/MarlinSPI.h
new file mode 100644
index 0000000000..fbd3585ff4
--- /dev/null
+++ b/Marlin/src/HAL/STM32/MarlinSPI.h
@@ -0,0 +1,107 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 3 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 .
+ *
+ */
+#pragma once
+
+#include "HAL.h"
+#include
+
+extern "C" {
+ #include
+}
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+#define DATA_SIZE_8BIT SPI_DATASIZE_8BIT
+#define DATA_SIZE_16BIT SPI_DATASIZE_16BIT
+
+class MarlinSPI {
+public:
+ MarlinSPI() : MarlinSPI(NC, NC, NC, NC) {}
+
+ MarlinSPI(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel = (pin_t)NC) : _mosiPin(mosi), _misoPin(miso), _sckPin(sclk), _ssPin(ssel) {
+ _spi.pin_miso = digitalPinToPinName(_misoPin);
+ _spi.pin_mosi = digitalPinToPinName(_mosiPin);
+ _spi.pin_sclk = digitalPinToPinName(_sckPin);
+ _spi.pin_ssel = digitalPinToPinName(_ssPin);
+ _dataSize = DATA_SIZE_8BIT;
+ _bitOrder = MSBFIRST;
+ _dataMode = SPI_MODE_0;
+ _spi.handle.State = HAL_SPI_STATE_RESET;
+ setClockDivider(SPI_SPEED_CLOCK_DIV2_MHZ);
+ }
+
+ void begin(void);
+ void end(void) {}
+
+ byte transfer(uint8_t _data);
+ uint8_t dmaTransfer(const void *transmitBuf, void *receiveBuf, uint16_t length);
+ uint8_t dmaSend(const void * transmitBuf, uint16_t length, bool minc = true);
+
+ /* These methods are deprecated and kept for compatibility.
+ * Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
+ */
+ void setBitOrder(BitOrder _order) { _bitOrder = _order; }
+
+ void setDataMode(uint8_t _mode) {
+ switch (_mode) {
+ case SPI_MODE0: _dataMode = SPI_MODE_0; break;
+ case SPI_MODE1: _dataMode = SPI_MODE_1; break;
+ case SPI_MODE2: _dataMode = SPI_MODE_2; break;
+ case SPI_MODE3: _dataMode = SPI_MODE_3; break;
+ }
+ }
+
+ void setClockDivider(uint8_t _div);
+
+private:
+ void setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc = false);
+
+ spi_t _spi;
+ DMA_HandleTypeDef _dmaTx;
+ DMA_HandleTypeDef _dmaRx;
+ BitOrder _bitOrder;
+ spi_mode_e _dataMode;
+ uint8_t _clockDivider;
+ uint32_t _speed;
+ uint32_t _dataSize;
+ pin_t _mosiPin;
+ pin_t _misoPin;
+ pin_t _sckPin;
+ pin_t _ssPin;
+};
diff --git a/Marlin/src/HAL/STM32/timers.h b/Marlin/src/HAL/STM32/timers.h
index 2bf70fc0fa..4649824303 100644
--- a/Marlin/src/HAL/STM32/timers.h
+++ b/Marlin/src/HAL/STM32/timers.h
@@ -105,7 +105,7 @@ void SetTimerInterruptPriorities();
// FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
- return timer_instance[timer_num] != NULL;
+ return timer_instance[timer_num] != nullptr;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;
diff --git a/Marlin/src/HAL/STM32F1/MarlinSPI.h b/Marlin/src/HAL/STM32F1/MarlinSPI.h
new file mode 100644
index 0000000000..fab245f904
--- /dev/null
+++ b/Marlin/src/HAL/STM32F1/MarlinSPI.h
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * 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 3 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 .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/STM32F1/SPI.cpp b/Marlin/src/HAL/STM32F1/SPI.cpp
index ef00b407a8..8995109238 100644
--- a/Marlin/src/HAL/STM32F1/SPI.cpp
+++ b/Marlin/src/HAL/STM32F1/SPI.cpp
@@ -147,6 +147,18 @@ SPIClass::SPIClass(uint32_t spi_num) {
_currentSetting->state = SPI_STATE_IDLE;
}
+SPIClass::SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel) {
+ #if BOARD_NR_SPI >= 1
+ if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
+ #endif
+ #if BOARD_NR_SPI >= 2
+ if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
+ #endif
+ #if BOARD_NR_SPI >= 3
+ if (mosi == BOARD_SPI3_MOSI_PIN) SPIClass(3);
+ #endif
+}
+
/**
* Set up/tear down
*/
diff --git a/Marlin/src/HAL/STM32F1/SPI.h b/Marlin/src/HAL/STM32F1/SPI.h
index 0d20a46577..828644f1dd 100644
--- a/Marlin/src/HAL/STM32F1/SPI.h
+++ b/Marlin/src/HAL/STM32F1/SPI.h
@@ -163,6 +163,11 @@ public:
*/
SPIClass(uint32_t spiPortNumber);
+ /**
+ * Init using pins
+ */
+ SPIClass(int8_t mosi, int8_t miso, int8_t sclk, int8_t ssel=-1);
+
/**
* @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
*/
diff --git a/Marlin/src/lcd/lcdprint.cpp b/Marlin/src/lcd/lcdprint.cpp
index e381c590f5..6781b81d7c 100644
--- a/Marlin/src/lcd/lcdprint.cpp
+++ b/Marlin/src/lcd/lcdprint.cpp
@@ -32,7 +32,12 @@
/**
* lcd_put_u8str_ind_P
- * Print a string with an index substituted within it
+ *
+ * Print a string with an index substituted within it:
+ *
+ * = displays '0'....'10' for indexes 0 - 10
+ * ~ displays '1'....'11' for indexes 0 - 10
+ * * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
*/
lcd_uint_t lcd_put_u8str_ind_P(PGM_P const pstr, const int8_t ind, PGM_P const inStr/*=nullptr*/, const lcd_uint_t maxlen/*=LCD_WIDTH*/) {
uint8_t *p = (uint8_t*)pstr;
diff --git a/Marlin/src/lcd/tft/tft_string.cpp b/Marlin/src/lcd/tft/tft_string.cpp
index b707596bb3..eb805ac423 100644
--- a/Marlin/src/lcd/tft/tft_string.cpp
+++ b/Marlin/src/lcd/tft/tft_string.cpp
@@ -44,21 +44,21 @@ void TFT_String::set_font(const uint8_t *font) {
for (glyph = 0; glyph < 256; glyph++) glyphs[glyph] = nullptr;
- DEBUG_ECHOLNPAIR("Format: ", font_header->Format);
- DEBUG_ECHOLNPAIR("BBXWidth: ", font_header->BBXWidth);
- DEBUG_ECHOLNPAIR("BBXHeight: ", font_header->BBXHeight);
- DEBUG_ECHOLNPAIR("BBXOffsetX: ", font_header->BBXOffsetX);
- DEBUG_ECHOLNPAIR("BBXOffsetY: ", font_header->BBXOffsetY);
- DEBUG_ECHOLNPAIR("CapitalAHeight: ", font_header->CapitalAHeight);
- DEBUG_ECHOLNPAIR("Encoding65Pos: ", font_header->Encoding65Pos);
- DEBUG_ECHOLNPAIR("Encoding97Pos: ", font_header->Encoding97Pos);
+ DEBUG_ECHOLNPAIR("Format: ", font_header->Format);
+ DEBUG_ECHOLNPAIR("BBXWidth: ", font_header->BBXWidth);
+ DEBUG_ECHOLNPAIR("BBXHeight: ", font_header->BBXHeight);
+ DEBUG_ECHOLNPAIR("BBXOffsetX: ", font_header->BBXOffsetX);
+ DEBUG_ECHOLNPAIR("BBXOffsetY: ", font_header->BBXOffsetY);
+ DEBUG_ECHOLNPAIR("CapitalAHeight: ", font_header->CapitalAHeight);
+ DEBUG_ECHOLNPAIR("Encoding65Pos: ", font_header->Encoding65Pos);
+ DEBUG_ECHOLNPAIR("Encoding97Pos: ", font_header->Encoding97Pos);
DEBUG_ECHOLNPAIR("FontStartEncoding: ", font_header->FontStartEncoding);
- DEBUG_ECHOLNPAIR("FontEndEncoding: ", font_header->FontEndEncoding);
- DEBUG_ECHOLNPAIR("LowerGDescent: ", font_header->LowerGDescent);
- DEBUG_ECHOLNPAIR("FontAscent: ", font_header->FontAscent);
- DEBUG_ECHOLNPAIR("FontDescent: ", font_header->FontDescent);
- DEBUG_ECHOLNPAIR("FontXAscent: ", font_header->FontXAscent);
- DEBUG_ECHOLNPAIR("FontXDescent: ", font_header->FontXDescent);
+ DEBUG_ECHOLNPAIR("FontEndEncoding: ", font_header->FontEndEncoding);
+ DEBUG_ECHOLNPAIR("LowerGDescent: ", font_header->LowerGDescent);
+ DEBUG_ECHOLNPAIR("FontAscent: ", font_header->FontAscent);
+ DEBUG_ECHOLNPAIR("FontDescent: ", font_header->FontDescent);
+ DEBUG_ECHOLNPAIR("FontXAscent: ", font_header->FontXAscent);
+ DEBUG_ECHOLNPAIR("FontXDescent: ", font_header->FontXDescent);
add_glyphs(font);
}
@@ -72,9 +72,8 @@ void TFT_String::add_glyphs(const uint8_t *font) {
glyphs[glyph] = (glyph_t *)pointer;
pointer += sizeof(glyph_t) + ((glyph_t *)pointer)->DataSize;
}
- else {
+ else
pointer++;
- }
}
}
@@ -86,6 +85,13 @@ void TFT_String::set() {
uint8_t read_byte(uint8_t *byte) { return *byte; }
+/**
+ * Add a string, applying substitutions for the following characters:
+ *
+ * = displays '0'....'10' for indexes 0 - 10
+ * ~ displays '1'....'11' for indexes 0 - 10
+ * * displays 'E1'...'E11' for indexes 0 - 10 (By default. Uses LCD_FIRST_TOOL)
+ */
void TFT_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
wchar_t wchar;
diff --git a/Marlin/src/libs/W25Qxx.cpp b/Marlin/src/libs/W25Qxx.cpp
index 03e002f66f..ebf326f2e5 100644
--- a/Marlin/src/libs/W25Qxx.cpp
+++ b/Marlin/src/libs/W25Qxx.cpp
@@ -25,7 +25,6 @@
#if HAS_SPI_FLASH
#include "W25Qxx.h"
-#include
W25QXXFlash W25QXX;
@@ -41,6 +40,11 @@ W25QXXFlash W25QXX;
#ifndef SPI_FLASH_CS_PIN
#define SPI_FLASH_CS_PIN W25QXX_CS_PIN
#endif
+#ifndef NC
+ #define NC -1
+#endif
+
+MarlinSPI W25QXXFlash::mySPI(SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN, SPI_FLASH_SCK_PIN, NC);
#define W25QXX_CS_H OUT_WRITE(SPI_FLASH_CS_PIN, HIGH)
#define W25QXX_CS_L OUT_WRITE(SPI_FLASH_CS_PIN, LOW)
@@ -69,11 +73,11 @@ void W25QXXFlash::init(uint8_t spiRate) {
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2;// Default from the SPI library
}
- SPI.setModule(SPI_DEVICE);
- SPI.begin();
- SPI.setClockDivider(clock);
- SPI.setBitOrder(MSBFIRST);
- SPI.setDataMode(SPI_MODE0);
+
+ mySPI.setClockDivider(clock);
+ mySPI.setBitOrder(MSBFIRST);
+ mySPI.setDataMode(SPI_MODE0);
+ mySPI.begin();
}
/**
@@ -82,12 +86,12 @@ void W25QXXFlash::init(uint8_t spiRate) {
* @return Byte received
*/
uint8_t W25QXXFlash::spi_flash_Rec() {
- const uint8_t returnByte = SPI.transfer(0xFF);
+ const uint8_t returnByte = mySPI.transfer(0xFF);
return returnByte;
}
uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
- const uint8_t returnByte = SPI.transfer(data);
+ const uint8_t returnByte = mySPI.transfer(data);
return returnByte;
}
@@ -100,7 +104,9 @@ uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
*
* @details Uses DMA
*/
-void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) { SPI.dmaTransfer(0, const_cast(buf), nbyte); }
+void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) {
+ mySPI.dmaTransfer(0, const_cast(buf), nbyte);
+}
/**
* @brief Send a single byte on SPI port
@@ -109,7 +115,7 @@ void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) { SPI.dmaTransfer
*
* @details
*/
-void W25QXXFlash::spi_flash_Send(uint8_t b) { SPI.send(b); }
+void W25QXXFlash::spi_flash_Send(uint8_t b) { mySPI.transfer(b); }
/**
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
@@ -120,8 +126,8 @@ void W25QXXFlash::spi_flash_Send(uint8_t b) { SPI.send(b); }
* @details Use DMA
*/
void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t* buf) {
- SPI.send(token);
- SPI.dmaSend(const_cast(buf), 512);
+ mySPI.transfer(token);
+ mySPI.dmaSend(const_cast(buf), 512);
}
uint16_t W25QXXFlash::W25QXX_ReadID(void) {
diff --git a/Marlin/src/libs/W25Qxx.h b/Marlin/src/libs/W25Qxx.h
index ac3e8a169b..eddae6b1f2 100644
--- a/Marlin/src/libs/W25Qxx.h
+++ b/Marlin/src/libs/W25Qxx.h
@@ -23,6 +23,8 @@
#include
+#include HAL_PATH(../HAL, MarlinSPI.h)
+
#define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg 0x05
@@ -49,6 +51,8 @@
#define SPI_FLASH_PerWritePageSize 256
class W25QXXFlash {
+private:
+ static MarlinSPI mySPI;
public:
void init(uint8_t spiRate);
static uint8_t spi_flash_Rec();
diff --git a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h
index 5c3dfc2ad8..e7e583a6f5 100644
--- a/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h
+++ b/Marlin/src/pins/stm32f1/pins_MKS_ROBIN_NANO.h
@@ -191,6 +191,9 @@
#define FSMC_DMA_DEV DMA2
#define FSMC_DMA_CHANNEL DMA_CH5
+ #define TFT_CS_PIN FSMC_CS_PIN
+ #define TFT_RS_PIN FSMC_RS_PIN
+
#define TOUCH_BUTTONS_HW_SPI
#define TOUCH_BUTTONS_HW_SPI_DEVICE 2
diff --git a/buildroot/tests/mks_robin_nano35-tests b/buildroot/tests/mks_robin_nano35-tests
index d67fa516b8..426f29d473 100644
--- a/buildroot/tests/mks_robin_nano35-tests
+++ b/buildroot/tests/mks_robin_nano35-tests
@@ -15,7 +15,7 @@ opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC"
#
-# MKS Robin v2 nano LVGL SPI
+# MKS Robin v2 nano Emulated DOGM SPI
# (Robin v2 nano has no FSMC interface)
#
use_example_configs Mks/Robin
diff --git a/buildroot/tests/mks_robin_nano35_stm32-tests b/buildroot/tests/mks_robin_nano35_stm32-tests
new file mode 100644
index 0000000000..58912b85a3
--- /dev/null
+++ b/buildroot/tests/mks_robin_nano35_stm32-tests
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+#
+# Build tests for MKS Robin nano
+# (STM32F1 genericSTM32F103VE)
+#
+
+# exit on first failure
+set -e
+
+#
+# MKS Robin nano v1.2 Emulated DOGM FSMC
+#
+use_example_configs Mks/Robin
+opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
+exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC"
+
+#
+# MKS Robin v2 nano Emulated DOGM SPI
+# (Robin v2 nano has no FSMC interface)
+#
+use_example_configs Mks/Robin
+opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
+opt_disable TFT_INTERFACE_FSMC
+opt_enable TFT_INTERFACE_SPI
+exec_test $1 $2 "MKS Robin v2 nano Emulated DOGM SPI"
+
+#
+# MKS Robin nano v1.2 LVGL FSMC
+#
+# use_example_configs Mks/Robin
+# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
+# opt_disable TFT_CLASSIC_UI TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
+# opt_enable TFT_LVGL_UI TFT_RES_480x320
+# exec_test $1 $2 "MKS Robin nano v1.2 LVGL FSMC"
+
+#
+# MKS Robin v2 nano LVGL SPI
+# (Robin v2 nano has no FSMC interface)
+#
+# use_example_configs Mks/Robin
+# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
+# opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
+# opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320
+# exec_test $1 $2 "MKS Robin v2 nano LVGL SPI"
+
+#
+# MKS Robin v2 nano New Color UI 480x320 SPI
+# (Robin v2 nano has no FSMC interface)
+#
+use_example_configs Mks/Robin
+opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
+opt_disable TFT_INTERFACE_FSMC TFT_RES_320x240
+opt_enable TFT_INTERFACE_SPI TFT_RES_480x320
+exec_test $1 $2 "MKS Robin v2 nano New Color UI 480x320 SPI"
+
+#
+# MKS Robin v2 nano LVGL SPI + TMC
+# (Robin v2 nano has no FSMC interface)
+#
+# use_example_configs Mks/Robin
+# opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO_V2
+# opt_disable TFT_INTERFACE_FSMC TFT_COLOR_UI TOUCH_SCREEN TFT_RES_320x240
+# opt_enable TFT_INTERFACE_SPI TFT_LVGL_UI TFT_RES_480x320
+# opt_set X_DRIVER_TYPE TMC2209
+# opt_set Y_DRIVER_TYPE TMC2209
+# exec_test $1 $2 "MKS Robin v2 nano LVGL SPI + TMC"
+
+# cleanup
+restore_configs