update code base to Marlin 2.0.9.2

This commit is contained in:
Stefan Kalscheuer
2021-10-03 18:57:12 +02:00
parent b9d7ba838e
commit 7077da3591
2617 changed files with 332093 additions and 103438 deletions

285
Marlin/src/libs/BL24CXX.cpp Normal file
View 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
View 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
View 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
View 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
View 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).

View 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
View 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
View 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
View 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;

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

2
Marlin/src/libs/heatshrink/heatshrink_common.h Executable file → Normal file
View 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
View File

39
Marlin/src/libs/heatshrink/heatshrink_decoder.cpp Executable file → Normal file
View 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
View 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 */

View 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

View 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

View File

@@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
};