update code base to Marlin 2.0.9.2
This commit is contained in:
285
Marlin/src/libs/BL24CXX.cpp
Normal file
285
Marlin/src/libs/BL24CXX.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
/**
|
||||
* 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 "../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(IIC_BL24CXX_EEPROM)
|
||||
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "BL24CXX.h"
|
||||
#ifdef __STM32F1__
|
||||
#include <libmaple/gpio.h>
|
||||
#else
|
||||
#include "../HAL/shared/Delay.h"
|
||||
#define delay_us(n) DELAY_US(n)
|
||||
#endif
|
||||
|
||||
#ifndef EEPROM_WRITE_DELAY
|
||||
#define EEPROM_WRITE_DELAY 10
|
||||
#endif
|
||||
#ifndef EEPROM_DEVICE_ADDRESS
|
||||
#define EEPROM_DEVICE_ADDRESS (0x50 << 1)
|
||||
#endif
|
||||
|
||||
// IO direction setting
|
||||
#ifdef __STM32F1__
|
||||
#define SDA_IN() do{ PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH &= 0XFFFF0FFF; PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH |= 8 << 12; }while(0)
|
||||
#define SDA_OUT() do{ PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH &= 0XFFFF0FFF; PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH |= 3 << 12; }while(0)
|
||||
#elif STM32F1
|
||||
#define SDA_IN() SET_INPUT(IIC_EEPROM_SDA)
|
||||
#define SDA_OUT() SET_OUTPUT(IIC_EEPROM_SDA)
|
||||
#endif
|
||||
|
||||
// IO ops
|
||||
#define IIC_SCL_0() WRITE(IIC_EEPROM_SCL, LOW)
|
||||
#define IIC_SCL_1() WRITE(IIC_EEPROM_SCL, HIGH)
|
||||
#define IIC_SDA_0() WRITE(IIC_EEPROM_SDA, LOW)
|
||||
#define IIC_SDA_1() WRITE(IIC_EEPROM_SDA, HIGH)
|
||||
#define READ_SDA() READ(IIC_EEPROM_SDA)
|
||||
|
||||
//
|
||||
// Simple IIC interface via libmaple
|
||||
//
|
||||
|
||||
// Initialize IIC
|
||||
void IIC::init() {
|
||||
SET_OUTPUT(IIC_EEPROM_SDA);
|
||||
SET_OUTPUT(IIC_EEPROM_SCL);
|
||||
IIC_SCL_1();
|
||||
IIC_SDA_1();
|
||||
}
|
||||
|
||||
// Generate IIC start signal
|
||||
void IIC::start() {
|
||||
SDA_OUT(); // SDA line output
|
||||
IIC_SDA_1();
|
||||
IIC_SCL_1();
|
||||
delay_us(4);
|
||||
IIC_SDA_0(); // START:when CLK is high, DATA change from high to low
|
||||
delay_us(4);
|
||||
IIC_SCL_0(); // Clamp the I2C bus, ready to send or receive data
|
||||
}
|
||||
|
||||
// Generate IIC stop signal
|
||||
void IIC::stop() {
|
||||
SDA_OUT(); // SDA line output
|
||||
IIC_SCL_0();
|
||||
IIC_SDA_0(); // STOP:when CLK is high DATA change from low to high
|
||||
delay_us(4);
|
||||
IIC_SCL_1();
|
||||
IIC_SDA_1(); // Send I2C bus end signal
|
||||
delay_us(4);
|
||||
}
|
||||
|
||||
// Wait for the response signal to arrive
|
||||
// 1 = failed to receive response
|
||||
// 0 = response received
|
||||
uint8_t IIC::wait_ack() {
|
||||
uint8_t ucErrTime = 0;
|
||||
SDA_IN(); // SDA is set as input
|
||||
IIC_SDA_1(); delay_us(1);
|
||||
IIC_SCL_1(); delay_us(1);
|
||||
while (READ_SDA()) {
|
||||
if (++ucErrTime > 250) {
|
||||
stop();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
IIC_SCL_0(); // Clock output 0
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Generate ACK response
|
||||
void IIC::ack() {
|
||||
IIC_SCL_0();
|
||||
SDA_OUT();
|
||||
IIC_SDA_0();
|
||||
delay_us(2);
|
||||
IIC_SCL_1();
|
||||
delay_us(2);
|
||||
IIC_SCL_0();
|
||||
}
|
||||
|
||||
// No ACK response
|
||||
void IIC::nAck() {
|
||||
IIC_SCL_0();
|
||||
SDA_OUT();
|
||||
IIC_SDA_1();
|
||||
delay_us(2);
|
||||
IIC_SCL_1();
|
||||
delay_us(2);
|
||||
IIC_SCL_0();
|
||||
}
|
||||
|
||||
// Send one IIC byte
|
||||
// Return whether the slave responds
|
||||
// 1 = there is a response
|
||||
// 0 = no response
|
||||
void IIC::send_byte(uint8_t txd) {
|
||||
SDA_OUT();
|
||||
IIC_SCL_0(); // Pull down the clock to start data transmission
|
||||
LOOP_L_N(t, 8) {
|
||||
// IIC_SDA = (txd & 0x80) >> 7;
|
||||
if (txd & 0x80) IIC_SDA_1(); else IIC_SDA_0();
|
||||
txd <<= 1;
|
||||
delay_us(2); // All three delays are necessary for TEA5767
|
||||
IIC_SCL_1();
|
||||
delay_us(2);
|
||||
IIC_SCL_0();
|
||||
delay_us(2);
|
||||
}
|
||||
}
|
||||
|
||||
// Read 1 byte, when ack=1, send ACK, ack=0, send nACK
|
||||
uint8_t IIC::read_byte(unsigned char ack_chr) {
|
||||
unsigned char receive = 0;
|
||||
SDA_IN(); // SDA is set as input
|
||||
LOOP_L_N(i, 8) {
|
||||
IIC_SCL_0();
|
||||
delay_us(2);
|
||||
IIC_SCL_1();
|
||||
receive <<= 1;
|
||||
if (READ_SDA()) receive++;
|
||||
delay_us(1);
|
||||
}
|
||||
ack_chr ? ack() : nAck(); // Send ACK / send nACK
|
||||
return receive;
|
||||
}
|
||||
|
||||
/******************** EEPROM ********************/
|
||||
|
||||
// Initialize the IIC interface
|
||||
void BL24CXX::init() { IIC::init(); }
|
||||
|
||||
// Read a byte at the specified address
|
||||
// ReadAddr: the address to start reading
|
||||
// Return: the byte read
|
||||
uint8_t BL24CXX::readOneByte(uint16_t ReadAddr) {
|
||||
uint8_t temp = 0;
|
||||
IIC::start();
|
||||
if (EE_TYPE > BL24C16) {
|
||||
IIC::send_byte(EEPROM_DEVICE_ADDRESS); // Send write command
|
||||
IIC::wait_ack();
|
||||
IIC::send_byte(ReadAddr >> 8); // Send high address
|
||||
IIC::wait_ack();
|
||||
}
|
||||
else
|
||||
IIC::send_byte(EEPROM_DEVICE_ADDRESS + ((ReadAddr >> 8) << 1)); // Send device address 0xA0, write data
|
||||
|
||||
IIC::wait_ack();
|
||||
IIC::send_byte(ReadAddr & 0xFF); // Send low address
|
||||
IIC::wait_ack();
|
||||
IIC::start();
|
||||
IIC::send_byte(EEPROM_DEVICE_ADDRESS | 0x01); // Send byte
|
||||
IIC::wait_ack();
|
||||
temp = IIC::read_byte(0);
|
||||
IIC::stop(); // Generate a stop condition
|
||||
return temp;
|
||||
}
|
||||
|
||||
// Write a data at the address specified by BL24CXX
|
||||
// WriteAddr: The destination address for writing data
|
||||
// DataToWrite: the data to be written
|
||||
void BL24CXX::writeOneByte(uint16_t WriteAddr, uint8_t DataToWrite) {
|
||||
IIC::start();
|
||||
if (EE_TYPE > BL24C16) {
|
||||
IIC::send_byte(EEPROM_DEVICE_ADDRESS); // Send write command
|
||||
IIC::wait_ack();
|
||||
IIC::send_byte(WriteAddr >> 8); // Send high address
|
||||
}
|
||||
else
|
||||
IIC::send_byte(EEPROM_DEVICE_ADDRESS + ((WriteAddr >> 8) << 1)); // Send device address 0xA0, write data
|
||||
|
||||
IIC::wait_ack();
|
||||
IIC::send_byte(WriteAddr & 0xFF); // Send low address
|
||||
IIC::wait_ack();
|
||||
IIC::send_byte(DataToWrite); // Receiving mode
|
||||
IIC::wait_ack();
|
||||
IIC::stop(); // Generate a stop condition
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// Start writing data of length Len at the specified address in BL24CXX
|
||||
// This function is used to write 16bit or 32bit data.
|
||||
// WriteAddr: the address to start writing
|
||||
// DataToWrite: the first address of the data array
|
||||
// Len: The length of the data to be written 2, 4
|
||||
void BL24CXX::writeLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len) {
|
||||
LOOP_L_N(t, Len)
|
||||
writeOneByte(WriteAddr + t, (DataToWrite >> (8 * t)) & 0xFF);
|
||||
}
|
||||
|
||||
// Start reading data of length Len from the specified address in BL24CXX
|
||||
// This function is used to read 16bit or 32bit data.
|
||||
// ReadAddr: the address to start reading
|
||||
// Return value: data
|
||||
// Len: The length of the data to be read 2,4
|
||||
uint32_t BL24CXX::readLenByte(uint16_t ReadAddr, uint8_t Len) {
|
||||
uint32_t temp = 0;
|
||||
LOOP_L_N(t, Len) {
|
||||
temp <<= 8;
|
||||
temp += readOneByte(ReadAddr + Len - t - 1);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
// Check if BL24CXX is normal
|
||||
// Return 1: Detection failed
|
||||
// return 0: detection is successful
|
||||
#define BL24CXX_TEST_ADDRESS 0x00
|
||||
#define BL24CXX_TEST_VALUE 0x55
|
||||
|
||||
bool BL24CXX::_check() {
|
||||
return (readOneByte(BL24CXX_TEST_ADDRESS) != BL24CXX_TEST_VALUE); // false = success!
|
||||
}
|
||||
|
||||
bool BL24CXX::check() {
|
||||
if (_check()) { // Value was written? Good EEPROM!
|
||||
writeOneByte(BL24CXX_TEST_ADDRESS, BL24CXX_TEST_VALUE); // Write now and check.
|
||||
return _check();
|
||||
}
|
||||
return false; // success!
|
||||
}
|
||||
|
||||
// Start reading the specified number of data at the specified address in BL24CXX
|
||||
// ReadAddr: The address to start reading is 0~255 for 24c02
|
||||
// pBuffer: the first address of the data array
|
||||
// NumToRead: the number of data to be read
|
||||
void BL24CXX::read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead) {
|
||||
for (; NumToRead; NumToRead--)
|
||||
*pBuffer++ = readOneByte(ReadAddr++);
|
||||
}
|
||||
|
||||
// Start writing the specified number of data at the specified address in BL24CXX
|
||||
// WriteAddr: the address to start writing, 0~255 for 24c02
|
||||
// pBuffer: the first address of the data array
|
||||
// NumToWrite: the number of data to be written
|
||||
void BL24CXX::write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite) {
|
||||
for (; NumToWrite; NumToWrite--, WriteAddr++)
|
||||
writeOneByte(WriteAddr, *pBuffer++);
|
||||
}
|
||||
|
||||
#endif // IIC_BL24CXX_EEPROM
|
72
Marlin/src/libs/BL24CXX.h
Normal file
72
Marlin/src/libs/BL24CXX.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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
|
||||
|
||||
/********************************************************************************
|
||||
* @file BL24CXX.h
|
||||
* @brief i2c EEPROM for Ender 3 v2 board (4.2.2)
|
||||
********************************************************************************/
|
||||
|
||||
/******************** IIC ********************/
|
||||
|
||||
class BL24CXX;
|
||||
|
||||
// All operation functions of IIC
|
||||
class IIC {
|
||||
friend class BL24CXX;
|
||||
protected:
|
||||
static void init(); // Initialize the IO port of IIC
|
||||
static void start(); // Send IIC start signal
|
||||
static void stop(); // Send IIC stop signal
|
||||
static void send_byte(uint8_t txd); // IIC sends a byte
|
||||
static uint8_t read_byte(unsigned char ack); // IIC reads a byte
|
||||
static uint8_t wait_ack(); // IIC waits for ACK signal
|
||||
static void ack(); // IIC sends ACK signal
|
||||
static void nAck(); // IIC does not send ACK signal
|
||||
};
|
||||
|
||||
/******************** EEPROM ********************/
|
||||
|
||||
#define BL24C01 127
|
||||
#define BL24C02 255
|
||||
#define BL24C04 511
|
||||
#define BL24C08 1023
|
||||
#define BL24C16 2047
|
||||
#define BL24C32 4095
|
||||
#define BL24C64 8191
|
||||
#define BL24C128 16383
|
||||
#define BL24C256 32767
|
||||
#define EE_TYPE BL24C16
|
||||
|
||||
class BL24CXX {
|
||||
private:
|
||||
static bool _check(); // Check the device
|
||||
public:
|
||||
static void init(); // Initialize IIC
|
||||
static bool check(); // Check / recheck the device
|
||||
static uint8_t readOneByte(uint16_t ReadAddr); // Read a byte at the specified address
|
||||
static void writeOneByte(uint16_t WriteAddr, uint8_t DataToWrite); // Write a byte at the specified address
|
||||
static void writeLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len); // The specified address begins to write the data of the specified length
|
||||
static uint32_t readLenByte(uint16_t ReadAddr, uint8_t Len); // The specified address starts to read the data of the specified length
|
||||
static void write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite); // Write the specified length of data from the specified address
|
||||
static void read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead); // Read the data of the specified length from the specified address
|
||||
};
|
270
Marlin/src/libs/L64XX/L64XX_Marlin.cpp
Executable file → Normal file
270
Marlin/src/libs/L64XX/L64XX_Marlin.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -37,42 +37,46 @@ L64XX_Marlin L64xxManager;
|
||||
#include "../../module/planner.h"
|
||||
#include "../../HAL/shared/Delay.h"
|
||||
|
||||
void echo_yes_no(const bool yes) { serialprintPGM(yes ? PSTR(" YES") : PSTR(" NO ")); }
|
||||
|
||||
static const char str_X[] PROGMEM = "X ", str_Y[] PROGMEM = "Y ", str_Z[] PROGMEM = "Z ",
|
||||
static const char LINEAR_AXIS_LIST(
|
||||
str_X[] PROGMEM = "X ", str_Y[] PROGMEM = "Y ", str_Z[] PROGMEM = "Z ",
|
||||
str_I[] PROGMEM = AXIS4_STR " ", str_J[] PROGMEM = AXIS5_STR " ", str_K[] PROGMEM = AXIS6_STR " "
|
||||
),
|
||||
str_X2[] PROGMEM = "X2", str_Y2[] PROGMEM = "Y2",
|
||||
str_Z2[] PROGMEM = "Z2", str_Z3[] PROGMEM = "Z3", str_Z4[] PROGMEM = "Z4",
|
||||
str_E0[] PROGMEM = "E0", str_E1[] PROGMEM = "E1",
|
||||
str_E2[] PROGMEM = "E2", str_E3[] PROGMEM = "E3",
|
||||
str_E4[] PROGMEM = "E4", str_E5[] PROGMEM = "E5",
|
||||
str_E6[] PROGMEM = "E6", str_E7[] PROGMEM = "E7"
|
||||
LIST_N(EXTRUDERS,
|
||||
str_E0[] PROGMEM = "E0", str_E1[] PROGMEM = "E1",
|
||||
str_E2[] PROGMEM = "E2", str_E3[] PROGMEM = "E3",
|
||||
str_E4[] PROGMEM = "E4", str_E5[] PROGMEM = "E5",
|
||||
str_E6[] PROGMEM = "E6", str_E7[] PROGMEM = "E7"
|
||||
)
|
||||
;
|
||||
|
||||
#define _EN_ITEM(N) , str_E##N
|
||||
PGM_P const L64XX_Marlin::index_to_axis[] PROGMEM = {
|
||||
str_X, str_Y, str_Z, str_X2, str_Y2, str_Z2, str_Z3, str_Z4,
|
||||
str_E0, str_E1, str_E2, str_E3, str_E4, str_E5, str_E6, str_E7
|
||||
LINEAR_AXIS_LIST(str_X, str_Y, str_Z, str_I, str_J, str_K),
|
||||
str_X2, str_Y2, str_Z2, str_Z3, str_Z4
|
||||
REPEAT(E_STEPPERS, _EN_ITEM)
|
||||
};
|
||||
#undef _EN_ITEM
|
||||
|
||||
#define DEBUG_OUT ENABLED(L6470_CHITCHAT)
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
void echo_yes_no(const bool yes) { DEBUG_ECHOPGM_P(yes ? PSTR(" YES") : PSTR(" NO ")); UNUSED(yes); }
|
||||
|
||||
uint8_t L64XX_Marlin::dir_commands[MAX_L64XX]; // array to hold direction command for each driver
|
||||
|
||||
#define _EN_ITEM(N) , INVERT_E##N##_DIR
|
||||
const uint8_t L64XX_Marlin::index_to_dir[MAX_L64XX] = {
|
||||
INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR
|
||||
, (INVERT_X_DIR) // X2
|
||||
#if ENABLED(X_DUAL_STEPPER_DRIVERS)
|
||||
^ (INVERT_X2_VS_X_DIR)
|
||||
#endif
|
||||
, (INVERT_Y_DIR) // Y2
|
||||
#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
|
||||
^ (INVERT_Y2_VS_Y_DIR)
|
||||
#endif
|
||||
, INVERT_Z_DIR, INVERT_Z_DIR, INVERT_Z_DIR // Z2,Z3,Z4
|
||||
|
||||
, INVERT_E0_DIR, INVERT_E1_DIR, INVERT_E2_DIR, INVERT_E3_DIR
|
||||
, INVERT_E4_DIR, INVERT_E5_DIR, INVERT_E6_DIR, INVERT_E7_DIR
|
||||
LINEAR_AXIS_LIST(INVERT_X_DIR, INVERT_Y_DIR, INVERT_Z_DIR, INVERT_I_DIR, INVERT_J_DIR, INVERT_K_DIR)
|
||||
, (INVERT_X_DIR) ^ BOTH(X_DUAL_STEPPER_DRIVERS, INVERT_X2_VS_X_DIR) // X2
|
||||
, (INVERT_Y_DIR) ^ BOTH(Y_DUAL_STEPPER_DRIVERS, INVERT_Y2_VS_Y_DIR) // Y2
|
||||
, (INVERT_Z_DIR) ^ ENABLED(INVERT_Z2_VS_Z_DIR) // Z2
|
||||
, (INVERT_Z_DIR) ^ ENABLED(INVERT_Z3_VS_Z_DIR) // Z3
|
||||
, (INVERT_Z_DIR) ^ ENABLED(INVERT_Z4_VS_Z_DIR) // Z4
|
||||
REPEAT(E_STEPPERS, _EN_ITEM)
|
||||
};
|
||||
#undef _EN_ITEM
|
||||
|
||||
volatile uint8_t L64XX_Marlin::spi_abort = false;
|
||||
uint8_t L64XX_Marlin::spi_active = false;
|
||||
@@ -331,6 +335,15 @@ void L64XX_Marlin::set_param(const L64XX_axis_t axis, const uint8_t param, const
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
case Z : SET_L6470_PARAM(Z); break;
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
case I : SET_L6470_PARAM(I); break;
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
case J : SET_L6470_PARAM(J); break;
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
case K : SET_L6470_PARAM(K); break;
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
case X2: SET_L6470_PARAM(X2); break;
|
||||
#endif
|
||||
@@ -373,14 +386,13 @@ void L64XX_Marlin::set_param(const L64XX_axis_t axis, const uint8_t param, const
|
||||
}
|
||||
}
|
||||
|
||||
inline void echo_min_max(const char a, const float &min, const float &max) {
|
||||
inline void echo_min_max(const char a, const_float_t min, const_float_t max) {
|
||||
DEBUG_CHAR(' '); DEBUG_CHAR(a);
|
||||
DEBUG_ECHOPAIR(" min = ", min);
|
||||
DEBUG_ECHOLNPAIR(" max = ", max);
|
||||
DEBUG_ECHOLNPGM(" min = ", min, " max = ", max);
|
||||
}
|
||||
inline void echo_oct_used(const float &oct, const uint8_t stall) {
|
||||
DEBUG_ECHOPAIR("over_current_threshold used : ", oct);
|
||||
serialprintPGM(stall ? PSTR(" (Stall") : PSTR(" (OCD"));
|
||||
inline void echo_oct_used(const_float_t oct, const uint8_t stall) {
|
||||
DEBUG_ECHOPGM("over_current_threshold used : ", oct);
|
||||
DEBUG_ECHOPGM_P(stall ? PSTR(" (Stall") : PSTR(" (OCD"));
|
||||
DEBUG_ECHOLNPGM(" threshold)");
|
||||
}
|
||||
inline void err_out_of_bounds() { DEBUG_ECHOLNPGM("Test aborted - motion out of bounds"); }
|
||||
@@ -400,7 +412,7 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
}
|
||||
|
||||
uint8_t found_displacement = false;
|
||||
LOOP_XYZE(i) if (uint16_t _displacement = parser.intval(axis_codes[i])) {
|
||||
LOOP_LOGICAL_AXES(i) if (uint16_t _displacement = parser.intval(axis_codes[i])) {
|
||||
found_displacement = true;
|
||||
displacement = _displacement;
|
||||
uint8_t axis_offset = parser.byteval('J');
|
||||
@@ -438,10 +450,15 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
// Position calcs & checks
|
||||
//
|
||||
|
||||
const float X_center = LOGICAL_X_POSITION(current_position.x),
|
||||
Y_center = LOGICAL_Y_POSITION(current_position.y),
|
||||
Z_center = LOGICAL_Z_POSITION(current_position.z),
|
||||
E_center = current_position.e;
|
||||
const float LOGICAL_AXIS_LIST(
|
||||
E_center = current_position.e,
|
||||
X_center = LOGICAL_X_POSITION(current_position.x),
|
||||
Y_center = LOGICAL_Y_POSITION(current_position.y),
|
||||
Z_center = LOGICAL_Z_POSITION(current_position.z),
|
||||
I_center = LOGICAL_I_POSITION(current_position.i),
|
||||
J_center = LOGICAL_J_POSITION(current_position.j),
|
||||
K_center = LOGICAL_K_POSITION(current_position.k)
|
||||
);
|
||||
|
||||
switch (axis_mon[0][0]) {
|
||||
default: position_max = position_min = 0; break;
|
||||
@@ -450,58 +467,79 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
position_min = X_center - displacement;
|
||||
position_max = X_center + displacement;
|
||||
echo_min_max('X', position_min, position_max);
|
||||
if (false
|
||||
#ifdef X_MIN_POS
|
||||
|| position_min < (X_MIN_POS)
|
||||
#endif
|
||||
#ifdef X_MAX_POS
|
||||
|| position_max > (X_MAX_POS)
|
||||
#endif
|
||||
) {
|
||||
if (TERN0(HAS_ENDSTOPS, position_min < (X_MIN_POS) || position_max > (X_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
|
||||
case 'Y': {
|
||||
position_min = Y_center - displacement;
|
||||
position_max = Y_center + displacement;
|
||||
echo_min_max('Y', position_min, position_max);
|
||||
if (false
|
||||
#ifdef Y_MIN_POS
|
||||
|| position_min < (Y_MIN_POS)
|
||||
#endif
|
||||
#ifdef Y_MAX_POS
|
||||
|| position_max > (Y_MAX_POS)
|
||||
#endif
|
||||
) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#if HAS_Y_AXIS
|
||||
case 'Y': {
|
||||
position_min = Y_center - displacement;
|
||||
position_max = Y_center + displacement;
|
||||
echo_min_max('Y', position_min, position_max);
|
||||
if (TERN0(HAS_ENDSTOPS, position_min < (Y_MIN_POS) || position_max > (Y_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
case 'Z': {
|
||||
position_min = Z_center - displacement;
|
||||
position_max = Z_center + displacement;
|
||||
echo_min_max('Z', position_min, position_max);
|
||||
if (false
|
||||
#ifdef Z_MIN_POS
|
||||
|| position_min < (Z_MIN_POS)
|
||||
#endif
|
||||
#ifdef Z_MAX_POS
|
||||
|| position_max > (Z_MAX_POS)
|
||||
#endif
|
||||
) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#if HAS_Z_AXIS
|
||||
case 'Z': {
|
||||
position_min = Z_center - displacement;
|
||||
position_max = Z_center + displacement;
|
||||
echo_min_max('Z', position_min, position_max);
|
||||
if (TERN0(HAS_ENDSTOPS, position_min < (Z_MIN_POS) || position_max > (Z_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
case 'E': {
|
||||
position_min = E_center - displacement;
|
||||
position_max = E_center + displacement;
|
||||
echo_min_max('E', position_min, position_max);
|
||||
} break;
|
||||
#if LINEAR_AXES >= 4
|
||||
case AXIS4_NAME: {
|
||||
position_min = I_center - displacement;
|
||||
position_max = I_center + displacement;
|
||||
echo_min_max(AXIS4_NAME, position_min, position_max);
|
||||
if (TERN0(HAS_ENDSTOPS, position_min < (I_MIN_POS) || position_max > (I_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 5
|
||||
case AXIS5_NAME: {
|
||||
position_min = J_center - displacement;
|
||||
position_max = J_center + displacement;
|
||||
echo_min_max(AXIS5_NAME, position_min, position_max);
|
||||
if (TERN1(HAS_ENDSTOPS, position_min < (J_MIN_POS) || position_max > (J_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if LINEAR_AXES >= 6
|
||||
case AXIS6_NAME: {
|
||||
position_min = K_center - displacement;
|
||||
position_max = K_center + displacement;
|
||||
echo_min_max(AXIS6_NAME, position_min, position_max);
|
||||
if (TERN2(HAS_ENDSTOPS, position_min < (K_MIN_POS) || position_max > (K_MAX_POS))) {
|
||||
err_out_of_bounds();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#if HAS_EXTRUDERS
|
||||
case 'E': {
|
||||
position_min = E_center - displacement;
|
||||
position_max = E_center + displacement;
|
||||
echo_min_max('E', position_min, position_max);
|
||||
} break;
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
@@ -530,7 +568,7 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
}
|
||||
|
||||
DEBUG_ECHOPGM("Monitoring:");
|
||||
for (j = 0; j < driver_count; j++) DEBUG_ECHOPAIR(" ", axis_mon[j]);
|
||||
for (j = 0; j < driver_count; j++) DEBUG_ECHOPGM(" ", axis_mon[j]);
|
||||
DEBUG_EOL();
|
||||
|
||||
// now have a list of driver(s) to monitor
|
||||
@@ -551,19 +589,19 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
}
|
||||
// only print the tval from one of the drivers
|
||||
kval_hold = get_param(axis_index[0], L6474_TVAL);
|
||||
DEBUG_ECHOLNPAIR("TVAL current (mA) = ", (kval_hold + 1) * sh.AXIS_STALL_CURRENT_CONSTANT_INV);
|
||||
DEBUG_ECHOLNPGM("TVAL current (mA) = ", (kval_hold + 1) * sh.AXIS_STALL_CURRENT_CONSTANT_INV);
|
||||
}
|
||||
else {
|
||||
kval_hold = parser.byteval('K');
|
||||
if (kval_hold) {
|
||||
DEBUG_ECHOLNPAIR("kval_hold = ", kval_hold);
|
||||
DEBUG_ECHOLNPGM("kval_hold = ", kval_hold);
|
||||
for (j = 0; j < driver_count; j++)
|
||||
set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold);
|
||||
}
|
||||
else {
|
||||
// only print the KVAL_HOLD from one of the drivers
|
||||
kval_hold = get_param(axis_index[0], L6470_KVAL_HOLD);
|
||||
DEBUG_ECHOLNPAIR("KVAL_HOLD = ", kval_hold);
|
||||
DEBUG_ECHOLNPGM("KVAL_HOLD = ", kval_hold);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -591,7 +629,7 @@ uint8_t L64XX_Marlin::get_user_input(uint8_t &driver_count, L64XX_axis_t axis_in
|
||||
OCD_TH_actual = (OCD_TH_val_local + 1) * 375;
|
||||
}
|
||||
|
||||
DEBUG_ECHOLNPAIR("over_current_threshold specified: ", over_current_threshold);
|
||||
DEBUG_ECHOLNPGM("over_current_threshold specified: ", over_current_threshold);
|
||||
if (!(sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT)) echo_oct_used((STALL_TH_val_local + 1) * 31.25, true);
|
||||
echo_oct_used((OCD_TH_val_local + 1) * 375, false);
|
||||
|
||||
@@ -663,7 +701,7 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
|
||||
) {
|
||||
say_axis(axis);
|
||||
DEBUG_ECHOPGM(" THERMAL: ");
|
||||
serialprintPGM((status & _status_axis_th_sd) ? PSTR("SHUTDOWN") : (status & _status_axis_th_wrn) ? PSTR("WARNING ") : PSTR("OK "));
|
||||
DEBUG_ECHOPGM_P((status & _status_axis_th_sd) ? PSTR("SHUTDOWN") : (status & _status_axis_th_wrn) ? PSTR("WARNING ") : PSTR("OK "));
|
||||
DEBUG_ECHOPGM(" OVERCURRENT: ");
|
||||
echo_yes_no((status & _status_axis_ocd) != 0);
|
||||
if (!(_status_axis_layout == L6474_STATUS_LAYOUT)) { // L6474 doesn't have these bits
|
||||
@@ -686,7 +724,7 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
|
||||
bool L64XX_Marlin::monitor_paused = false; // Flag to skip monitor during M122, M906, M916, M917, M918, etc.
|
||||
|
||||
struct L6470_driver_data {
|
||||
uint8_t driver_index;
|
||||
L64XX_axis_t driver_index;
|
||||
uint32_t driver_status;
|
||||
uint8_t is_otw;
|
||||
uint8_t otw_counter;
|
||||
@@ -697,52 +735,61 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
|
||||
|
||||
L6470_driver_data driver_L6470_data[] = {
|
||||
#if AXIS_IS_L64XX(X)
|
||||
{ 0, 0, 0, 0, 0, 0, 0 },
|
||||
{ X, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y)
|
||||
{ 1, 0, 0, 0, 0, 0, 0 },
|
||||
{ Y, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
{ 2, 0, 0, 0, 0, 0, 0 },
|
||||
{ Z, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
{ I, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
{ J, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
{ K, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
{ 3, 0, 0, 0, 0, 0, 0 },
|
||||
{ X2, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Y2)
|
||||
{ 4, 0, 0, 0, 0, 0, 0 },
|
||||
{ Y2, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z2)
|
||||
{ 5, 0, 0, 0, 0, 0, 0 },
|
||||
{ Z2, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z3)
|
||||
{ 6, 0, 0, 0, 0, 0, 0 },
|
||||
{ Z3, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(Z4)
|
||||
{ 7, 0, 0, 0, 0, 0, 0 },
|
||||
{ Z4, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E0)
|
||||
{ 8, 0, 0, 0, 0, 0, 0 },
|
||||
{ E0, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E1)
|
||||
{ 9, 0, 0, 0, 0, 0, 0 },
|
||||
{ E1, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E2)
|
||||
{ 10, 0, 0, 0, 0, 0, 0 },
|
||||
{ E2, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E3)
|
||||
{ 11, 0, 0, 0, 0, 0, 0 },
|
||||
{ E3, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E4)
|
||||
{ 12, 0, 0, 0, 0, 0, 0 },
|
||||
{ E4, 0, 0, 0, 0, 0, 0 },
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
{ 13, 0, 0, 0, 0, 0, 0 }
|
||||
{ E5, 0, 0, 0, 0, 0, 0 }
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
{ 14, 0, 0, 0, 0, 0, 0 }
|
||||
{ E6, 0, 0, 0, 0, 0, 0 }
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
{ 16, 0, 0, 0, 0, 0, 0 }
|
||||
{ E7, 0, 0, 0, 0, 0, 0 }
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -889,6 +936,15 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
|
||||
#if AXIS_IS_L64XX(Z)
|
||||
monitor_update(Z);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(I)
|
||||
monitor_update(I);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(J)
|
||||
monitor_update(J);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(K)
|
||||
monitor_update(K);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(X2)
|
||||
monitor_update(X2);
|
||||
#endif
|
||||
@@ -922,10 +978,14 @@ void L64XX_Marlin::say_axis(const L64XX_axis_t axis, const uint8_t label/*=true*
|
||||
#if AXIS_IS_L64XX(E5)
|
||||
monitor_update(E5);
|
||||
#endif
|
||||
|
||||
#if ENABLED(L6470_DEBUG)
|
||||
if (report_L6470_status) DEBUG_EOL();
|
||||
#if AXIS_IS_L64XX(E6)
|
||||
monitor_update(E6);
|
||||
#endif
|
||||
#if AXIS_IS_L64XX(E7)
|
||||
monitor_update(E7);
|
||||
#endif
|
||||
|
||||
if (TERN0(L6470_DEBUG, report_L6470_status)) DEBUG_EOL();
|
||||
|
||||
spi_active = false; // done with all SPI transfers - clear handshake flags
|
||||
spi_abort = false;
|
||||
|
6
Marlin/src/libs/L64XX/L64XX_Marlin.h
Executable file → Normal file
6
Marlin/src/libs/L64XX/L64XX_Marlin.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -35,7 +35,9 @@
|
||||
#define dSPIN_STEP_CLOCK_REV dSPIN_STEP_CLOCK+1
|
||||
#define HAS_L64XX_EXTRUDER (AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7))
|
||||
|
||||
enum L64XX_axis_t : uint8_t { X, Y, Z, X2, Y2, Z2, Z3, Z4, E0, E1, E2, E3, E4, E5, E6, E7, MAX_L64XX };
|
||||
#define _EN_ITEM(N) , E##N
|
||||
enum L64XX_axis_t : uint8_t { LINEAR_AXIS_LIST(X, Y, Z, I, J, K), X2, Y2, Z2, Z3, Z4 REPEAT(E_STEPPERS, _EN_ITEM), MAX_L64XX };
|
||||
#undef _EN_ITEM
|
||||
|
||||
class L64XX_Marlin : public L64XXHelper {
|
||||
public:
|
||||
|
2
Marlin/src/libs/L64XX/README.md
Executable file → Normal file
2
Marlin/src/libs/L64XX/README.md
Executable file → Normal file
@@ -16,7 +16,7 @@ This software assumes that all drivers are in one SPI daisy chain.
|
||||
|
||||
- SDO of the last device is tied to MISO of the controller
|
||||
|
||||
- All devices share the same `SCK` and `SS_PIN` pins. The user must supply a macro to control the `RESET_PIN`(s).
|
||||
- All devices share the same `SCK_PIN` and `SS_PIN` pins. The user must supply a macro to control the `RESET_PIN`(s).
|
||||
|
||||
- Each L6470 passes the data it saw on its SDI to its neighbor on the **NEXT** SPI cycle (8 bit delay).
|
||||
|
||||
|
500
Marlin/src/libs/MAX31865.cpp
Normal file
500
Marlin/src/libs/MAX31865.cpp
Normal file
@@ -0,0 +1,500 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on Based on Adafruit MAX31865 library:
|
||||
*
|
||||
* This is a library for the Adafruit PT100/P1000 RTD Sensor w/MAX31865
|
||||
* Designed specifically to work with the Adafruit RTD Sensor
|
||||
* https://www.adafruit.com/products/3328
|
||||
*
|
||||
* This sensor uses SPI to communicate, 4 pins are required to interface.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
*
|
||||
* Modifications by JoAnn Manges (@GadgetAngel)
|
||||
* Copyright (c) 2020, JoAnn Manges
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
// Useful for RTD debugging.
|
||||
//#define MAX31865_DEBUG
|
||||
//#define MAX31865_DEBUG_SPI
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
|
||||
|
||||
//#include <SoftwareSPI.h> // TODO: switch to SPIclass/SoftSPI
|
||||
#include "MAX31865.h"
|
||||
|
||||
// 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
|
||||
);
|
||||
|
||||
#ifndef LARGE_PINMAP
|
||||
|
||||
/**
|
||||
* Create the interface object using software (bitbang) SPI for PIN values
|
||||
* less than or equal to 127.
|
||||
*
|
||||
* @param spi_cs the SPI CS pin to use
|
||||
* @param spi_mosi the SPI MOSI pin to use
|
||||
* @param spi_miso the SPI MISO pin to use
|
||||
* @param spi_clk the SPI clock pin to use
|
||||
*/
|
||||
MAX31865::MAX31865(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk) {
|
||||
_cs = spi_cs;
|
||||
_mosi = spi_mosi;
|
||||
_miso = spi_miso;
|
||||
_sclk = spi_clk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the interface object using hardware SPI for PIN for PIN values less
|
||||
* than or equal to 127.
|
||||
*
|
||||
* @param spi_cs the SPI CS pin to use along with the default SPI device
|
||||
*/
|
||||
MAX31865::MAX31865(int8_t spi_cs) {
|
||||
_cs = spi_cs;
|
||||
_sclk = _miso = _mosi = -1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/**
|
||||
* Create the interface object using software (bitbang) SPI for PIN values
|
||||
* which are larger than 127. If you have PIN values less than or equal to
|
||||
* 127 use the other call for SW SPI.
|
||||
*
|
||||
* @param spi_cs the SPI CS pin to use
|
||||
* @param spi_mosi the SPI MOSI pin to use
|
||||
* @param spi_miso the SPI MISO pin to use
|
||||
* @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) {
|
||||
_cs = spi_cs;
|
||||
_mosi = spi_mosi;
|
||||
_miso = spi_miso;
|
||||
_sclk = spi_clk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the interface object using hardware SPI for PIN values which are
|
||||
* larger than 127. If you have PIN values less than or equal to 127 use
|
||||
* the other call for HW SPI.
|
||||
*
|
||||
* @param spi_cs the SPI CS pin to use along with the default SPI device
|
||||
* @param pin_mapping set to 1 for positive pin values
|
||||
*/
|
||||
MAX31865::MAX31865(uint32_t spi_cs, uint8_t pin_mapping) {
|
||||
_cs = spi_cs;
|
||||
_sclk = _miso = _mosi = -1UL; //-1UL or 0xFFFFFFFF or 4294967295
|
||||
}
|
||||
|
||||
#endif // LARGE_PINMAP
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Instance & Class methods
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the SPI interface and set the number of RTD wires used
|
||||
*
|
||||
* @param wires The number of wires in enum format. Can be MAX31865_2WIRE, MAX31865_3WIRE, or MAX31865_4WIRE.
|
||||
* @param zero The resistance of the RTD at 0 degC, in ohms.
|
||||
* @param ref The resistance of the reference resistor, in ohms.
|
||||
*/
|
||||
void MAX31865::begin(max31865_numwires_t wires, float zero, float ref) {
|
||||
Rzero = zero;
|
||||
Rref = 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);
|
||||
}
|
||||
else {
|
||||
// Start and configure hardware SPI
|
||||
#ifdef MAX31865_DEBUG
|
||||
SERIAL_ECHOLN("Initializing MAX31865 Hardware SPI");
|
||||
#endif
|
||||
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
setWires(wires);
|
||||
enableBias(false);
|
||||
autoConvert(false);
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the raw 8-bit FAULTSTAT register
|
||||
*
|
||||
* @return The raw unsigned 8-bit FAULT status register
|
||||
*/
|
||||
uint8_t MAX31865::readFault() {
|
||||
return readRegister8(MAX31856_FAULTSTAT_REG);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all faults in FAULTSTAT.
|
||||
*/
|
||||
void MAX31865::clearFault() {
|
||||
setConfig(MAX31856_CONFIG_FAULTSTAT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we want to have continuous conversions (50/60 Hz)
|
||||
*
|
||||
* @param b If true, auto conversion is enabled
|
||||
*/
|
||||
void MAX31865::autoConvert(bool b) {
|
||||
setConfig(MAX31856_CONFIG_MODEAUTO, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we want filter out 50Hz noise or 60Hz noise
|
||||
*
|
||||
* @param b If true, 50Hz noise is filtered, else 60Hz(default)
|
||||
*/
|
||||
void MAX31865::enable50HzFilter(bool b) {
|
||||
setConfig(MAX31856_CONFIG_FILT50HZ, b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the bias voltage on the RTD sensor
|
||||
*
|
||||
* @param b If true bias is enabled, else disabled
|
||||
*/
|
||||
void MAX31865::enableBias(bool b) {
|
||||
setConfig(MAX31856_CONFIG_BIAS, b);
|
||||
|
||||
// From the datasheet:
|
||||
// Note that if VBIAS is off (to reduce supply current between conversions), any filter
|
||||
// capacitors at the RTDIN inputs need to charge before an accurate conversion can be
|
||||
// performed. Therefore, enable VBIAS and wait at least 10.5 time constants of the input
|
||||
// RC network plus an additional 1ms before initiating the conversion.
|
||||
if (b)
|
||||
DELAY_US(11500); //11.5ms
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a one-shot temperature reading.
|
||||
*/
|
||||
void MAX31865::oneShot() {
|
||||
setConfig(MAX31856_CONFIG_1SHOT, 1);
|
||||
|
||||
// From the datasheet:
|
||||
// Note that a single conversion requires approximately 52ms in 60Hz filter
|
||||
// mode or 62.5ms in 50Hz filter mode to complete. 1-Shot is a self-clearing bit.
|
||||
// TODO: switch this out depending on the filter mode.
|
||||
DELAY_US(65000); // 65ms
|
||||
}
|
||||
|
||||
/**
|
||||
* How many wires we have in our RTD setup, can be MAX31865_2WIRE,
|
||||
* MAX31865_3WIRE, or MAX31865_4WIRE
|
||||
*
|
||||
* @param wires The number of wires in enum format
|
||||
*/
|
||||
void MAX31865::setWires(max31865_numwires_t wires) {
|
||||
uint8_t t = readRegister8(MAX31856_CONFIG_REG);
|
||||
if (wires == MAX31865_3WIRE)
|
||||
t |= MAX31856_CONFIG_3WIRE;
|
||||
else // 2 or 4 wire
|
||||
t &= ~MAX31856_CONFIG_3WIRE;
|
||||
writeRegister8(MAX31856_CONFIG_REG, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the raw 16-bit value from the RTD_REG in one shot mode. This will include
|
||||
* the fault bit, D0.
|
||||
*
|
||||
* @return The raw unsigned 16-bit register value with ERROR bit attached, NOT temperature!
|
||||
*/
|
||||
uint16_t MAX31865::readRaw() {
|
||||
clearFault();
|
||||
enableBias(true);
|
||||
|
||||
oneShot();
|
||||
uint16_t rtd = readRegister16(MAX31856_RTDMSB_REG);
|
||||
|
||||
#ifdef MAX31865_DEBUG
|
||||
SERIAL_ECHOLNPGM("RTD MSB:", (rtd >> 8), " RTD LSB:", (rtd & 0x00FF));
|
||||
#endif
|
||||
|
||||
// Disable the bias to lower power dissipation between reads.
|
||||
// If the ref resistor heats up, the temperature reading will be skewed.
|
||||
enableBias(false);
|
||||
|
||||
return rtd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate and return the resistance value of the connected RTD.
|
||||
*
|
||||
* @param refResistor The value of the matching reference resistor, usually 430 or 4300
|
||||
* @return The raw RTD resistance value, NOT temperature!
|
||||
*/
|
||||
float MAX31865::readResistance() {
|
||||
// Strip the error bit (D0) and convert to a float ratio.
|
||||
// less precise method: (readRaw() * Rref) >> 16
|
||||
return (((readRaw() >> 1) / 32768.0f) * Rref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the RTD and pass it to temperature(float) for calculation.
|
||||
*
|
||||
* @return Temperature in C
|
||||
*/
|
||||
float MAX31865::temperature() {
|
||||
return temperature(readResistance());
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the 15-bit ADC value, calculate the resistance and pass it to temperature(float) for calculation.
|
||||
*
|
||||
* @return Temperature in C
|
||||
*/
|
||||
float MAX31865::temperature(uint16_t adcVal) {
|
||||
return temperature(((adcVal) / 32768.0f) * Rref);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the temperature in C from the RTD resistance.
|
||||
* Uses the technique outlined in this PDF:
|
||||
* http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
|
||||
*
|
||||
* @param Rrtd the resistance value in ohms
|
||||
* @return the temperature in degC
|
||||
*/
|
||||
float MAX31865::temperature(float Rrtd) {
|
||||
float temp = (RTD_Z1 + sqrt(RTD_Z2 + (RTD_Z3 * Rrtd))) / RTD_Z4;
|
||||
|
||||
// From the PDF...
|
||||
//
|
||||
// The previous equation is valid only for temperatures of 0°C and above.
|
||||
// The equation for RRTD(t) that defines negative temperature behavior is a
|
||||
// fourth-order polynomial (after expanding the third term) and is quite
|
||||
// impractical to solve for a single expression of temperature as a function
|
||||
// of resistance.
|
||||
//
|
||||
if (temp < 0) {
|
||||
Rrtd = (Rrtd / Rzero) * 100; // normalize to 100 ohm
|
||||
float rpoly = Rrtd;
|
||||
|
||||
temp = -242.02 + (2.2228 * rpoly);
|
||||
rpoly *= Rrtd; // square
|
||||
temp += 2.5859e-3 * rpoly;
|
||||
rpoly *= Rrtd; // ^3
|
||||
temp -= 4.8260e-6 * rpoly;
|
||||
rpoly *= Rrtd; // ^4
|
||||
temp -= 2.8183e-8 * rpoly;
|
||||
rpoly *= Rrtd; // ^5
|
||||
temp += 1.5243e-10 * rpoly;
|
||||
}
|
||||
|
||||
return temp;
|
||||
}
|
||||
|
||||
//
|
||||
// private:
|
||||
//
|
||||
|
||||
|
||||
/**
|
||||
* Set a value in the configuration register.
|
||||
*
|
||||
* @param config 8-bit value for the config item
|
||||
* @param enable whether to enable or disable the value
|
||||
*/
|
||||
void MAX31865::setConfig(uint8_t config, bool enable) {
|
||||
uint8_t t = readRegister8(MAX31856_CONFIG_REG);
|
||||
if (enable)
|
||||
t |= config;
|
||||
else
|
||||
t &= ~config; // disable
|
||||
writeRegister8(MAX31856_CONFIG_REG, t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a single byte from the specified register address.
|
||||
*
|
||||
* @param addr the register address
|
||||
* @return the register contents
|
||||
*/
|
||||
uint8_t MAX31865::readRegister8(uint8_t addr) {
|
||||
uint8_t ret = 0;
|
||||
readRegisterN(addr, &ret, 1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read two bytes: 1 from the specified register address, and 1 from the next address.
|
||||
*
|
||||
* @param addr the first register address
|
||||
* @return both register contents as a single 16-bit int
|
||||
*/
|
||||
uint16_t MAX31865::readRegister16(uint8_t addr) {
|
||||
uint8_t buffer[2] = {0, 0};
|
||||
readRegisterN(addr, buffer, 2);
|
||||
|
||||
uint16_t ret = buffer[0];
|
||||
ret <<= 8;
|
||||
ret |= buffer[1];
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read +n+ bytes from a specified address into +buffer+. Set D7 to 0 to specify a read.
|
||||
*
|
||||
* @param addr the first register address
|
||||
* @param buffer storage for the read bytes
|
||||
* @param n the number of bytes to read
|
||||
*/
|
||||
void MAX31865::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
|
||||
addr &= 0x7F; // make sure top bit is not set
|
||||
if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
|
||||
SPI.beginTransaction(spiConfig);
|
||||
else
|
||||
WRITE(_sclk, LOW);
|
||||
|
||||
WRITE(_cs, LOW);
|
||||
spixfer(addr);
|
||||
|
||||
while (n--) {
|
||||
buffer[0] = spixfer(0xFF);
|
||||
#ifdef MAX31865_DEBUG_SPI
|
||||
SERIAL_ECHOLNPGM("buffer read ", n, " data: ", buffer[0]);
|
||||
#endif
|
||||
buffer++;
|
||||
}
|
||||
|
||||
if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
|
||||
SPI.endTransaction();
|
||||
|
||||
WRITE(_cs, HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write an 8-bit value to a register. Set D7 to 1 to specify a write.
|
||||
*
|
||||
* @param addr the address to write to
|
||||
* @param data the data to write
|
||||
*/
|
||||
void MAX31865::writeRegister8(uint8_t addr, uint8_t data) {
|
||||
if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
|
||||
SPI.beginTransaction(spiConfig);
|
||||
else
|
||||
WRITE(_sclk, LOW);
|
||||
|
||||
WRITE(_cs, LOW);
|
||||
|
||||
spixfer(addr | 0x80); // make sure top bit is set
|
||||
spixfer(data);
|
||||
|
||||
if (_sclk == TERN(LARGE_PINMAP, -1UL, -1))
|
||||
SPI.endTransaction();
|
||||
|
||||
WRITE(_cs, HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transfer SPI data +x+ and read the response. From the datasheet...
|
||||
* Input data (SDI) is latched on the internal strobe edge and output data (SDO) is
|
||||
* shifted out on the shift edge. There is one clock for each bit transferred.
|
||||
* Address and data bits are transferred in groups of eight, MSB first.
|
||||
*
|
||||
* @param x an 8-bit chunk of data to write
|
||||
* @return the 8-bit response
|
||||
*/
|
||||
uint8_t MAX31865::spixfer(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;
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
#endif // HAS_MAX31865 && !USE_ADAFRUIT_MAX31865
|
131
Marlin/src/libs/MAX31865.h
Normal file
131
Marlin/src/libs/MAX31865.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on Adafruit MAX31865 library:
|
||||
*
|
||||
* This is a library for the Adafruit PT100/P1000 RTD Sensor w/MAX31865
|
||||
* Designed specifically to work with the Adafruit RTD Sensor
|
||||
* https://www.adafruit.com/products/3328
|
||||
*
|
||||
* This sensor uses SPI to communicate, 4 pins are required to interface.
|
||||
*
|
||||
* Adafruit invests time and resources providing this open source code,
|
||||
* please support Adafruit and open-source hardware by purchasing
|
||||
* products from Adafruit!
|
||||
*
|
||||
* Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
*
|
||||
* Modifications by JoAnn Manges (@GadgetAngel)
|
||||
* Copyright (c) 2020, JoAnn Manges
|
||||
* All rights reserved.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "../HAL/shared/Delay.h"
|
||||
#include HAL_PATH(../HAL, MarlinSPI.h)
|
||||
|
||||
#define MAX31856_CONFIG_REG 0x00
|
||||
#define MAX31856_CONFIG_BIAS 0x80
|
||||
#define MAX31856_CONFIG_MODEAUTO 0x40
|
||||
#define MAX31856_CONFIG_MODEOFF 0x00
|
||||
#define MAX31856_CONFIG_1SHOT 0x20
|
||||
#define MAX31856_CONFIG_3WIRE 0x10
|
||||
#define MAX31856_CONFIG_24WIRE 0x00
|
||||
#define MAX31856_CONFIG_FAULTSTAT 0x02
|
||||
#define MAX31856_CONFIG_FILT50HZ 0x01
|
||||
#define MAX31856_CONFIG_FILT60HZ 0x00
|
||||
|
||||
#define MAX31856_RTDMSB_REG 0x01
|
||||
#define MAX31856_RTDLSB_REG 0x02
|
||||
#define MAX31856_HFAULTMSB_REG 0x03
|
||||
#define MAX31856_HFAULTLSB_REG 0x04
|
||||
#define MAX31856_LFAULTMSB_REG 0x05
|
||||
#define MAX31856_LFAULTLSB_REG 0x06
|
||||
#define MAX31856_FAULTSTAT_REG 0x07
|
||||
|
||||
#define MAX31865_FAULT_HIGHTHRESH 0x80 // D7
|
||||
#define MAX31865_FAULT_LOWTHRESH 0x40 // D6
|
||||
#define MAX31865_FAULT_REFINLOW 0x20 // D5
|
||||
#define MAX31865_FAULT_REFINHIGH 0x10 // D4
|
||||
#define MAX31865_FAULT_RTDINLOW 0x08 // D3
|
||||
#define MAX31865_FAULT_OVUV 0x04 // D2
|
||||
|
||||
// http://www.analog.com/media/en/technical-documentation/application-notes/AN709_0.pdf
|
||||
// constants for calculating temperature from the measured RTD resistance.
|
||||
#define RTD_Z1 -0.0039083
|
||||
#define RTD_Z2 0.00001758480889
|
||||
#define RTD_Z3 -0.0000000231
|
||||
#define RTD_Z4 -0.000001155
|
||||
|
||||
typedef enum max31865_numwires {
|
||||
MAX31865_2WIRE = 0,
|
||||
MAX31865_3WIRE = 1,
|
||||
MAX31865_4WIRE = 0
|
||||
} max31865_numwires_t;
|
||||
|
||||
/* Interface class for the MAX31865 RTD Sensor reader */
|
||||
class MAX31865 {
|
||||
private:
|
||||
static SPISettings spiConfig;
|
||||
|
||||
TERN(LARGE_PINMAP, uint32_t, uint8_t) _sclk, _miso, _mosi, _cs;
|
||||
float Rzero, Rref;
|
||||
|
||||
void setConfig(uint8_t config, bool enable);
|
||||
|
||||
void readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n);
|
||||
uint8_t readRegister8(uint8_t addr);
|
||||
uint16_t readRegister16(uint8_t addr);
|
||||
|
||||
void writeRegister8(uint8_t addr, uint8_t reg);
|
||||
uint8_t spixfer(uint8_t addr);
|
||||
|
||||
public:
|
||||
#ifdef LARGE_PINMAP
|
||||
MAX31865(uint32_t spi_cs, uint8_t pin_mapping);
|
||||
MAX31865(uint32_t spi_cs, uint32_t spi_mosi, uint32_t spi_miso,
|
||||
uint32_t spi_clk, uint8_t pin_mapping);
|
||||
#else
|
||||
MAX31865(int8_t spi_cs);
|
||||
MAX31865(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso,
|
||||
int8_t spi_clk);
|
||||
#endif
|
||||
|
||||
void begin(max31865_numwires_t wires, float zero, float ref);
|
||||
|
||||
uint8_t readFault();
|
||||
void clearFault();
|
||||
|
||||
void setWires(max31865_numwires_t wires);
|
||||
void autoConvert(bool b);
|
||||
void enable50HzFilter(bool b);
|
||||
void enableBias(bool b);
|
||||
void oneShot();
|
||||
|
||||
uint16_t readRaw();
|
||||
float readResistance();
|
||||
float temperature();
|
||||
float temperature(uint16_t adcVal);
|
||||
float temperature(float Rrtd);
|
||||
};
|
383
Marlin/src/libs/W25Qxx.cpp
Normal file
383
Marlin/src/libs/W25Qxx.cpp
Normal file
@@ -0,0 +1,383 @@
|
||||
/**
|
||||
* 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 "../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SPI_FLASH
|
||||
|
||||
#include "W25Qxx.h"
|
||||
|
||||
W25QXXFlash W25QXX;
|
||||
|
||||
#ifndef NC
|
||||
#define NC -1
|
||||
#endif
|
||||
|
||||
MarlinSPI W25QXXFlash::mySPI(SPI_FLASH_MOSI_PIN, SPI_FLASH_MISO_PIN, SPI_FLASH_SCK_PIN, NC);
|
||||
|
||||
#define SPI_FLASH_CS_H() OUT_WRITE(SPI_FLASH_CS_PIN, HIGH)
|
||||
#define SPI_FLASH_CS_L() OUT_WRITE(SPI_FLASH_CS_PIN, LOW)
|
||||
|
||||
bool flash_dma_mode = true;
|
||||
|
||||
void W25QXXFlash::init(uint8_t spiRate) {
|
||||
|
||||
OUT_WRITE(SPI_FLASH_CS_PIN, HIGH);
|
||||
|
||||
/**
|
||||
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
|
||||
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
|
||||
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
|
||||
*/
|
||||
#if SPI_DEVICE == 1
|
||||
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4
|
||||
#else
|
||||
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
|
||||
#endif
|
||||
uint8_t clock;
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: clock = SPI_CLOCK_MAX; break;
|
||||
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4; break;
|
||||
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8; break;
|
||||
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
|
||||
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
|
||||
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
|
||||
default: clock = SPI_CLOCK_DIV2;// Default from the SPI library
|
||||
}
|
||||
|
||||
mySPI.setClockDivider(clock);
|
||||
mySPI.setBitOrder(MSBFIRST);
|
||||
mySPI.setDataMode(SPI_MODE0);
|
||||
mySPI.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a single byte from the SPI port.
|
||||
*
|
||||
* @return Byte received
|
||||
*/
|
||||
uint8_t W25QXXFlash::spi_flash_Rec() {
|
||||
const uint8_t returnByte = mySPI.transfer(0xFF);
|
||||
return returnByte;
|
||||
}
|
||||
|
||||
uint8_t W25QXXFlash::spi_flash_read_write_byte(uint8_t data) {
|
||||
const uint8_t returnByte = mySPI.transfer(data);
|
||||
return returnByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive a number of bytes from the SPI port to a buffer
|
||||
*
|
||||
* @param buf Pointer to starting address of buffer to write to.
|
||||
* @param nbyte Number of bytes to receive.
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Uses DMA
|
||||
*/
|
||||
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
|
||||
*
|
||||
* @param b Byte to send
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
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)
|
||||
*
|
||||
* @param buf Pointer with buffer start address
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Use DMA
|
||||
*/
|
||||
void W25QXXFlash::spi_flash_SendBlock(uint8_t token, const uint8_t *buf) {
|
||||
mySPI.transfer(token);
|
||||
mySPI.dmaSend(const_cast<uint8_t*>(buf), 512);
|
||||
}
|
||||
|
||||
uint16_t W25QXXFlash::W25QXX_ReadID(void) {
|
||||
uint16_t Temp = 0;
|
||||
SPI_FLASH_CS_L();
|
||||
spi_flash_Send(0x90);
|
||||
spi_flash_Send(0x00);
|
||||
spi_flash_Send(0x00);
|
||||
spi_flash_Send(0x00);
|
||||
Temp |= spi_flash_Rec() << 8;
|
||||
Temp |= spi_flash_Rec();
|
||||
SPI_FLASH_CS_H();
|
||||
return Temp;
|
||||
}
|
||||
|
||||
void W25QXXFlash::SPI_FLASH_WriteEnable(void) {
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
// Send "Write Enable" instruction
|
||||
spi_flash_Send(W25X_WriteEnable);
|
||||
// Deselect the FLASH: Chip Select high
|
||||
SPI_FLASH_CS_H();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_WaitForWriteEnd
|
||||
* Description : Polls the status of the Write In Progress (WIP) flag in the
|
||||
* FLASH's status register and loop until write operation has
|
||||
* completed.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25QXXFlash::SPI_FLASH_WaitForWriteEnd(void) {
|
||||
uint8_t FLASH_Status = 0;
|
||||
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
// Send "Read Status Register" instruction
|
||||
spi_flash_Send(W25X_ReadStatusReg);
|
||||
|
||||
// Loop as long as the memory is busy with a write cycle
|
||||
do
|
||||
/* Send a dummy byte to generate the clock needed by the FLASH
|
||||
and put the value of the status register in FLASH_Status variable */
|
||||
FLASH_Status = spi_flash_Rec();
|
||||
while ((FLASH_Status & WIP_Flag) == 0x01); // Write in progress
|
||||
|
||||
// Deselect the FLASH: Chip Select high
|
||||
SPI_FLASH_CS_H();
|
||||
}
|
||||
|
||||
void W25QXXFlash::SPI_FLASH_SectorErase(uint32_t SectorAddr) {
|
||||
// Send write enable instruction
|
||||
SPI_FLASH_WriteEnable();
|
||||
|
||||
// Sector Erase
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
// Send Sector Erase instruction
|
||||
spi_flash_Send(W25X_SectorErase);
|
||||
// Send SectorAddr high nybble address byte
|
||||
spi_flash_Send((SectorAddr & 0xFF0000) >> 16);
|
||||
// Send SectorAddr medium nybble address byte
|
||||
spi_flash_Send((SectorAddr & 0xFF00) >> 8);
|
||||
// Send SectorAddr low nybble address byte
|
||||
spi_flash_Send(SectorAddr & 0xFF);
|
||||
// Deselect the FLASH: Chip Select high
|
||||
|
||||
SPI_FLASH_CS_H();
|
||||
// Wait the end of Flash writing
|
||||
SPI_FLASH_WaitForWriteEnd();
|
||||
}
|
||||
|
||||
void W25QXXFlash::SPI_FLASH_BlockErase(uint32_t BlockAddr) {
|
||||
SPI_FLASH_WriteEnable();
|
||||
SPI_FLASH_CS_L();
|
||||
// Send Sector Erase instruction
|
||||
spi_flash_Send(W25X_BlockErase);
|
||||
// Send SectorAddr high nybble address byte
|
||||
spi_flash_Send((BlockAddr & 0xFF0000) >> 16);
|
||||
// Send SectorAddr medium nybble address byte
|
||||
spi_flash_Send((BlockAddr & 0xFF00) >> 8);
|
||||
// Send SectorAddr low nybble address byte
|
||||
spi_flash_Send(BlockAddr & 0xFF);
|
||||
|
||||
SPI_FLASH_CS_H();
|
||||
|
||||
SPI_FLASH_WaitForWriteEnd();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_BulkErase
|
||||
* Description : Erases the entire FLASH.
|
||||
* Input : None
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25QXXFlash::SPI_FLASH_BulkErase(void) {
|
||||
// Send write enable instruction
|
||||
SPI_FLASH_WriteEnable();
|
||||
|
||||
// Bulk Erase
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
|
||||
// Send Bulk Erase instruction
|
||||
spi_flash_Send(W25X_ChipErase);
|
||||
// Deselect the FLASH: Chip Select high
|
||||
SPI_FLASH_CS_H();
|
||||
// Wait the end of Flash writing
|
||||
SPI_FLASH_WaitForWriteEnd();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_PageWrite
|
||||
* Description : Writes more than one byte to the FLASH with a single WRITE
|
||||
* cycle(Page WRITE sequence). The number of byte can't exceed
|
||||
* the FLASH page size.
|
||||
* Input : - pBuffer : pointer to the buffer containing the data to be
|
||||
* written to the FLASH.
|
||||
* - WriteAddr : FLASH's internal address to write to.
|
||||
* - NumByteToWrite : number of bytes to write to the FLASH,
|
||||
* must be equal or less than "SPI_FLASH_PageSize" value.
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25QXXFlash::SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) {
|
||||
// Enable the write access to the FLASH
|
||||
SPI_FLASH_WriteEnable();
|
||||
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
// Send "Write to Memory " instruction
|
||||
spi_flash_Send(W25X_PageProgram);
|
||||
// Send WriteAddr high nybble address byte to write to
|
||||
spi_flash_Send((WriteAddr & 0xFF0000) >> 16);
|
||||
// Send WriteAddr medium nybble address byte to write to
|
||||
spi_flash_Send((WriteAddr & 0xFF00) >> 8);
|
||||
// Send WriteAddr low nybble address byte to write to
|
||||
spi_flash_Send(WriteAddr & 0xFF);
|
||||
|
||||
NOMORE(NumByteToWrite, SPI_FLASH_PerWritePageSize);
|
||||
|
||||
// While there is data to be written on the FLASH
|
||||
while (NumByteToWrite--) {
|
||||
// Send the current byte
|
||||
spi_flash_Send(*pBuffer);
|
||||
// Point on the next byte to be written
|
||||
pBuffer++;
|
||||
}
|
||||
|
||||
// Deselect the FLASH: Chip Select high
|
||||
SPI_FLASH_CS_H();
|
||||
|
||||
// Wait the end of Flash writing
|
||||
SPI_FLASH_WaitForWriteEnd();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_BufferWrite
|
||||
* Description : Writes block of data to the FLASH. In this function, the
|
||||
* number of WRITE cycles are reduced, using Page WRITE sequence.
|
||||
* Input : - pBuffer : pointer to the buffer containing the data to be
|
||||
* written to the FLASH.
|
||||
* - WriteAddr : FLASH's internal address to write to.
|
||||
* - NumByteToWrite : number of bytes to write to the FLASH.
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25QXXFlash::SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) {
|
||||
uint8_t NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
|
||||
|
||||
Addr = WriteAddr % SPI_FLASH_PageSize;
|
||||
count = SPI_FLASH_PageSize - Addr;
|
||||
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
|
||||
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
|
||||
|
||||
if (Addr == 0) { // WriteAddr is SPI_FLASH_PageSize aligned
|
||||
if (NumOfPage == 0) { // NumByteToWrite < SPI_FLASH_PageSize
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
|
||||
}
|
||||
else { // NumByteToWrite > SPI_FLASH_PageSize
|
||||
while (NumOfPage--) {
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
|
||||
WriteAddr += SPI_FLASH_PageSize;
|
||||
pBuffer += SPI_FLASH_PageSize;
|
||||
}
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
|
||||
}
|
||||
}
|
||||
else { // WriteAddr is not SPI_FLASH_PageSize aligned
|
||||
if (NumOfPage == 0) { // NumByteToWrite < SPI_FLASH_PageSize
|
||||
if (NumOfSingle > count) { // (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize
|
||||
temp = NumOfSingle - count;
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
|
||||
WriteAddr += count;
|
||||
pBuffer += count;
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);
|
||||
}
|
||||
else
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
|
||||
}
|
||||
else { // NumByteToWrite > SPI_FLASH_PageSize
|
||||
NumByteToWrite -= count;
|
||||
NumOfPage = NumByteToWrite / SPI_FLASH_PageSize;
|
||||
NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
|
||||
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
|
||||
WriteAddr += count;
|
||||
pBuffer += count;
|
||||
|
||||
while (NumOfPage--) {
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
|
||||
WriteAddr += SPI_FLASH_PageSize;
|
||||
pBuffer += SPI_FLASH_PageSize;
|
||||
}
|
||||
|
||||
if (NumOfSingle != 0)
|
||||
SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SPI_FLASH_BufferRead
|
||||
* Description : Reads a block of data from the FLASH.
|
||||
* Input : - pBuffer : pointer to the buffer that receives the data read
|
||||
* from the FLASH.
|
||||
* - ReadAddr : FLASH's internal address to read from.
|
||||
* - NumByteToRead : number of bytes to read from the FLASH.
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void W25QXXFlash::SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) {
|
||||
// Select the FLASH: Chip Select low
|
||||
SPI_FLASH_CS_L();
|
||||
|
||||
// Send "Read from Memory " instruction
|
||||
spi_flash_Send(W25X_ReadData);
|
||||
|
||||
// Send ReadAddr high nybble address byte to read from
|
||||
spi_flash_Send((ReadAddr & 0xFF0000) >> 16);
|
||||
// Send ReadAddr medium nybble address byte to read from
|
||||
spi_flash_Send((ReadAddr & 0xFF00) >> 8);
|
||||
// Send ReadAddr low nybble address byte to read from
|
||||
spi_flash_Send(ReadAddr & 0xFF);
|
||||
|
||||
if (NumByteToRead <= 32 || !flash_dma_mode) {
|
||||
while (NumByteToRead--) { // While there is data to be read
|
||||
// Read a byte from the FLASH
|
||||
*pBuffer = spi_flash_Rec();
|
||||
// Point to the next location where the byte read will be saved
|
||||
pBuffer++;
|
||||
}
|
||||
}
|
||||
else
|
||||
spi_flash_Read(pBuffer, NumByteToRead);
|
||||
|
||||
SPI_FLASH_CS_H();
|
||||
}
|
||||
|
||||
#endif // HAS_SPI_FLASH
|
74
Marlin/src/libs/W25Qxx.h
Normal file
74
Marlin/src/libs/W25Qxx.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include HAL_PATH(../HAL, MarlinSPI.h)
|
||||
|
||||
#define W25X_WriteEnable 0x06
|
||||
#define W25X_WriteDisable 0x04
|
||||
#define W25X_ReadStatusReg 0x05
|
||||
#define W25X_WriteStatusReg 0x01
|
||||
#define W25X_ReadData 0x03
|
||||
#define W25X_FastReadData 0x0B
|
||||
#define W25X_FastReadDual 0x3B
|
||||
#define W25X_PageProgram 0x02
|
||||
#define W25X_BlockErase 0xD8
|
||||
#define W25X_SectorErase 0x20
|
||||
#define W25X_ChipErase 0xC7
|
||||
#define W25X_PowerDown 0xB9
|
||||
#define W25X_ReleasePowerDown 0xAB
|
||||
#define W25X_DeviceID 0xAB
|
||||
#define W25X_ManufactDeviceID 0x90
|
||||
#define W25X_JedecDeviceID 0x9F
|
||||
|
||||
#define WIP_Flag 0x01 /* Write In Progress (WIP) flag */
|
||||
|
||||
#define Dummy_Byte 0xA5
|
||||
|
||||
#define SPI_FLASH_SectorSize 4096
|
||||
#define SPI_FLASH_PageSize 256
|
||||
#define SPI_FLASH_PerWritePageSize 256
|
||||
|
||||
class W25QXXFlash {
|
||||
private:
|
||||
static MarlinSPI mySPI;
|
||||
public:
|
||||
void init(uint8_t spiRate);
|
||||
static uint8_t spi_flash_Rec();
|
||||
static uint8_t spi_flash_read_write_byte(uint8_t data);
|
||||
static void spi_flash_Read(uint8_t *buf, uint16_t nbyte);
|
||||
static void spi_flash_Send(uint8_t b);
|
||||
static void spi_flash_SendBlock(uint8_t token, const uint8_t *buf);
|
||||
static uint16_t W25QXX_ReadID(void);
|
||||
static void SPI_FLASH_WriteEnable(void);
|
||||
static void SPI_FLASH_WaitForWriteEnd(void);
|
||||
static void SPI_FLASH_SectorErase(uint32_t SectorAddr);
|
||||
static void SPI_FLASH_BlockErase(uint32_t BlockAddr);
|
||||
static void SPI_FLASH_BulkErase(void);
|
||||
static void SPI_FLASH_PageWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
|
||||
static void SPI_FLASH_BufferWrite(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite);
|
||||
static void SPI_FLASH_BufferRead(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead);
|
||||
};
|
||||
|
||||
extern W25QXXFlash W25QXX;
|
50
Marlin/src/libs/autoreport.h
Normal file
50
Marlin/src/libs/autoreport.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* 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 "../inc/MarlinConfig.h"
|
||||
|
||||
template <typename Helper>
|
||||
struct AutoReporter {
|
||||
millis_t next_report_ms;
|
||||
uint8_t report_interval;
|
||||
#if HAS_MULTI_SERIAL
|
||||
SerialMask report_port_mask;
|
||||
AutoReporter() : report_port_mask(SerialMask::All) {}
|
||||
#endif
|
||||
|
||||
inline void set_interval(uint8_t seconds, const uint8_t limit=60) {
|
||||
report_interval = _MIN(seconds, limit);
|
||||
next_report_ms = millis() + SEC_TO_MS(seconds);
|
||||
}
|
||||
|
||||
inline void tick() {
|
||||
if (!report_interval) return;
|
||||
const millis_t ms = millis();
|
||||
if (ELAPSED(ms, next_report_ms)) {
|
||||
next_report_ms = ms + SEC_TO_MS(report_interval);
|
||||
PORT_REDIRECT(report_port_mask);
|
||||
Helper::report();
|
||||
//PORT_RESTORE();
|
||||
}
|
||||
}
|
||||
};
|
6
Marlin/src/libs/bresenham.h
Executable file → Normal file
6
Marlin/src/libs/bresenham.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -120,11 +120,11 @@ public:
|
||||
|
||||
static void report(const uint8_t index) {
|
||||
if (index < Cfg::SIZE) {
|
||||
SERIAL_ECHOPAIR("bresenham ", int(index), " : (", dividend[index], "/", divisor, ") ");
|
||||
SERIAL_ECHOPGM("bresenham ", index, " : (", dividend[index], "/", divisor, ") ");
|
||||
if (counter[index] >= 0) SERIAL_CHAR(' ');
|
||||
if (labs(counter[index]) < 100) { SERIAL_CHAR(' '); if (labs(counter[index]) < 10) SERIAL_CHAR(' '); }
|
||||
SERIAL_ECHO(counter[index]);
|
||||
SERIAL_ECHOLNPAIR(" ... ", value[index]);
|
||||
SERIAL_ECHOLNPGM(" ... ", value[index]);
|
||||
}
|
||||
}
|
||||
|
||||
|
7
Marlin/src/libs/buzzer.cpp
Executable file → Normal file
7
Marlin/src/libs/buzzer.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include "buzzer.h"
|
||||
#include "../module/temperature.h"
|
||||
#include "../lcd/marlinui.h"
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#include "../lcd/extui/ui_api.h"
|
||||
@@ -44,6 +45,7 @@ Buzzer buzzer;
|
||||
* @param frequency Frequency of the tone in hertz
|
||||
*/
|
||||
void Buzzer::tone(const uint16_t duration, const uint16_t frequency/*=0*/) {
|
||||
if (!ui.buzzer_enabled) return;
|
||||
while (buffer.isFull()) {
|
||||
tick();
|
||||
thermalManager.manage_heater();
|
||||
@@ -53,6 +55,7 @@ void Buzzer::tone(const uint16_t duration, const uint16_t frequency/*=0*/) {
|
||||
}
|
||||
|
||||
void Buzzer::tick() {
|
||||
if (!ui.buzzer_enabled) return;
|
||||
const millis_t now = millis();
|
||||
|
||||
if (!state.endtime) {
|
||||
@@ -62,7 +65,7 @@ void Buzzer::tick() {
|
||||
state.endtime = now + state.tone.duration;
|
||||
|
||||
if (state.tone.frequency > 0) {
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
#if ENABLED(EXTENSIBLE_UI) && DISABLED(EXTUI_LOCAL_BEEPER)
|
||||
CRITICAL_SECTION_START();
|
||||
ExtUI::onPlayTone(state.tone.frequency, state.tone.duration);
|
||||
CRITICAL_SECTION_END();
|
||||
|
9
Marlin/src/libs/buzzer.h
Executable file → Normal file
9
Marlin/src/libs/buzzer.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -56,7 +56,7 @@
|
||||
static CircularQueue<tone_t, TONE_QUEUE_LENGTH> buffer;
|
||||
|
||||
/**
|
||||
* @brief Inverts the sate of a digital PIN
|
||||
* @brief Inverts the state of a digital PIN
|
||||
* @details This will invert the current state of an digital IO pin.
|
||||
*/
|
||||
FORCE_INLINE static void invert() { TOGGLE(BEEPER_PIN); }
|
||||
@@ -84,9 +84,9 @@
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Class constructor
|
||||
* @brief Init Buzzer
|
||||
*/
|
||||
Buzzer() {
|
||||
static inline void init() {
|
||||
SET_OUTPUT(BEEPER_PIN);
|
||||
reset();
|
||||
}
|
||||
@@ -118,6 +118,7 @@
|
||||
#elif HAS_BUZZER
|
||||
|
||||
// Buzz indirectly via the MarlinUI instance
|
||||
#include "../lcd/marlinui.h"
|
||||
#define BUZZ(d,f) ui.buzz(d,f)
|
||||
|
||||
#else
|
||||
|
2
Marlin/src/libs/circularqueue.h
Executable file → Normal file
2
Marlin/src/libs/circularqueue.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
2
Marlin/src/libs/crc16.cpp
Executable file → Normal file
2
Marlin/src/libs/crc16.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
2
Marlin/src/libs/crc16.h
Executable file → Normal file
2
Marlin/src/libs/crc16.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
20
Marlin/src/libs/duration_t.h
Executable file → Normal file
20
Marlin/src/libs/duration_t.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -106,11 +106,17 @@ struct duration_t {
|
||||
return this->value;
|
||||
}
|
||||
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-overflow"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as a string
|
||||
* @details String will be formated using a "full" representation of duration
|
||||
* @details String will be formatted using a "full" representation of duration
|
||||
*
|
||||
* @param buffer The array pointed to must be able to accommodate 21 bytes
|
||||
* @param buffer The array pointed to must be able to accommodate 22 bytes
|
||||
* (21 for the string, 1 more for the terminating nul)
|
||||
*
|
||||
* Output examples:
|
||||
* 123456789012345678901 (strlen)
|
||||
@@ -127,7 +133,7 @@ struct duration_t {
|
||||
m = this->minute() % 60,
|
||||
s = this->second() % 60;
|
||||
|
||||
if (y) sprintf_P(buffer, PSTR("%iy %id %ih %im %is"), y, d, h, m, s);
|
||||
if (y) sprintf_P(buffer, PSTR("%iy %id %ih %im %is"), y, d, h, m, s);
|
||||
else if (d) sprintf_P(buffer, PSTR("%id %ih %im %is"), d, h, m, s);
|
||||
else if (h) sprintf_P(buffer, PSTR("%ih %im %is"), h, m, s);
|
||||
else if (m) sprintf_P(buffer, PSTR("%im %is"), m, s);
|
||||
@@ -137,7 +143,7 @@ struct duration_t {
|
||||
|
||||
/**
|
||||
* @brief Formats the duration as a string
|
||||
* @details String will be formated using a "digital" representation of duration
|
||||
* @details String will be formatted using a "digital" representation of duration
|
||||
*
|
||||
* @param buffer The array pointed to must be able to accommodate 10 bytes
|
||||
*
|
||||
@@ -163,4 +169,8 @@ struct duration_t {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
};
|
||||
|
0
Marlin/src/libs/heatshrink/LICENSE
Executable file → Normal file
0
Marlin/src/libs/heatshrink/LICENSE
Executable file → Normal file
2
Marlin/src/libs/heatshrink/heatshrink_common.h
Executable file → Normal file
2
Marlin/src/libs/heatshrink/heatshrink_common.h
Executable file → Normal file
@@ -4,7 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#define HEATSHRINK_AUTHOR "Scott Vokes <vokes.s@gmail.com>"
|
||||
#define HEATSHRINK_URL "https://github.com/atomicobject/heatshrink"
|
||||
#define HEATSHRINK_URL "github.com/atomicobject/heatshrink"
|
||||
|
||||
/* Version 0.4.1 */
|
||||
#define HEATSHRINK_VERSION_MAJOR 0
|
||||
|
0
Marlin/src/libs/heatshrink/heatshrink_config.h
Executable file → Normal file
0
Marlin/src/libs/heatshrink/heatshrink_config.h
Executable file → Normal file
39
Marlin/src/libs/heatshrink/heatshrink_decoder.cpp
Executable file → Normal file
39
Marlin/src/libs/heatshrink/heatshrink_decoder.cpp
Executable file → Normal file
@@ -1,9 +1,36 @@
|
||||
/**
|
||||
* 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 "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(BINARY_FILE_TRANSFER)
|
||||
|
||||
/**
|
||||
* libs/heatshrink/heatshrink_decoder.cpp
|
||||
*/
|
||||
#include "heatshrink_decoder.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "heatshrink_decoder.h"
|
||||
|
||||
#pragma GCC optimize ("O3")
|
||||
|
||||
@@ -62,7 +89,7 @@ heatshrink_decoder *heatshrink_decoder_alloc(uint16_t input_buffer_size, uint8_t
|
||||
size_t buffers_sz = (1 << window_sz2) + input_buffer_size;
|
||||
size_t sz = sizeof(heatshrink_decoder) + buffers_sz;
|
||||
heatshrink_decoder *hsd = HEATSHRINK_MALLOC(sz);
|
||||
if (hsd == nullptr) return nullptr;
|
||||
if (!hsd) return nullptr;
|
||||
hsd->input_buffer_size = input_buffer_size;
|
||||
hsd->window_sz2 = window_sz2;
|
||||
hsd->lookahead_sz2 = lookahead_sz2;
|
||||
@@ -97,7 +124,7 @@ void heatshrink_decoder_reset(heatshrink_decoder *hsd) {
|
||||
/* Copy SIZE bytes into the decoder's input buffer, if it will fit. */
|
||||
HSD_sink_res heatshrink_decoder_sink(heatshrink_decoder *hsd,
|
||||
uint8_t *in_buf, size_t size, size_t *input_size) {
|
||||
if (hsd == nullptr || in_buf == nullptr || input_size == nullptr)
|
||||
if (!hsd || !in_buf || !input_size)
|
||||
return HSDR_SINK_ERROR_NULL;
|
||||
|
||||
size_t rem = HEATSHRINK_DECODER_INPUT_BUFFER_SIZE(hsd) - hsd->input_size;
|
||||
@@ -133,7 +160,7 @@ static HSD_state st_backref_count_lsb(heatshrink_decoder *hsd);
|
||||
static HSD_state st_yield_backref(heatshrink_decoder *hsd, output_info *oi);
|
||||
|
||||
HSD_poll_res heatshrink_decoder_poll(heatshrink_decoder *hsd, uint8_t *out_buf, size_t out_buf_size, size_t *output_size) {
|
||||
if (hsd == nullptr || out_buf == nullptr || output_size == nullptr)
|
||||
if (!hsd || !out_buf || !output_size)
|
||||
return HSDR_POLL_ERROR_NULL;
|
||||
|
||||
*output_size = 0;
|
||||
@@ -324,7 +351,7 @@ static uint16_t get_bits(heatshrink_decoder *hsd, uint8_t count) {
|
||||
}
|
||||
|
||||
HSD_finish_res heatshrink_decoder_finish(heatshrink_decoder *hsd) {
|
||||
if (hsd == nullptr) { return HSDR_FINISH_ERROR_NULL; }
|
||||
if (!hsd) return HSDR_FINISH_ERROR_NULL;
|
||||
switch (hsd->state) {
|
||||
case HSDS_TAG_BIT:
|
||||
return hsd->input_size == 0 ? HSDR_FINISH_DONE : HSDR_FINISH_MORE;
|
||||
@@ -353,3 +380,5 @@ static void push_byte(heatshrink_decoder *hsd, output_info *oi, uint8_t byte) {
|
||||
oi->buf[(*oi->output_size)++] = byte;
|
||||
(void)hsd;
|
||||
}
|
||||
|
||||
#endif // BINARY_FILE_TRANSFER
|
||||
|
27
Marlin/src/libs/heatshrink/heatshrink_decoder.h
Executable file → Normal file
27
Marlin/src/libs/heatshrink/heatshrink_decoder.h
Executable file → Normal file
@@ -1,13 +1,36 @@
|
||||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* libs/heatshrink/heatshrink_decoder.h
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "heatshrink_common.h"
|
||||
#include "heatshrink_config.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
typedef enum {
|
||||
HSDR_SINK_OK, /* data sunk, ready to poll */
|
||||
HSDR_SINK_FULL, /* out of space in internal buffer */
|
||||
|
90
Marlin/src/libs/hex_print.cpp
Normal file
90
Marlin/src/libs/hex_print.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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 "../inc/MarlinConfigPre.h"
|
||||
|
||||
#if NEED_HEX_PRINT
|
||||
|
||||
#include "hex_print.h"
|
||||
#include "../core/serial.h"
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
constexpr int byte_start = 4;
|
||||
static char _hex[] = "0x00000000";
|
||||
#else
|
||||
constexpr int byte_start = 0;
|
||||
static char _hex[] = "0x0000";
|
||||
#endif
|
||||
|
||||
char* hex_byte(const uint8_t b) {
|
||||
_hex[byte_start + 4] = hex_nybble(b >> 4);
|
||||
_hex[byte_start + 5] = hex_nybble(b);
|
||||
return &_hex[byte_start + 4];
|
||||
}
|
||||
|
||||
inline void _hex_word(const uint16_t w) {
|
||||
_hex[byte_start + 2] = hex_nybble(w >> 12);
|
||||
_hex[byte_start + 3] = hex_nybble(w >> 8);
|
||||
_hex[byte_start + 4] = hex_nybble(w >> 4);
|
||||
_hex[byte_start + 5] = hex_nybble(w);
|
||||
}
|
||||
|
||||
char* hex_word(const uint16_t w) {
|
||||
_hex_word(w);
|
||||
return &_hex[byte_start + 2];
|
||||
}
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
char* hex_long(const uintptr_t l) {
|
||||
_hex[2] = hex_nybble(l >> 28);
|
||||
_hex[3] = hex_nybble(l >> 24);
|
||||
_hex[4] = hex_nybble(l >> 20);
|
||||
_hex[5] = hex_nybble(l >> 16);
|
||||
_hex_word((uint16_t)(l & 0xFFFF));
|
||||
return &_hex[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
char* hex_address(const void * const w) {
|
||||
#ifdef CPU_32_BIT
|
||||
(void)hex_long((uintptr_t)w);
|
||||
#else
|
||||
(void)hex_word((uintptr_t)w);
|
||||
#endif
|
||||
return _hex;
|
||||
}
|
||||
|
||||
void print_hex_nybble(const uint8_t n) { SERIAL_CHAR(hex_nybble(n)); }
|
||||
void print_hex_byte(const uint8_t b) { SERIAL_ECHO(hex_byte(b)); }
|
||||
void print_hex_word(const uint16_t w) { SERIAL_ECHO(hex_word(w)); }
|
||||
void print_hex_address(const void * const w) { SERIAL_ECHO(hex_address(w)); }
|
||||
|
||||
void print_hex_long(const uint32_t w, const char delimiter) {
|
||||
SERIAL_ECHOPGM("0x");
|
||||
for (int B = 24; B >= 8; B -= 8) {
|
||||
print_hex_byte(w >> B);
|
||||
SERIAL_CHAR(delimiter);
|
||||
}
|
||||
print_hex_byte(w);
|
||||
}
|
||||
|
||||
#endif // NEED_HEX_PRINT
|
8
Marlin/src/libs/hex_print_routines.h → Marlin/src/libs/hex_print.h
Executable file → Normal file
8
Marlin/src/libs/hex_print_routines.h → Marlin/src/libs/hex_print.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -39,9 +39,3 @@ void print_hex_byte(const uint8_t b);
|
||||
void print_hex_word(const uint16_t w);
|
||||
void print_hex_address(const void * const w);
|
||||
void print_hex_long(const uint32_t w, const char delimiter);
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
typedef uint32_t ptr_int_t;
|
||||
#else
|
||||
typedef uint16_t ptr_int_t;
|
||||
#endif
|
@@ -1,90 +0,0 @@
|
||||
/**
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "../gcode/parser.h"
|
||||
|
||||
#if ANY(AUTO_BED_LEVELING_UBL, M100_FREE_MEMORY_WATCHER, DEBUG_GCODE_PARSER, TMC_DEBUG)
|
||||
|
||||
#include "hex_print_routines.h"
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
constexpr int byte_start = 4;
|
||||
static char _hex[] = "0x00000000";
|
||||
#else
|
||||
constexpr int byte_start = 0;
|
||||
static char _hex[] = "0x0000";
|
||||
#endif
|
||||
|
||||
char* hex_byte(const uint8_t b) {
|
||||
_hex[byte_start + 4] = hex_nybble(b >> 4);
|
||||
_hex[byte_start + 5] = hex_nybble(b);
|
||||
return &_hex[byte_start + 4];
|
||||
}
|
||||
|
||||
inline void _hex_word(const uint16_t w) {
|
||||
_hex[byte_start + 2] = hex_nybble(w >> 12);
|
||||
_hex[byte_start + 3] = hex_nybble(w >> 8);
|
||||
_hex[byte_start + 4] = hex_nybble(w >> 4);
|
||||
_hex[byte_start + 5] = hex_nybble(w);
|
||||
}
|
||||
|
||||
char* hex_word(const uint16_t w) {
|
||||
_hex_word(w);
|
||||
return &_hex[byte_start + 2];
|
||||
}
|
||||
|
||||
#ifdef CPU_32_BIT
|
||||
char* hex_long(const uint32_t l) {
|
||||
_hex[2] = hex_nybble(l >> 28);
|
||||
_hex[3] = hex_nybble(l >> 24);
|
||||
_hex[4] = hex_nybble(l >> 20);
|
||||
_hex[5] = hex_nybble(l >> 16);
|
||||
_hex_word((uint16_t)(l & 0xFFFF));
|
||||
return &_hex[2];
|
||||
}
|
||||
#endif
|
||||
|
||||
char* hex_address(const void * const w) {
|
||||
#ifdef CPU_32_BIT
|
||||
(void)hex_long((ptr_int_t)w);
|
||||
#else
|
||||
(void)hex_word((ptr_int_t)w);
|
||||
#endif
|
||||
return _hex;
|
||||
}
|
||||
|
||||
void print_hex_nybble(const uint8_t n) { SERIAL_CHAR(hex_nybble(n)); }
|
||||
void print_hex_byte(const uint8_t b) { SERIAL_ECHO(hex_byte(b)); }
|
||||
void print_hex_word(const uint16_t w) { SERIAL_ECHO(hex_word(w)); }
|
||||
void print_hex_address(const void * const w) { SERIAL_ECHO(hex_address(w)); }
|
||||
|
||||
void print_hex_long(const uint32_t w, const char delimiter) {
|
||||
SERIAL_ECHOPGM("0x");
|
||||
for (int B = 24; B >= 8; B -= 8){
|
||||
print_hex_byte(w >> B);
|
||||
SERIAL_CHAR(delimiter);
|
||||
}
|
||||
print_hex_byte(w);
|
||||
}
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL || M100_FREE_MEMORY_WATCHER || DEBUG_GCODE_PARSER
|
33
Marlin/src/libs/least_squares_fit.cpp
Executable file → Normal file
33
Marlin/src/libs/least_squares_fit.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -29,12 +29,11 @@
|
||||
* it saves roughly 10K of program memory. It also does not require all of
|
||||
* coordinates to be present during the calculations. Each point can be
|
||||
* probed and then discarded.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
#if ANY(AUTO_BED_LEVELING_UBL, AUTO_BED_LEVELING_LINEAR, Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
|
||||
#if NEED_LSF
|
||||
|
||||
#include "least_squares_fit.h"
|
||||
|
||||
@@ -47,24 +46,24 @@ int finish_incremental_LSF(struct linear_fit_data *lsf) {
|
||||
if (N == 0.0)
|
||||
return 1;
|
||||
|
||||
lsf->xbar /= N;
|
||||
lsf->ybar /= N;
|
||||
lsf->zbar /= N;
|
||||
lsf->x2bar = lsf->x2bar / N - sq(lsf->xbar);
|
||||
lsf->y2bar = lsf->y2bar / N - sq(lsf->ybar);
|
||||
lsf->z2bar = lsf->z2bar / N - sq(lsf->zbar);
|
||||
lsf->xybar = lsf->xybar / N - lsf->xbar * lsf->ybar;
|
||||
lsf->yzbar = lsf->yzbar / N - lsf->ybar * lsf->zbar;
|
||||
lsf->xzbar = lsf->xzbar / N - lsf->xbar * lsf->zbar;
|
||||
const float DD = lsf->x2bar * lsf->y2bar - sq(lsf->xybar);
|
||||
const float RN = 1.0f / N,
|
||||
xbar = lsf->xbar * RN,
|
||||
ybar = lsf->ybar * RN,
|
||||
zbar = lsf->zbar * RN,
|
||||
x2bar = lsf->x2bar * RN - sq(xbar),
|
||||
y2bar = lsf->y2bar * RN - sq(ybar),
|
||||
xybar = lsf->xybar * RN - xbar * ybar,
|
||||
yzbar = lsf->yzbar * RN - ybar * zbar,
|
||||
xzbar = lsf->xzbar * RN - xbar * zbar,
|
||||
DD = x2bar * y2bar - sq(xybar);
|
||||
|
||||
if (ABS(DD) <= 1e-10 * (lsf->max_absx + lsf->max_absy))
|
||||
return 1;
|
||||
|
||||
lsf->A = (lsf->yzbar * lsf->xybar - lsf->xzbar * lsf->y2bar) / DD;
|
||||
lsf->B = (lsf->xzbar * lsf->xybar - lsf->yzbar * lsf->x2bar) / DD;
|
||||
lsf->D = -(lsf->zbar + lsf->A * lsf->xbar + lsf->B * lsf->ybar);
|
||||
lsf->A = (yzbar * xybar - xzbar * y2bar) / DD;
|
||||
lsf->B = (xzbar * xybar - yzbar * x2bar) / DD;
|
||||
lsf->D = -(zbar + lsf->A * xbar + lsf->B * ybar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // AUTO_BED_LEVELING_UBL || ENABLED(AUTO_BED_LEVELING_LINEAR)
|
||||
#endif // NEED_LSF
|
||||
|
15
Marlin/src/libs/least_squares_fit.h
Executable file → Normal file
15
Marlin/src/libs/least_squares_fit.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -30,7 +30,6 @@
|
||||
* it saves roughly 10K of program memory. And even better... the data
|
||||
* fed into the algorithm does not need to all be present at the same time.
|
||||
* A point can be probed and its values fed into the algorithm and then discarded.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
@@ -38,7 +37,7 @@
|
||||
|
||||
struct linear_fit_data {
|
||||
float xbar, ybar, zbar,
|
||||
x2bar, y2bar, z2bar,
|
||||
x2bar, y2bar,
|
||||
xybar, xzbar, yzbar,
|
||||
max_absx, max_absy,
|
||||
A, B, D, N;
|
||||
@@ -48,7 +47,7 @@ inline void incremental_LSF_reset(struct linear_fit_data *lsf) {
|
||||
memset(lsf, 0, sizeof(linear_fit_data));
|
||||
}
|
||||
|
||||
inline void incremental_WLSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z, const float &w) {
|
||||
inline void incremental_WLSF(struct linear_fit_data *lsf, const_float_t x, const_float_t y, const_float_t z, const_float_t w) {
|
||||
// weight each accumulator by factor w, including the "number" of samples
|
||||
// (analogous to calling inc_LSF twice with same values to weight it by 2X)
|
||||
const float wx = w * x, wy = w * y, wz = w * z;
|
||||
@@ -57,7 +56,6 @@ inline void incremental_WLSF(struct linear_fit_data *lsf, const float &x, const
|
||||
lsf->zbar += wz;
|
||||
lsf->x2bar += wx * x;
|
||||
lsf->y2bar += wy * y;
|
||||
lsf->z2bar += wz * z;
|
||||
lsf->xybar += wx * y;
|
||||
lsf->xzbar += wx * z;
|
||||
lsf->yzbar += wy * z;
|
||||
@@ -65,17 +63,16 @@ inline void incremental_WLSF(struct linear_fit_data *lsf, const float &x, const
|
||||
lsf->max_absx = _MAX(ABS(wx), lsf->max_absx);
|
||||
lsf->max_absy = _MAX(ABS(wy), lsf->max_absy);
|
||||
}
|
||||
inline void incremental_WLSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const float &z, const float &w) {
|
||||
inline void incremental_WLSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const_float_t z, const_float_t w) {
|
||||
incremental_WLSF(lsf, pos.x, pos.y, z, w);
|
||||
}
|
||||
|
||||
inline void incremental_LSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z) {
|
||||
inline void incremental_LSF(struct linear_fit_data *lsf, const_float_t x, const_float_t y, const_float_t z) {
|
||||
lsf->xbar += x;
|
||||
lsf->ybar += y;
|
||||
lsf->zbar += z;
|
||||
lsf->x2bar += sq(x);
|
||||
lsf->y2bar += sq(y);
|
||||
lsf->z2bar += sq(z);
|
||||
lsf->xybar += x * y;
|
||||
lsf->xzbar += x * z;
|
||||
lsf->yzbar += y * z;
|
||||
@@ -83,7 +80,7 @@ inline void incremental_LSF(struct linear_fit_data *lsf, const float &x, const f
|
||||
lsf->max_absy = _MAX(ABS(y), lsf->max_absy);
|
||||
lsf->N += 1.0;
|
||||
}
|
||||
inline void incremental_LSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const float &z) {
|
||||
inline void incremental_LSF(struct linear_fit_data *lsf, const xy_pos_t &pos, const_float_t z) {
|
||||
incremental_LSF(lsf, pos.x, pos.y, z);
|
||||
}
|
||||
|
||||
|
122
Marlin/src/libs/nozzle.cpp
Executable file → Normal file
122
Marlin/src/libs/nozzle.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,10 @@ Nozzle nozzle;
|
||||
#include "../MarlinCore.h"
|
||||
#include "../module/motion.h"
|
||||
|
||||
#if NOZZLE_CLEAN_MIN_TEMP > 20
|
||||
#include "../module/temperature.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_FEATURE)
|
||||
|
||||
/**
|
||||
@@ -48,20 +52,27 @@ Nozzle nozzle;
|
||||
|
||||
// Move to the starting point
|
||||
#if ENABLED(NOZZLE_CLEAN_NO_Z)
|
||||
do_blocking_move_to_xy(start);
|
||||
#if ENABLED(NOZZLE_CLEAN_NO_Y)
|
||||
do_blocking_move_to_x(start.x);
|
||||
#else
|
||||
do_blocking_move_to_xy(start);
|
||||
#endif
|
||||
#else
|
||||
do_blocking_move_to(start);
|
||||
#endif
|
||||
|
||||
// Start the stroke pattern
|
||||
LOOP_L_N(i, strokes >> 1) {
|
||||
do_blocking_move_to_xy(end);
|
||||
do_blocking_move_to_xy(start);
|
||||
#if ENABLED(NOZZLE_CLEAN_NO_Y)
|
||||
do_blocking_move_to_x(end.x);
|
||||
do_blocking_move_to_x(start.x);
|
||||
#else
|
||||
do_blocking_move_to_xy(end);
|
||||
do_blocking_move_to_xy(start);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
do_blocking_move_to(oldpos);
|
||||
#endif
|
||||
TERN_(NOZZLE_CLEAN_GOBACK, do_blocking_move_to(oldpos));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +119,7 @@ Nozzle nozzle;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
do_blocking_move_to(back);
|
||||
#endif
|
||||
TERN_(NOZZLE_CLEAN_GOBACK, do_blocking_move_to(back));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,18 +130,13 @@ Nozzle nozzle;
|
||||
* @param strokes number of strokes to execute
|
||||
* @param radius radius of circle
|
||||
*/
|
||||
void Nozzle::circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const float &radius) {
|
||||
void Nozzle::circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const_float_t radius) {
|
||||
if (strokes == 0) return;
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
const xyz_pos_t back = current_position;
|
||||
#endif
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_NO_Z)
|
||||
do_blocking_move_to_xy(start);
|
||||
#else
|
||||
do_blocking_move_to(start);
|
||||
#endif
|
||||
TERN(NOZZLE_CLEAN_NO_Z, do_blocking_move_to_xy, do_blocking_move_to)(start);
|
||||
|
||||
LOOP_L_N(s, strokes)
|
||||
LOOP_L_N(i, NOZZLE_CLEAN_CIRCLE_FN)
|
||||
@@ -144,9 +148,7 @@ Nozzle nozzle;
|
||||
// Let's be safe
|
||||
do_blocking_move_to_xy(start);
|
||||
|
||||
#if ENABLED(NOZZLE_CLEAN_GOBACK)
|
||||
do_blocking_move_to(back);
|
||||
#endif
|
||||
TERN_(NOZZLE_CLEAN_GOBACK, do_blocking_move_to(back));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,25 +158,66 @@ Nozzle nozzle;
|
||||
* @param pattern one of the available patterns
|
||||
* @param argument depends on the cleaning pattern
|
||||
*/
|
||||
void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const uint8_t cleans) {
|
||||
void Nozzle::clean(const uint8_t &pattern, const uint8_t &strokes, const_float_t radius, const uint8_t &objects, const uint8_t cleans) {
|
||||
xyz_pos_t start[HOTENDS] = NOZZLE_CLEAN_START_POINT, end[HOTENDS] = NOZZLE_CLEAN_END_POINT, middle[HOTENDS] = NOZZLE_CLEAN_CIRCLE_MIDDLE;
|
||||
|
||||
const uint8_t arrPos = ANY(SINGLENOZZLE, MIXING_EXTRUDER) ? 0 : active_extruder;
|
||||
|
||||
#if NOZZLE_CLEAN_MIN_TEMP > 20
|
||||
if (thermalManager.degTargetHotend(arrPos) < NOZZLE_CLEAN_MIN_TEMP) {
|
||||
#if ENABLED(NOZZLE_CLEAN_HEATUP)
|
||||
SERIAL_ECHOLNPGM("Nozzle too Cold - Heating");
|
||||
thermalManager.setTargetHotend(NOZZLE_CLEAN_MIN_TEMP, arrPos);
|
||||
thermalManager.wait_for_hotend(arrPos);
|
||||
#else
|
||||
SERIAL_ECHOLNPGM("Nozzle too cold - Skipping wipe");
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_SOFTWARE_ENDSTOPS
|
||||
|
||||
#define LIMIT_AXIS(A) do{ \
|
||||
LIMIT( start[arrPos].A, soft_endstop.min.A, soft_endstop.max.A); \
|
||||
LIMIT(middle[arrPos].A, soft_endstop.min.A, soft_endstop.max.A); \
|
||||
LIMIT( end[arrPos].A, soft_endstop.min.A, soft_endstop.max.A); \
|
||||
}while(0)
|
||||
|
||||
if (soft_endstop.enabled()) {
|
||||
|
||||
LIMIT_AXIS(x);
|
||||
LIMIT_AXIS(y);
|
||||
LIMIT_AXIS(z);
|
||||
const bool radiusOutOfRange = (middle[arrPos].x + radius > soft_endstop.max.x)
|
||||
|| (middle[arrPos].x - radius < soft_endstop.min.x)
|
||||
|| (middle[arrPos].y + radius > soft_endstop.max.y)
|
||||
|| (middle[arrPos].y - radius < soft_endstop.min.y);
|
||||
if (radiusOutOfRange && pattern == 2) {
|
||||
SERIAL_ECHOLNPGM("Warning: Radius Out of Range");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (pattern == 2) {
|
||||
if (!(cleans & (_BV(X_AXIS) | _BV(Y_AXIS)))) {
|
||||
SERIAL_ECHOLNPGM("Warning : Clean Circle requires XY");
|
||||
SERIAL_ECHOLNPGM("Warning: Clean Circle requires XY");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!TEST(cleans, X_AXIS)) start[active_extruder].x = end[active_extruder].x = current_position.x;
|
||||
if (!TEST(cleans, Y_AXIS)) start[active_extruder].y = end[active_extruder].y = current_position.y;
|
||||
if (!TEST(cleans, X_AXIS)) start[arrPos].x = end[arrPos].x = current_position.x;
|
||||
if (!TEST(cleans, Y_AXIS)) start[arrPos].y = end[arrPos].y = current_position.y;
|
||||
}
|
||||
if (!TEST(cleans, Z_AXIS)) start[active_extruder].z = end[active_extruder].z = current_position.z;
|
||||
if (!TEST(cleans, Z_AXIS)) start[arrPos].z = end[arrPos].z = current_position.z;
|
||||
|
||||
switch (pattern) {
|
||||
case 1: zigzag(start[active_extruder], end[active_extruder], strokes, objects); break;
|
||||
case 2: circle(start[active_extruder], middle[active_extruder], strokes, radius); break;
|
||||
default: stroke(start[active_extruder], end[active_extruder], strokes);
|
||||
case 1: zigzag(start[arrPos], end[arrPos], strokes, objects); break;
|
||||
case 2: circle(start[arrPos], middle[arrPos], strokes, radius); break;
|
||||
default: stroke(start[arrPos], end[arrPos], strokes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,6 +225,18 @@ Nozzle nozzle;
|
||||
|
||||
#if ENABLED(NOZZLE_PARK_FEATURE)
|
||||
|
||||
float Nozzle::park_mode_0_height(const_float_t park_z) {
|
||||
// Apply a minimum raise, if specified. Use park.z as a minimum height instead.
|
||||
return _MAX(park_z, // Minimum height over 0 based on input
|
||||
_MIN(Z_MAX_POS, // Maximum height is fixed
|
||||
#ifdef NOZZLE_PARK_Z_RAISE_MIN
|
||||
NOZZLE_PARK_Z_RAISE_MIN + // Minimum raise...
|
||||
#endif
|
||||
current_position.z // ...over current position
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
void Nozzle::park(const uint8_t z_action, const xyz_pos_t &park/*=NOZZLE_PARK_POINT*/) {
|
||||
constexpr feedRate_t fr_xy = NOZZLE_PARK_XY_FEEDRATE, fr_z = NOZZLE_PARK_Z_FEEDRATE;
|
||||
|
||||
@@ -194,11 +249,16 @@ Nozzle nozzle;
|
||||
do_blocking_move_to_z(_MIN(current_position.z + park.z, Z_MAX_POS), fr_z);
|
||||
break;
|
||||
|
||||
default: // Raise to at least the Z-park height
|
||||
do_blocking_move_to_z(_MAX(park.z, current_position.z), fr_z);
|
||||
default: // Raise by NOZZLE_PARK_Z_RAISE_MIN, use park.z as a minimum height
|
||||
do_blocking_move_to_z(park_mode_0_height(park.z), fr_z);
|
||||
break;
|
||||
}
|
||||
|
||||
do_blocking_move_to_xy(park, fr_xy);
|
||||
do_blocking_move_to_xy(
|
||||
TERN(NOZZLE_PARK_Y_ONLY, current_position, park).x,
|
||||
TERN(NOZZLE_PARK_X_ONLY, current_position, park).y,
|
||||
fr_xy
|
||||
);
|
||||
|
||||
report_current_position();
|
||||
}
|
||||
|
7
Marlin/src/libs/nozzle.h
Executable file → Normal file
7
Marlin/src/libs/nozzle.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -62,7 +62,7 @@ class Nozzle {
|
||||
* @param strokes number of strokes to execute
|
||||
* @param radius radius of circle
|
||||
*/
|
||||
static void circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const float &radius) _Os;
|
||||
static void circle(const xyz_pos_t &start, const xyz_pos_t &middle, const uint8_t &strokes, const_float_t radius) _Os;
|
||||
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
|
||||
@@ -77,12 +77,13 @@ class Nozzle {
|
||||
* @param pattern one of the available patterns
|
||||
* @param argument depends on the cleaning pattern
|
||||
*/
|
||||
static void clean(const uint8_t &pattern, const uint8_t &strokes, const float &radius, const uint8_t &objects, const uint8_t cleans) _Os;
|
||||
static void clean(const uint8_t &pattern, const uint8_t &strokes, const_float_t radius, const uint8_t &objects, const uint8_t cleans) _Os;
|
||||
|
||||
#endif // NOZZLE_CLEAN_FEATURE
|
||||
|
||||
#if ENABLED(NOZZLE_PARK_FEATURE)
|
||||
|
||||
static float park_mode_0_height(const_float_t park_z) _Os;
|
||||
static void park(const uint8_t z_action, const xyz_pos_t &park=NOZZLE_PARK_POINT) _Os;
|
||||
|
||||
#endif
|
||||
|
128
Marlin/src/libs/numtostr.cpp
Executable file → Normal file
128
Marlin/src/libs/numtostr.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -31,17 +31,23 @@ char conv[8] = { 0 };
|
||||
#define DIGIMOD(n, f) DIGIT((n)/(f) % 10)
|
||||
#define RJDIGIT(n, f) ((n) >= (f) ? DIGIMOD(n, f) : ' ')
|
||||
#define MINUSOR(n, alt) (n >= 0 ? (alt) : (n = -n, '-'))
|
||||
#define INTFLOAT(V,N) (((V) * 10 * pow(10, N) + ((V) < 0 ? -5: 5)) / 10) // pow10?
|
||||
#define UINTFLOAT(V,N) INTFLOAT((V) < 0 ? -(V) : (V), N)
|
||||
|
||||
// Convert a full-range unsigned 8bit int to a percentage
|
||||
const char* ui8tostr4pctrj(const uint8_t i) {
|
||||
const uint8_t n = ui8_to_percent(i);
|
||||
conv[3] = RJDIGIT(n, 100);
|
||||
conv[4] = RJDIGIT(n, 10);
|
||||
conv[5] = DIGIMOD(n, 1);
|
||||
// Format uint8_t (0-100) as rj string with 123% / _12% / __1% format
|
||||
const char* pcttostrpctrj(const uint8_t i) {
|
||||
conv[3] = RJDIGIT(i, 100);
|
||||
conv[4] = RJDIGIT(i, 10);
|
||||
conv[5] = DIGIMOD(i, 1);
|
||||
conv[6] = '%';
|
||||
return &conv[3];
|
||||
}
|
||||
|
||||
// Convert uint8_t (0-255) to a percentage, format as above
|
||||
const char* ui8tostr4pctrj(const uint8_t i) {
|
||||
return pcttostrpctrj(ui8_to_percent(i));
|
||||
}
|
||||
|
||||
// Convert unsigned 8bit int to string 123 format
|
||||
const char* ui8tostr3rj(const uint8_t i) {
|
||||
conv[4] = RJDIGIT(i, 100);
|
||||
@@ -50,6 +56,13 @@ const char* ui8tostr3rj(const uint8_t i) {
|
||||
return &conv[4];
|
||||
}
|
||||
|
||||
// Convert uint8_t to string with 12 format
|
||||
const char* ui8tostr2(const uint8_t i) {
|
||||
conv[5] = DIGIMOD(i, 10);
|
||||
conv[6] = DIGIMOD(i, 1);
|
||||
return &conv[5];
|
||||
}
|
||||
|
||||
// Convert signed 8bit int to rj string with 123 or -12 format
|
||||
const char* i8tostr3rj(const int8_t x) {
|
||||
int xx = x;
|
||||
@@ -164,9 +177,18 @@ const char* i16tostr4signrj(const int16_t i) {
|
||||
return &conv[3];
|
||||
}
|
||||
|
||||
// Convert unsigned float to string with 1.1 format
|
||||
const char* ftostr11ns(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 1);
|
||||
conv[4] = DIGIMOD(i, 10);
|
||||
conv[5] = '.';
|
||||
conv[6] = DIGIMOD(i, 1);
|
||||
return &conv[4];
|
||||
}
|
||||
|
||||
// Convert unsigned float to string with 1.23 format
|
||||
const char* ftostr12ns(const float &f) {
|
||||
const long i = ((f < 0 ? -f : f) * 1000 + 5) / 10;
|
||||
const char* ftostr12ns(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 2);
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
conv[4] = '.';
|
||||
conv[5] = DIGIMOD(i, 10);
|
||||
@@ -174,10 +196,31 @@ const char* ftostr12ns(const float &f) {
|
||||
return &conv[3];
|
||||
}
|
||||
|
||||
// Convert unsigned float to string with 12.3 format
|
||||
const char* ftostr31ns(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 1);
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
conv[4] = DIGIMOD(i, 10);
|
||||
conv[5] = '.';
|
||||
conv[6] = DIGIMOD(i, 1);
|
||||
return &conv[3];
|
||||
}
|
||||
|
||||
// Convert unsigned float to string with 123.4 format
|
||||
const char* ftostr41ns(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 1);
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
conv[4] = DIGIMOD(i, 10);
|
||||
conv[5] = '.';
|
||||
conv[6] = DIGIMOD(i, 1);
|
||||
return &conv[2];
|
||||
}
|
||||
|
||||
// Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
|
||||
const char* ftostr42_52(const float &f) {
|
||||
const char* ftostr42_52(const_float_t f) {
|
||||
if (f <= -10 || f >= 100) return ftostr52(f); // -23.45 / 123.45
|
||||
long i = (f * 1000 + (f < 0 ? -5: 5)) / 10;
|
||||
long i = INTFLOAT(f, 2);
|
||||
conv[2] = (f >= 0 && f < 10) ? ' ' : MINUSOR(i, DIGIMOD(i, 1000));
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
conv[4] = '.';
|
||||
@@ -187,8 +230,8 @@ const char* ftostr42_52(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to fixed-length string with 023.45 / -23.45 format
|
||||
const char* ftostr52(const float &f) {
|
||||
long i = (f * 1000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr52(const_float_t f) {
|
||||
long i = INTFLOAT(f, 2);
|
||||
conv[1] = MINUSOR(i, DIGIMOD(i, 10000));
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
@@ -199,9 +242,9 @@ const char* ftostr52(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to fixed-length string with 12.345 / _2.345 / -2.345 or -23.45 / 123.45 format
|
||||
const char* ftostr53_63(const float &f) {
|
||||
const char* ftostr53_63(const_float_t f) {
|
||||
if (f <= -10 || f >= 100) return ftostr63(f); // -23.456 / 123.456
|
||||
long i = (f * 10000 + (f < 0 ? -5: 5)) / 10;
|
||||
long i = INTFLOAT(f, 3);
|
||||
conv[1] = (f >= 0 && f < 10) ? ' ' : MINUSOR(i, DIGIMOD(i, 10000));
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
conv[3] = '.';
|
||||
@@ -212,8 +255,8 @@ const char* ftostr53_63(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to fixed-length string with 023.456 / -23.456 format
|
||||
const char* ftostr63(const float &f) {
|
||||
long i = (f * 10000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr63(const_float_t f) {
|
||||
long i = INTFLOAT(f, 3);
|
||||
conv[0] = MINUSOR(i, DIGIMOD(i, 100000));
|
||||
conv[1] = DIGIMOD(i, 10000);
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
@@ -227,8 +270,8 @@ const char* ftostr63(const float &f) {
|
||||
#if ENABLED(LCD_DECIMAL_SMALL_XY)
|
||||
|
||||
// Convert float to rj string with 1234, _123, -123, _-12, 12.3, _1.2, or -1.2 format
|
||||
const char* ftostr4sign(const float &f) {
|
||||
const int i = (f * 100 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr4sign(const_float_t f) {
|
||||
const int i = INTFLOAT(f, 1);
|
||||
if (!WITHIN(i, -99, 999)) return i16tostr4signrj((int)f);
|
||||
const bool neg = i < 0;
|
||||
const int ii = neg ? -i : i;
|
||||
@@ -241,9 +284,20 @@ const char* ftostr63(const float &f) {
|
||||
|
||||
#endif
|
||||
|
||||
// Convert float to fixed-length string with +12.3 / -12.3 format
|
||||
const char* ftostr31sign(const_float_t f) {
|
||||
int i = INTFLOAT(f, 1);
|
||||
conv[2] = MINUSOR(i, '+');
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
conv[4] = DIGIMOD(i, 10);
|
||||
conv[5] = '.';
|
||||
conv[6] = DIGIMOD(i, 1);
|
||||
return &conv[2];
|
||||
}
|
||||
|
||||
// Convert float to fixed-length string with +123.4 / -123.4 format
|
||||
const char* ftostr41sign(const float &f) {
|
||||
int i = (f * 100 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr41sign(const_float_t f) {
|
||||
int i = INTFLOAT(f, 1);
|
||||
conv[1] = MINUSOR(i, '+');
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
conv[3] = DIGIMOD(i, 100);
|
||||
@@ -254,8 +308,8 @@ const char* ftostr41sign(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
|
||||
const char* ftostr43sign(const float &f, char plus/*=' '*/) {
|
||||
long i = (f * 10000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr43sign(const_float_t f, char plus/*=' '*/) {
|
||||
long i = INTFLOAT(f, 3);
|
||||
conv[1] = i ? MINUSOR(i, plus) : ' ';
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
conv[3] = '.';
|
||||
@@ -266,8 +320,8 @@ const char* ftostr43sign(const float &f, char plus/*=' '*/) {
|
||||
}
|
||||
|
||||
// Convert signed float to string (5 digit) with -1.2345 / _0.0000 / +1.2345 format
|
||||
const char* ftostr54sign(const float &f, char plus/*=' '*/) {
|
||||
long i = (f * 100000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr54sign(const_float_t f, char plus/*=' '*/) {
|
||||
long i = INTFLOAT(f, 4);
|
||||
conv[0] = i ? MINUSOR(i, plus) : ' ';
|
||||
conv[1] = DIGIMOD(i, 10000);
|
||||
conv[2] = '.';
|
||||
@@ -279,14 +333,14 @@ const char* ftostr54sign(const float &f, char plus/*=' '*/) {
|
||||
}
|
||||
|
||||
// Convert unsigned float to rj string with 12345 format
|
||||
const char* ftostr5rj(const float &f) {
|
||||
const long i = ((f < 0 ? -f : f) * 10 + 5) / 10;
|
||||
const char* ftostr5rj(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 0);
|
||||
return ui16tostr5rj(i);
|
||||
}
|
||||
|
||||
// Convert signed float to string with +1234.5 format
|
||||
const char* ftostr51sign(const float &f) {
|
||||
long i = (f * 100 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr51sign(const_float_t f) {
|
||||
long i = INTFLOAT(f, 1);
|
||||
conv[0] = MINUSOR(i, '+');
|
||||
conv[1] = DIGIMOD(i, 10000);
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
@@ -298,8 +352,8 @@ const char* ftostr51sign(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to string with +123.45 format
|
||||
const char* ftostr52sign(const float &f) {
|
||||
long i = (f * 1000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr52sign(const_float_t f) {
|
||||
long i = INTFLOAT(f, 2);
|
||||
conv[0] = MINUSOR(i, '+');
|
||||
conv[1] = DIGIMOD(i, 10000);
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
@@ -311,8 +365,8 @@ const char* ftostr52sign(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to string with +12.345 format
|
||||
const char* ftostr53sign(const float &f) {
|
||||
long i = (f * 10000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr53sign(const_float_t f) {
|
||||
long i = INTFLOAT(f, 3);
|
||||
conv[0] = MINUSOR(i, '+');
|
||||
conv[1] = DIGIMOD(i, 10000);
|
||||
conv[2] = DIGIMOD(i, 1000);
|
||||
@@ -324,8 +378,8 @@ const char* ftostr53sign(const float &f) {
|
||||
}
|
||||
|
||||
// Convert unsigned float to string with ____4.5, __34.5, _234.5, 1234.5 format
|
||||
const char* ftostr51rj(const float &f) {
|
||||
const long i = ((f < 0 ? -f : f) * 100 + 5) / 10;
|
||||
const char* ftostr51rj(const_float_t f) {
|
||||
const long i = UINTFLOAT(f, 1);
|
||||
conv[0] = ' ';
|
||||
conv[1] = RJDIGIT(i, 10000);
|
||||
conv[2] = RJDIGIT(i, 1000);
|
||||
@@ -337,8 +391,8 @@ const char* ftostr51rj(const float &f) {
|
||||
}
|
||||
|
||||
// Convert signed float to space-padded string with -_23.4_ format
|
||||
const char* ftostr52sp(const float &f) {
|
||||
long i = (f * 1000 + (f < 0 ? -5: 5)) / 10;
|
||||
const char* ftostr52sp(const_float_t f) {
|
||||
long i = INTFLOAT(f, 2);
|
||||
uint8_t dig;
|
||||
conv[0] = MINUSOR(i, ' ');
|
||||
conv[1] = RJDIGIT(i, 10000);
|
||||
|
63
Marlin/src/libs/numtostr.h
Executable file → Normal file
63
Marlin/src/libs/numtostr.h
Executable file → Normal file
@@ -16,16 +16,23 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
#include "../core/types.h"
|
||||
|
||||
// Convert a full-range unsigned 8bit int to a percentage
|
||||
// Format uint8_t (0-100) as rj string with 123% / _12% / __1% format
|
||||
const char* pcttostrpctrj(const uint8_t i);
|
||||
|
||||
// Convert uint8_t (0-255) to a percentage, format as above
|
||||
const char* ui8tostr4pctrj(const uint8_t i);
|
||||
|
||||
// Convert uint8_t to string with 12 format
|
||||
const char* ui8tostr2(const uint8_t x);
|
||||
|
||||
// Convert uint8_t to string with 123 format
|
||||
const char* ui8tostr3rj(const uint8_t i);
|
||||
|
||||
@@ -55,59 +62,67 @@ const char* i16tostr3left(const int16_t xx);
|
||||
// Convert signed int to rj string with _123, -123, _-12, or __-1 format
|
||||
const char* i16tostr4signrj(const int16_t x);
|
||||
|
||||
// Convert unsigned float to string with 1.2 format
|
||||
const char* ftostr11ns(const_float_t x);
|
||||
|
||||
// Convert unsigned float to string with 1.23 format
|
||||
const char* ftostr12ns(const float &x);
|
||||
const char* ftostr12ns(const_float_t x);
|
||||
|
||||
// Convert unsigned float to string with 12.3 format
|
||||
const char* ftostr31ns(const_float_t x);
|
||||
|
||||
// Convert unsigned float to string with 123.4 format
|
||||
const char* ftostr41ns(const_float_t x);
|
||||
|
||||
// Convert signed float to fixed-length string with 12.34 / _2.34 / -2.34 or -23.45 / 123.45 format
|
||||
const char* ftostr42_52(const float &x);
|
||||
const char* ftostr42_52(const_float_t x);
|
||||
|
||||
// Convert signed float to fixed-length string with 023.45 / -23.45 format
|
||||
const char* ftostr52(const float &x);
|
||||
const char* ftostr52(const_float_t x);
|
||||
|
||||
// Convert signed float to fixed-length string with 12.345 / -2.345 or 023.456 / -23.456 format
|
||||
const char* ftostr53_63(const float &x);
|
||||
const char* ftostr53_63(const_float_t x);
|
||||
|
||||
// Convert signed float to fixed-length string with 023.456 / -23.456 format
|
||||
const char* ftostr63(const float &x);
|
||||
const char* ftostr63(const_float_t x);
|
||||
|
||||
// Convert float to fixed-length string with +12.3 / -12.3 format
|
||||
const char* ftostr31sign(const_float_t x);
|
||||
|
||||
// Convert float to fixed-length string with +123.4 / -123.4 format
|
||||
const char* ftostr41sign(const float &x);
|
||||
const char* ftostr41sign(const_float_t x);
|
||||
|
||||
// Convert signed float to string (6 digit) with -1.234 / _0.000 / +1.234 format
|
||||
const char* ftostr43sign(const float &x, char plus=' ');
|
||||
const char* ftostr43sign(const_float_t x, char plus=' ');
|
||||
|
||||
// Convert signed float to string (5 digit) with -1.2345 / _0.0000 / +1.2345 format
|
||||
const char* ftostr54sign(const float &x, char plus=' ');
|
||||
const char* ftostr54sign(const_float_t x, char plus=' ');
|
||||
|
||||
// Convert unsigned float to rj string with 12345 format
|
||||
const char* ftostr5rj(const float &x);
|
||||
const char* ftostr5rj(const_float_t x);
|
||||
|
||||
// Convert signed float to string with +1234.5 format
|
||||
const char* ftostr51sign(const float &x);
|
||||
const char* ftostr51sign(const_float_t x);
|
||||
|
||||
// Convert signed float to space-padded string with -_23.4_ format
|
||||
const char* ftostr52sp(const float &x);
|
||||
const char* ftostr52sp(const_float_t x);
|
||||
|
||||
// Convert signed float to string with +123.45 format
|
||||
const char* ftostr52sign(const float &x);
|
||||
const char* ftostr52sign(const_float_t x);
|
||||
|
||||
// Convert signed float to string with +12.345 format
|
||||
const char* ftostr53sign(const float &f);
|
||||
const char* ftostr53sign(const_float_t f);
|
||||
|
||||
// Convert unsigned float to string with 1234.5 format omitting trailing zeros
|
||||
const char* ftostr51rj(const float &x);
|
||||
|
||||
#include "../core/macros.h"
|
||||
const char* ftostr51rj(const_float_t x);
|
||||
|
||||
// Convert float to rj string with 123 or -12 format
|
||||
FORCE_INLINE const char* ftostr3(const float &x) { return i16tostr3rj(int16_t(x + (x < 0 ? -0.5f : 0.5f))); }
|
||||
|
||||
#include "../inc/MarlinConfigPre.h"
|
||||
FORCE_INLINE const char* ftostr3(const_float_t x) { return i16tostr3rj(int16_t(x + (x < 0 ? -0.5f : 0.5f))); }
|
||||
|
||||
#if ENABLED(LCD_DECIMAL_SMALL_XY)
|
||||
// Convert float to rj string with 1234, _123, 12.3, _1.2, -123, _-12, or -1.2 format
|
||||
const char* ftostr4sign(const float &fx);
|
||||
const char* ftostr4sign(const_float_t fx);
|
||||
#else
|
||||
// Convert float to rj string with 1234, _123, -123, __12, _-12, ___1, or __-1 format
|
||||
FORCE_INLINE const char* ftostr4sign(const float &x) { return i16tostr4signrj(int16_t(x + (x < 0 ? -0.5f : 0.5f))); }
|
||||
FORCE_INLINE const char* ftostr4sign(const_float_t x) { return i16tostr4signrj(int16_t(x + (x < 0 ? -0.5f : 0.5f))); }
|
||||
#endif
|
||||
|
12
Marlin/src/libs/private_spi.h
Executable file → Normal file
12
Marlin/src/libs/private_spi.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -35,15 +35,15 @@ class SPIclass {
|
||||
|
||||
// Hardware SPI
|
||||
template<>
|
||||
class SPIclass<MISO_PIN, MOSI_PIN, SCK_PIN> {
|
||||
class SPIclass<SD_MISO_PIN, SD_MOSI_PIN, SD_SCK_PIN> {
|
||||
public:
|
||||
FORCE_INLINE static void init() {
|
||||
OUT_WRITE(SCK_PIN, LOW);
|
||||
OUT_WRITE(MOSI_PIN, HIGH);
|
||||
SET_INPUT_PULLUP(MISO_PIN);
|
||||
OUT_WRITE(SD_SCK_PIN, LOW);
|
||||
OUT_WRITE(SD_MOSI_PIN, HIGH);
|
||||
SET_INPUT_PULLUP(SD_MISO_PIN);
|
||||
}
|
||||
FORCE_INLINE static uint8_t receive() {
|
||||
#if defined(__AVR__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#if defined(__AVR__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
|
||||
SPDR = 0;
|
||||
for (;!TEST(SPSR, SPIF););
|
||||
return SPDR;
|
||||
|
12
Marlin/src/libs/softspi.h
Executable file → Normal file
12
Marlin/src/libs/softspi.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -25,11 +25,7 @@
|
||||
// Based on https://github.com/niteris/ArduinoSoftSpi
|
||||
//
|
||||
|
||||
#include "../HAL/shared/Marduino.h"
|
||||
|
||||
#ifndef FORCE_INLINE
|
||||
#define FORCE_INLINE inline __attribute__((always_inline))
|
||||
#endif
|
||||
#include "../HAL/shared/Marduino.h" // CORE_TEENSY
|
||||
|
||||
#define nop __asm__ volatile ("nop") // NOP for timing
|
||||
|
||||
@@ -715,7 +711,7 @@ class SoftSPI {
|
||||
|
||||
FORCE_INLINE bool MODE_CPHA(uint8_t mode) { return bool(mode & 1); }
|
||||
FORCE_INLINE bool MODE_CPOL(uint8_t mode) { return bool(mode & 2); }
|
||||
FORCE_INLINE void receiveBit(uint8_t bit, uint8_t* data) {
|
||||
FORCE_INLINE void receiveBit(uint8_t bit, uint8_t *data) {
|
||||
if (MODE_CPHA(Mode)) fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
nop;
|
||||
nop;
|
||||
@@ -734,7 +730,7 @@ class SoftSPI {
|
||||
if (!MODE_CPHA(Mode)) fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
|
||||
FORCE_INLINE void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
|
||||
FORCE_INLINE void transferBit(uint8_t bit, uint8_t *rxData, uint8_t txData) {
|
||||
if (MODE_CPHA(Mode)) fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
fastDigitalWrite(MosiPin, txData & _BV(bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
|
39
Marlin/src/libs/stopwatch.cpp
Executable file → Normal file
39
Marlin/src/libs/stopwatch.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -34,14 +34,10 @@ millis_t Stopwatch::startTimestamp;
|
||||
millis_t Stopwatch::stopTimestamp;
|
||||
|
||||
bool Stopwatch::stop() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("stop"));
|
||||
#endif
|
||||
Stopwatch::debug(PSTR("stop"));
|
||||
|
||||
if (isRunning() || isPaused()) {
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
ExtUI::onPrintTimerStopped();
|
||||
#endif
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onPrintTimerStopped());
|
||||
state = STOPPED;
|
||||
stopTimestamp = millis();
|
||||
return true;
|
||||
@@ -50,14 +46,10 @@ bool Stopwatch::stop() {
|
||||
}
|
||||
|
||||
bool Stopwatch::pause() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("pause"));
|
||||
#endif
|
||||
Stopwatch::debug(PSTR("pause"));
|
||||
|
||||
if (isRunning()) {
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
ExtUI::onPrintTimerPaused();
|
||||
#endif
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onPrintTimerPaused());
|
||||
state = PAUSED;
|
||||
stopTimestamp = millis();
|
||||
return true;
|
||||
@@ -66,13 +58,9 @@ bool Stopwatch::pause() {
|
||||
}
|
||||
|
||||
bool Stopwatch::start() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("start"));
|
||||
#endif
|
||||
Stopwatch::debug(PSTR("start"));
|
||||
|
||||
#if ENABLED(EXTENSIBLE_UI)
|
||||
ExtUI::onPrintTimerStarted();
|
||||
#endif
|
||||
TERN_(EXTENSIBLE_UI, ExtUI::onPrintTimerStarted());
|
||||
|
||||
if (!isRunning()) {
|
||||
if (isPaused()) accumulator = duration();
|
||||
@@ -86,18 +74,14 @@ bool Stopwatch::start() {
|
||||
}
|
||||
|
||||
void Stopwatch::resume(const millis_t with_time) {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("resume"));
|
||||
#endif
|
||||
Stopwatch::debug(PSTR("resume"));
|
||||
|
||||
reset();
|
||||
if ((accumulator = with_time)) state = RUNNING;
|
||||
}
|
||||
|
||||
void Stopwatch::reset() {
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
Stopwatch::debug(PSTR("reset"));
|
||||
#endif
|
||||
Stopwatch::debug(PSTR("reset"));
|
||||
|
||||
state = STOPPED;
|
||||
startTimestamp = 0;
|
||||
@@ -106,8 +90,7 @@ void Stopwatch::reset() {
|
||||
}
|
||||
|
||||
millis_t Stopwatch::duration() {
|
||||
return ((isRunning() ? millis() : stopTimestamp)
|
||||
- startTimestamp) / 1000UL + accumulator;
|
||||
return accumulator + MS_TO_SEC((isRunning() ? millis() : stopTimestamp) - startTimestamp);
|
||||
}
|
||||
|
||||
#if ENABLED(DEBUG_STOPWATCH)
|
||||
@@ -115,7 +98,7 @@ millis_t Stopwatch::duration() {
|
||||
void Stopwatch::debug(const char func[]) {
|
||||
if (DEBUGGING(INFO)) {
|
||||
SERIAL_ECHOPGM("Stopwatch::");
|
||||
serialprintPGM(func);
|
||||
SERIAL_ECHOPGM_P(func);
|
||||
SERIAL_ECHOLNPGM("()");
|
||||
}
|
||||
}
|
||||
|
7
Marlin/src/libs/stopwatch.h
Executable file → Normal file
7
Marlin/src/libs/stopwatch.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -56,6 +56,7 @@ class Stopwatch {
|
||||
* @return true on success
|
||||
*/
|
||||
static bool stop();
|
||||
static inline bool abort() { return stop(); } // Alias by default
|
||||
|
||||
/**
|
||||
* @brief Pause the stopwatch
|
||||
@@ -114,5 +115,9 @@ class Stopwatch {
|
||||
*/
|
||||
static void debug(const char func[]);
|
||||
|
||||
#else
|
||||
|
||||
static inline void debug(const char[]) {}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
34
Marlin/src/libs/vector_3.cpp
Executable file → Normal file
34
Marlin/src/libs/vector_3.cpp
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -52,10 +52,9 @@
|
||||
*/
|
||||
|
||||
vector_3 vector_3::cross(const vector_3 &left, const vector_3 &right) {
|
||||
const xyz_float_t &lv = left, &rv = right;
|
||||
return vector_3(lv.y * rv.z - lv.z * rv.y, // YZ cross
|
||||
lv.z * rv.x - lv.x * rv.z, // ZX cross
|
||||
lv.x * rv.y - lv.y * rv.x); // XY cross
|
||||
return vector_3(left.y * right.z - left.z * right.y, // YZ cross
|
||||
left.z * right.x - left.x * right.z, // ZX cross
|
||||
left.x * right.y - left.y * right.x); // XY cross
|
||||
}
|
||||
|
||||
vector_3 vector_3::get_normal() const {
|
||||
@@ -64,22 +63,20 @@ vector_3 vector_3::get_normal() const {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
void vector_3::normalize() {
|
||||
*this *= RSQRT(sq(x) + sq(y) + sq(z));
|
||||
}
|
||||
float vector_3::magnitude() const { return SQRT(sq(x) + sq(y) + sq(z)); }
|
||||
|
||||
void vector_3::normalize() { *this *= RSQRT(sq(x) + sq(y) + sq(z)); }
|
||||
|
||||
// Apply a rotation to the matrix
|
||||
void vector_3::apply_rotation(const matrix_3x3 &matrix) {
|
||||
const float _x = x, _y = y, _z = z;
|
||||
*this = { matrix.vectors[0][0] * _x + matrix.vectors[1][0] * _y + matrix.vectors[2][0] * _z,
|
||||
matrix.vectors[0][1] * _x + matrix.vectors[1][1] * _y + matrix.vectors[2][1] * _z,
|
||||
matrix.vectors[0][2] * _x + matrix.vectors[1][2] * _y + matrix.vectors[2][2] * _z };
|
||||
*this = { matrix.vectors[0].x * _x + matrix.vectors[1].x * _y + matrix.vectors[2].x * _z,
|
||||
matrix.vectors[0].y * _x + matrix.vectors[1].y * _y + matrix.vectors[2].y * _z,
|
||||
matrix.vectors[0].z * _x + matrix.vectors[1].z * _y + matrix.vectors[2].z * _z };
|
||||
}
|
||||
|
||||
extern const char SP_X_STR[], SP_Y_STR[], SP_Z_STR[];
|
||||
|
||||
void vector_3::debug(PGM_P const title) {
|
||||
serialprintPGM(title);
|
||||
SERIAL_ECHOPGM_P(title);
|
||||
SERIAL_ECHOPAIR_F_P(SP_X_STR, x, 6);
|
||||
SERIAL_ECHOPAIR_F_P(SP_Y_STR, y, 6);
|
||||
SERIAL_ECHOLNPAIR_F_P(SP_Z_STR, z, 6);
|
||||
@@ -89,8 +86,8 @@ void vector_3::debug(PGM_P const title) {
|
||||
* matrix_3x3
|
||||
*/
|
||||
|
||||
void apply_rotation_xyz(const matrix_3x3 &matrix, float &_x, float &_y, float &_z) {
|
||||
vector_3 vec = vector_3(_x, _y, _z); vec.apply_rotation(matrix);
|
||||
void matrix_3x3::apply_rotation_xyz(float &_x, float &_y, float &_z) {
|
||||
vector_3 vec = vector_3(_x, _y, _z); vec.apply_rotation(*this);
|
||||
_x = vec.x; _y = vec.y; _z = vec.z;
|
||||
}
|
||||
|
||||
@@ -141,10 +138,7 @@ matrix_3x3 matrix_3x3::transpose(const matrix_3x3 &original) {
|
||||
}
|
||||
|
||||
void matrix_3x3::debug(PGM_P const title) {
|
||||
if (title != nullptr) {
|
||||
serialprintPGM(title);
|
||||
SERIAL_EOL();
|
||||
}
|
||||
if (title) SERIAL_ECHOLNPGM_P(title);
|
||||
LOOP_L_N(i, 3) {
|
||||
LOOP_L_N(j, 3) {
|
||||
if (vectors[i][j] >= 0.0) SERIAL_CHAR('+');
|
||||
|
43
Marlin/src/libs/vector_3.h
Executable file → Normal file
43
Marlin/src/libs/vector_3.h
Executable file → Normal file
@@ -16,7 +16,7 @@
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
@@ -44,13 +44,16 @@
|
||||
|
||||
class matrix_3x3;
|
||||
|
||||
struct vector_3 : xyz_float_t {
|
||||
|
||||
vector_3(const float &_x, const float &_y, const float &_z) { set(_x, _y, _z); }
|
||||
vector_3(const xy_float_t &in) { set(in.x, in.y); }
|
||||
vector_3(const xyz_float_t &in) { set(in.x, in.y, in.z); }
|
||||
vector_3(const xyze_float_t &in) { set(in.x, in.y, in.z); }
|
||||
vector_3() { reset(); }
|
||||
struct vector_3 {
|
||||
union {
|
||||
struct { float x, y, z; };
|
||||
float pos[3];
|
||||
};
|
||||
vector_3(const_float_t _x, const_float_t _y, const_float_t _z) : x(_x), y(_y), z(_z) {}
|
||||
vector_3(const xy_float_t &in) { x = in.x; TERN_(HAS_Y_AXIS, y = in.y); }
|
||||
vector_3(const xyz_float_t &in) { x = in.x; TERN_(HAS_Y_AXIS, y = in.y); TERN_(HAS_Z_AXIS, z = in.z); }
|
||||
vector_3(const xyze_float_t &in) { x = in.x; TERN_(HAS_Y_AXIS, y = in.y); TERN_(HAS_Z_AXIS, z = in.z); }
|
||||
vector_3() { x = y = z = 0; }
|
||||
|
||||
// Factory method
|
||||
static vector_3 cross(const vector_3 &a, const vector_3 &b);
|
||||
@@ -60,19 +63,26 @@ struct vector_3 : xyz_float_t {
|
||||
void apply_rotation(const matrix_3x3 &matrix);
|
||||
|
||||
// Accessors
|
||||
float get_length() const;
|
||||
float magnitude() const;
|
||||
vector_3 get_normal() const;
|
||||
|
||||
// Operators
|
||||
FORCE_INLINE vector_3 operator+(const vector_3 &v) const { vector_3 o = *this; o += v; return o; }
|
||||
FORCE_INLINE vector_3 operator-(const vector_3 &v) const { vector_3 o = *this; o -= v; return o; }
|
||||
FORCE_INLINE vector_3 operator*(const float &v) const { vector_3 o = *this; o *= v; return o; }
|
||||
float& operator[](const int n) { return pos[n]; }
|
||||
const float& operator[](const int n) const { return pos[n]; }
|
||||
|
||||
vector_3& operator*=(const float &v) { x *= v; y *= v; z *= v; return *this; }
|
||||
vector_3 operator+(const vector_3 &v) { return vector_3(x + v.x, y + v.y, z + v.z); }
|
||||
vector_3 operator-(const vector_3 &v) { return vector_3(x - v.x, y - v.y, z - v.z); }
|
||||
vector_3 operator*(const float &v) { return vector_3(x * v, y * v, z * v); }
|
||||
|
||||
operator xy_float_t() { return xy_float_t({ x, y }); }
|
||||
operator xyz_float_t() { return xyz_float_t({ x, y, z }); }
|
||||
|
||||
void debug(PGM_P const title);
|
||||
};
|
||||
|
||||
struct matrix_3x3 {
|
||||
abc_float_t vectors[3];
|
||||
vector_3 vectors[3];
|
||||
|
||||
// Factory methods
|
||||
static matrix_3x3 create_from_rows(const vector_3 &row_0, const vector_3 &row_1, const vector_3 &row_2);
|
||||
@@ -82,9 +92,6 @@ struct matrix_3x3 {
|
||||
void set_to_identity();
|
||||
|
||||
void debug(PGM_P const title);
|
||||
};
|
||||
|
||||
void apply_rotation_xyz(const matrix_3x3 &rotationMatrix, float &x, float &y, float &z);
|
||||
FORCE_INLINE void apply_rotation_xyz(const matrix_3x3 &rotationMatrix, xyz_pos_t &pos) {
|
||||
apply_rotation_xyz(rotationMatrix, pos.x, pos.y, pos.z);
|
||||
}
|
||||
void apply_rotation_xyz(float &x, float &y, float &z);
|
||||
};
|
||||
|
Reference in New Issue
Block a user