Standardize Marlin SPI (part 1) (#19989)

This commit is contained in:
Victor Oliveira 2020-11-07 00:07:15 -03:00 committed by Scott Lahteine
parent e49f267c4a
commit 2dd1522e30
17 changed files with 522 additions and 53 deletions

View file

@ -83,6 +83,7 @@ jobs:
- STM32F103RET6_creality - STM32F103RET6_creality
- LERDGEX - LERDGEX
- mks_robin_nano35 - mks_robin_nano35
- mks_robin_nano35_stm32
- NUCLEO_F767ZI - NUCLEO_F767ZI
# Put lengthy tests last # Put lengthy tests last

View file

@ -127,11 +127,9 @@
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]); 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 // Read single byte from SPI
uint8_t spiRec() { return doio(0xFF); } uint8_t spiRec() { return doio(0xFF); }
@ -143,9 +141,7 @@
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF); for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
} }
uint8_t spiTransfer(uint8_t b) { uint8_t spiTransfer(uint8_t b) { return doio(b); }
return doio(b);
}
// Write from buffer to SPI // Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t* buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
@ -201,6 +197,15 @@ SPIClass::SPIClass(uint8_t device) {
GPDMA_Init(); 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() { void SPIClass::begin() {
// Init the SPI pins in the first begin call // Init the SPI pins in the first begin call
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) || 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); for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
} }
void SPIClass::setClock(uint32_t clock) { void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
_currentSetting->clock = clock;
}
void SPIClass::setModule(uint8_t device) { void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
_currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
}
void SPIClass::setBitOrder(uint8_t bitOrder) { void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
_currentSetting->bitOrder = bitOrder;
}
void SPIClass::setDataMode(uint8_t dataMode) { void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
_currentSetting->dataMode = dataMode;
}
void SPIClass::setDataSize(uint32_t ds) { void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
_currentSetting->dataSize = ds;
}
/** /**
* Set up/tear down * Set up/tear down

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <SPI.h>
/**
* 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;

View file

@ -126,6 +126,11 @@ public:
*/ */
SPIClass(uint8_t spiPortNumber); 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 * Select and configure the current selected SPI device to use
*/ */

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
#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;
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "HAL.h"
#include <SPI.h>
extern "C" {
#include <utility/spi_com.h>
}
/**
* 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;
};

View file

@ -105,7 +105,7 @@ void SetTimerInterruptPriorities();
// FORCE_INLINE because these are used in performance-critical situations // FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) { 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) { 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; return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <SPI.h>
/**
* 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;

View file

@ -147,6 +147,18 @@ SPIClass::SPIClass(uint32_t spi_num) {
_currentSetting->state = SPI_STATE_IDLE; _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 * Set up/tear down
*/ */

View file

@ -163,6 +163,11 @@ public:
*/ */
SPIClass(uint32_t spiPortNumber); 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). * @brief Equivalent to begin(SPI_1_125MHZ, MSBFIRST, 0).
*/ */

View file

@ -32,7 +32,12 @@
/** /**
* lcd_put_u8str_ind_P * 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*/) { 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; uint8_t *p = (uint8_t*)pstr;

View file

@ -44,21 +44,21 @@ void TFT_String::set_font(const uint8_t *font) {
for (glyph = 0; glyph < 256; glyph++) glyphs[glyph] = nullptr; for (glyph = 0; glyph < 256; glyph++) glyphs[glyph] = nullptr;
DEBUG_ECHOLNPAIR("Format: ", font_header->Format); DEBUG_ECHOLNPAIR("Format: ", font_header->Format);
DEBUG_ECHOLNPAIR("BBXWidth: ", font_header->BBXWidth); DEBUG_ECHOLNPAIR("BBXWidth: ", font_header->BBXWidth);
DEBUG_ECHOLNPAIR("BBXHeight: ", font_header->BBXHeight); DEBUG_ECHOLNPAIR("BBXHeight: ", font_header->BBXHeight);
DEBUG_ECHOLNPAIR("BBXOffsetX: ", font_header->BBXOffsetX); DEBUG_ECHOLNPAIR("BBXOffsetX: ", font_header->BBXOffsetX);
DEBUG_ECHOLNPAIR("BBXOffsetY: ", font_header->BBXOffsetY); DEBUG_ECHOLNPAIR("BBXOffsetY: ", font_header->BBXOffsetY);
DEBUG_ECHOLNPAIR("CapitalAHeight: ", font_header->CapitalAHeight); DEBUG_ECHOLNPAIR("CapitalAHeight: ", font_header->CapitalAHeight);
DEBUG_ECHOLNPAIR("Encoding65Pos: ", font_header->Encoding65Pos); DEBUG_ECHOLNPAIR("Encoding65Pos: ", font_header->Encoding65Pos);
DEBUG_ECHOLNPAIR("Encoding97Pos: ", font_header->Encoding97Pos); DEBUG_ECHOLNPAIR("Encoding97Pos: ", font_header->Encoding97Pos);
DEBUG_ECHOLNPAIR("FontStartEncoding: ", font_header->FontStartEncoding); DEBUG_ECHOLNPAIR("FontStartEncoding: ", font_header->FontStartEncoding);
DEBUG_ECHOLNPAIR("FontEndEncoding: ", font_header->FontEndEncoding); DEBUG_ECHOLNPAIR("FontEndEncoding: ", font_header->FontEndEncoding);
DEBUG_ECHOLNPAIR("LowerGDescent: ", font_header->LowerGDescent); DEBUG_ECHOLNPAIR("LowerGDescent: ", font_header->LowerGDescent);
DEBUG_ECHOLNPAIR("FontAscent: ", font_header->FontAscent); DEBUG_ECHOLNPAIR("FontAscent: ", font_header->FontAscent);
DEBUG_ECHOLNPAIR("FontDescent: ", font_header->FontDescent); DEBUG_ECHOLNPAIR("FontDescent: ", font_header->FontDescent);
DEBUG_ECHOLNPAIR("FontXAscent: ", font_header->FontXAscent); DEBUG_ECHOLNPAIR("FontXAscent: ", font_header->FontXAscent);
DEBUG_ECHOLNPAIR("FontXDescent: ", font_header->FontXDescent); DEBUG_ECHOLNPAIR("FontXDescent: ", font_header->FontXDescent);
add_glyphs(font); add_glyphs(font);
} }
@ -72,9 +72,8 @@ void TFT_String::add_glyphs(const uint8_t *font) {
glyphs[glyph] = (glyph_t *)pointer; glyphs[glyph] = (glyph_t *)pointer;
pointer += sizeof(glyph_t) + ((glyph_t *)pointer)->DataSize; pointer += sizeof(glyph_t) + ((glyph_t *)pointer)->DataSize;
} }
else { else
pointer++; pointer++;
}
} }
} }
@ -86,6 +85,13 @@ void TFT_String::set() {
uint8_t read_byte(uint8_t *byte) { return *byte; } 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) { void TFT_String::add(uint8_t *string, int8_t index, uint8_t *itemString) {
wchar_t wchar; wchar_t wchar;

View file

@ -25,7 +25,6 @@
#if HAS_SPI_FLASH #if HAS_SPI_FLASH
#include "W25Qxx.h" #include "W25Qxx.h"
#include <SPI.h>
W25QXXFlash W25QXX; W25QXXFlash W25QXX;
@ -41,6 +40,11 @@ W25QXXFlash W25QXX;
#ifndef SPI_FLASH_CS_PIN #ifndef SPI_FLASH_CS_PIN
#define SPI_FLASH_CS_PIN W25QXX_CS_PIN #define SPI_FLASH_CS_PIN W25QXX_CS_PIN
#endif #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_H OUT_WRITE(SPI_FLASH_CS_PIN, HIGH)
#define W25QXX_CS_L OUT_WRITE(SPI_FLASH_CS_PIN, LOW) #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; case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2;// Default from the SPI library default: clock = SPI_CLOCK_DIV2;// Default from the SPI library
} }
SPI.setModule(SPI_DEVICE);
SPI.begin(); mySPI.setClockDivider(clock);
SPI.setClockDivider(clock); mySPI.setBitOrder(MSBFIRST);
SPI.setBitOrder(MSBFIRST); mySPI.setDataMode(SPI_MODE0);
SPI.setDataMode(SPI_MODE0); mySPI.begin();
} }
/** /**
@ -82,12 +86,12 @@ void W25QXXFlash::init(uint8_t spiRate) {
* @return Byte received * @return Byte received
*/ */
uint8_t W25QXXFlash::spi_flash_Rec() { uint8_t W25QXXFlash::spi_flash_Rec() {
const uint8_t returnByte = SPI.transfer(0xFF); const uint8_t returnByte = mySPI.transfer(0xFF);
return returnByte; return returnByte;
} }
uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) { 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; return returnByte;
} }
@ -100,7 +104,9 @@ uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
* *
* @details Uses DMA * @details Uses DMA
*/ */
void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) { SPI.dmaTransfer(0, const_cast<uint8_t*>(buf), nbyte); } void W25QXXFlash::spi_flash_Read(uint8_t* buf, uint16_t nbyte) {
mySPI.dmaTransfer(0, const_cast<uint8_t*>(buf), nbyte);
}
/** /**
* @brief Send a single byte on SPI port * @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 * @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) * @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 * @details Use DMA
*/ */
void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t* buf) { void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t* buf) {
SPI.send(token); mySPI.transfer(token);
SPI.dmaSend(const_cast<uint8_t*>(buf), 512); mySPI.dmaSend(const_cast<uint8_t*>(buf), 512);
} }
uint16_t W25QXXFlash::W25QXX_ReadID(void) { uint16_t W25QXXFlash::W25QXX_ReadID(void) {

View file

@ -23,6 +23,8 @@
#include <stdint.h> #include <stdint.h>
#include HAL_PATH(../HAL, MarlinSPI.h)
#define W25X_WriteEnable 0x06 #define W25X_WriteEnable 0x06
#define W25X_WriteDisable 0x04 #define W25X_WriteDisable 0x04
#define W25X_ReadStatusReg 0x05 #define W25X_ReadStatusReg 0x05
@ -49,6 +51,8 @@
#define SPI_FLASH_PerWritePageSize 256 #define SPI_FLASH_PerWritePageSize 256
class W25QXXFlash { class W25QXXFlash {
private:
static MarlinSPI mySPI;
public: public:
void init(uint8_t spiRate); void init(uint8_t spiRate);
static uint8_t spi_flash_Rec(); static uint8_t spi_flash_Rec();

View file

@ -191,6 +191,9 @@
#define FSMC_DMA_DEV DMA2 #define FSMC_DMA_DEV DMA2
#define FSMC_DMA_CHANNEL DMA_CH5 #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
#define TOUCH_BUTTONS_HW_SPI_DEVICE 2 #define TOUCH_BUTTONS_HW_SPI_DEVICE 2

View file

@ -15,7 +15,7 @@ opt_set MOTHERBOARD BOARD_MKS_ROBIN_NANO
exec_test $1 $2 "MKS Robin nano v1.2 Emulated DOGM FSMC" 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) # (Robin v2 nano has no FSMC interface)
# #
use_example_configs Mks/Robin use_example_configs Mks/Robin

View file

@ -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