Merge branch 'MK3' into remove-eeprom-func

This commit is contained in:
Guðni Már Gilbert 2022-02-11 19:32:11 +00:00 committed by GitHub
commit 4672b6444c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
84 changed files with 6736 additions and 5135 deletions

View File

@ -6,14 +6,14 @@ labels: bug
assignees: ''
---
<!--
Please, before you create a new bug report, please make sure you searched in open and closed issues and couldn't find anything that matches.
-->
**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
**Printer firmware version**- [e.g. 3.8.1, 3.8.1-RC1, ...]
**Printer firmware version** - [e.g. 3.8.1, 3.8.1-RC1, ...]
**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
**MMU upgrade firmware version [e.g. 1.0.6, 1.0.6-RC2, ...]
**MMU upgrade** - [e.g. MMU2S, MMU2, MMU1]
**MMU upgrade firmware version** - [e.g. 1.0.6, 1.0.6-RC2, ...]
**SD card or USB/Octoprint**
Please let us know if you print via SD card or USB/Octoprint

17
.github/ISSUE_TEMPLATE/community.md vendored Normal file
View File

@ -0,0 +1,17 @@
---
name: Community
about: Related to "Community made" features
title: "[Community made] <Enter comprehensive title>"
labels: community_made
assignees: ''
---
Prusa Research will NOT follow up these issues!
The maintainers of the "Community made" feature should/will react.
Please, before you create a new "Community made" ticket, please make sure you searched in open and closed issues and couldn't find anything that matches.
**Which Community made feature do you want to address?**
**What is your request/question/suggestion?**

4
.gitignore vendored
View File

@ -1,7 +1,9 @@
.settings
.project
.cproject
.vscode
Debug
__pycache__
Firmware/Configuration_prusa.h
Firmware/Doc
/Firmware/.vs/Firmware/v14
@ -52,3 +54,5 @@ Firmware/Doc
/Firmware/Firmware.vcxproj
/Firmware/Configuration_prusa_bckp.h
/Firmware/variants/printers.h
Configuration.tmp
config.tmp

View File

@ -1,4 +1,4 @@
dist: trusty
dist: focal
before_install:
- sudo apt-get install -y ninja-build
# Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off
@ -32,4 +32,4 @@ script:
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo13a-E3Dv6full variant failed" && false; }
- rm Firmware/Configuration_prusa.h
- cp Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo10a-E3Dv6full variant failed" && false; }
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo10a-E3Dv6full variant failed" && false; }

36
Community_made.md Normal file
View File

@ -0,0 +1,36 @@
# Community made
## Prusa-Firmware build
- `PF-build.sh`
- Maintainers: **@3d-gussner**
- Co-maintainers:
- Contributors: **@mkbel**, **@ropaha**, **@deliopoulos**, **@DRracer**, **wavexx**, **@leptun**, **@andrewluebke**, **@kuhnmarek**
- [X] **Active** since February 2019
- [X] **Maintained** since January 2019
### How-to use PF-build.sh
Start `./PF-build.sh` and follow the instructions
Help `./PF-build.sh -h`
# MK404 Simulator
## MK404-build.sh
**MK404 is a community 3d printer simulator created by @vintagepc**
Please checkout and support his github repository [MK404](https://github.com/vintagepc/MK404) and the [MK404 Wiki](https://github.com/vintagepc/MK404/wiki)
At this moment the `MK404-build.sh` script is only supported on Linux
- `MK404-build.sh`
- Maintainers: **@3d-gussner**
- Co-maintainers:
- Contributors:
- [X] **Active** since August 2021
- [X] **Maintained** since August 2021
### How-to use MK404-build.sh
After compiling with `PF-build.sh` you get the option to start the `MK404` simulator with the fresh compiled firmware. (Linux only at this moment)
Help `./MK404-build.sh -h`
## Translations
- see [/lang/Community_made_translations.md](https://github.com/prusa3d/Prusa-Firmware/blob/MK3/lang/Community_made_translations.md)

View File

@ -18,10 +18,16 @@ extern PGM_P sPrinterName;
// Firmware version
#define FW_MAJOR 3
#define FW_MINOR 10
#define FW_REVISION 0
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION)
#define FW_REVISION 1
//#define FW_FLAVOR RC //uncomment if DEBUG, DEVEL, APLHA, BETA or RC
//#define FW_FLAVERSION 1 //uncomment if FW_FLAVOR is defined and versioning is needed.
#ifndef FW_FLAVOR
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION)
#else
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION)
#endif
#define FW_COMMIT_NR 4481
#define FW_COMMIT_NR 4697
// FW_VERSION_UNKNOWN means this is an unofficial build.
// The firmware should only be checked into github with this symbol.
@ -483,11 +489,6 @@ your extruder heater takes 2 minutes to hit the target on heating.
// Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino
//#define FAST_PWM_FAN
// Temperature status LEDs that display the hotend and bet temperature.
// If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
// Otherwise the RED led is on. There is 1C hysteresis.
//#define TEMP_STAT_LEDS
// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
// which is not ass annoying as with the hardware PWM. On the other hand, if this frequency
// is too low, you should also increment SOFT_PWM_SCALE.

View File

@ -32,7 +32,7 @@ static bool EEPROM_writeData(uint8_t* pos, uint8_t* value, uint8_t size, const c
#endif //DEBUG_EEPROM_WRITE
{
#ifdef DEBUG_EEPROM_WRITE
printf_P(PSTR("EEPROM_WRITE_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
printf_P(PSTR("EEPROM_WRITE_VAR addr=0x%04x size=0x%02x name=%s\n"), pos, size, name);
#endif //DEBUG_EEPROM_WRITE
while (size--)
{
@ -56,7 +56,7 @@ static void EEPROM_readData(uint8_t* pos, uint8_t* value, uint8_t size, const ch
#endif //DEBUG_EEPROM_READ
{
#ifdef DEBUG_EEPROM_READ
printf_P(PSTR("EEPROM_READ_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
printf_P(PSTR("EEPROM_READ_VAR addr=0x%04x size=0x%02x name=%s\n"), pos, size, name);
#endif //DEBUG_EEPROM_READ
while(size--)
{
@ -260,10 +260,6 @@ bool Config_RetrieveSettings()
{
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base), reinterpret_cast<uint8_t*>(&cs), sizeof(cs), "cs");
if (cs.max_jerk[X_AXIS] > DEFAULT_XJERK) cs.max_jerk[X_AXIS] = DEFAULT_XJERK;
if (cs.max_jerk[Y_AXIS] > DEFAULT_YJERK) cs.max_jerk[Y_AXIS] = DEFAULT_YJERK;
calculate_extruder_multipliers();
//if max_feedrate_silent and max_acceleration_units_per_sq_second_silent were never stored to eeprom, use default values:

View File

@ -13,7 +13,7 @@
#ifdef PIDTEMP
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
#define PID_ADD_EXTRUSION_RATE
// #define PID_ADD_EXTRUSION_RATE
#ifdef PID_ADD_EXTRUSION_RATE
#define DEFAULT_Kc (1) //heating power=Kc*(e_speed)
#endif
@ -250,6 +250,9 @@
#define HAS_FOLDER_SORTING (FOLDER_SORTING)
#endif
// Enabe this option to get a pretty message whenever the endstop gets hit (as in the position at which the endstop got triggered)
//#define VERBOSE_CHECK_HIT_ENDSTOPS
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED

View File

@ -538,26 +538,20 @@ const char* dcode_9_ADC_name(uint8_t i)
return 0;
}
#ifdef AMBIENT_THERMISTOR
extern int current_temperature_raw_ambient;
#endif //AMBIENT_THERMISTOR
#ifdef VOLT_PWR_PIN
extern int current_voltage_raw_pwr;
#endif //VOLT_PWR_PIN
#ifdef VOLT_BED_PIN
extern int current_voltage_raw_bed;
#endif //VOLT_BED_PIN
uint16_t dcode_9_ADC_val(uint8_t i)
{
switch (i)
{
#ifdef SHOW_TEMP_ADC_VALUES
case 0: return current_temperature_raw[0];
#endif //SHOW_TEMP_ADC_VALUES
case 1: return 0;
#ifdef SHOW_TEMP_ADC_VALUES
case 2: return current_temperature_bed_raw;
#endif //SHOW_TEMP_ADC_VALUES
#ifdef PINDA_THERMISTOR
case 3: return current_temperature_raw_pinda;
#endif //PINDA_THERMISTOR
#ifdef VOLT_PWR_PIN
case 4: return current_voltage_raw_pwr;
#endif //VOLT_PWR_PIN
@ -996,7 +990,7 @@ void __attribute__((noinline)) serial_dump_and_reset(dump_crash_reason reason)
// sample SP/PC
sp = SP;
GETPC(&pc);
pc = GETPC();
// extend WDT long enough to allow writing the entire stream
wdt_enable(WDTO_8S);

View File

@ -236,17 +236,19 @@ void update_currents();
void get_coordinates();
void prepare_move();
void kill(const char *full_screen_message = NULL, unsigned char id = 0);
void Stop();
bool IsStopped();
void finishAndDisableSteppers();
void UnconditionalStop(); // Stop heaters, motion and clear current print status
void Stop(); // Emergency stop used by overtemp functions which allows recovery
bool IsStopped(); // Returns true if the print has been stopped
//put an ASCII command at the end of the current buffer, read from flash
#define enquecommand_P(cmd) enquecommand(cmd, true)
//put an ASCII command at the begin of the current buffer, read from flash
#define enquecommand_front_P(cmd) enquecommand_front(cmd, true)
void prepare_arc_move(char isclockwise);
void prepare_arc_move(bool isclockwise);
void clamp_to_software_endstops(float target[3]);
void refresh_cmd_timeout(void);
@ -275,6 +277,17 @@ FORCE_INLINE unsigned long millis_nc() {
void setPwmFrequency(uint8_t pin, int val);
#endif
enum class HeatingStatus : uint8_t
{
NO_HEATING = 0,
EXTRUDER_HEATING = 1,
EXTRUDER_HEATING_COMPLETE = 2,
BED_HEATING = 3,
BED_HEATING_COMPLETE = 4,
};
extern HeatingStatus heating_status;
extern bool fans_check_enabled;
extern float homing_feedrate[];
extern uint8_t axis_relative_modes;
@ -294,9 +307,9 @@ extern int8_t lcd_change_fil_state;
extern float default_retraction;
#ifdef TMC2130
void homeaxis(int axis, uint8_t cnt = 1, uint8_t* pstep = 0);
void homeaxis(uint8_t axis, uint8_t cnt = 1, uint8_t* pstep = 0);
#else
void homeaxis(int axis, uint8_t cnt = 1);
void homeaxis(uint8_t axis, uint8_t cnt = 1);
#endif //TMC2130
@ -319,18 +332,13 @@ extern int bowden_length[4];
extern bool is_usb_printing;
extern bool homing_flag;
extern bool loading_flag;
extern unsigned int usb_printing_counter;
extern unsigned long kicktime;
extern uint8_t usb_printing_counter;
extern unsigned long total_filament_used;
void save_statistics(unsigned long _total_filament_used, unsigned long _total_print_time);
extern unsigned int heating_status;
extern unsigned int status_number;
extern unsigned int heating_status_counter;
extern uint8_t status_number;
extern uint8_t heating_status_counter;
extern char snmm_filaments_used;
extern unsigned long PingTime;
extern unsigned long NcTime;
extern bool no_response;
extern uint8_t important_status;
extern uint8_t saved_filament_type;
@ -348,9 +356,7 @@ extern unsigned long start_pause_print;
extern unsigned long t_fan_rising_edge;
extern bool mesh_bed_leveling_flag;
extern bool mesh_bed_run_from_menu;
extern int8_t lcd_change_fil_state;
// save/restore printing
extern bool saved_printing;
extern uint8_t saved_printing_type;

View File

@ -30,7 +30,7 @@ uint8_t selectedSerialPort = 0;
// this is so I can support Attiny series and any other chip without a UART
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
#if UART_PRESENT(SERIAL_PORT)
#ifdef HAS_UART
ring_buffer rx_buffer = { { 0 }, 0, 0 };
#endif

View File

@ -28,9 +28,12 @@
#endif
// The presence of the UBRRH register is used to detect a UART.
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
(port == 3 && defined(UBRR3H)))
#if ((SERIAL_PORT == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
(SERIAL_PORT == 1 && defined(UBRR1H)) || \
(SERIAL_PORT == 2 && defined(UBRR2H)) || \
(SERIAL_PORT == 3 && defined(UBRR3H)))
#define HAS_UART
#endif
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
// requires two levels of indirection to expand macro values properly)
@ -82,7 +85,7 @@ struct ring_buffer
int tail;
};
#if UART_PRESENT(SERIAL_PORT)
#ifdef HAS_UART
extern ring_buffer rx_buffer;
#endif

File diff suppressed because it is too large Load Diff

View File

@ -205,14 +205,14 @@ uint32_t Sd2Card::cardSize() {
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectHigh() {
digitalWrite(chipSelectPin_, HIGH);
WRITE(SDSS, 1);
}
//------------------------------------------------------------------------------
void Sd2Card::chipSelectLow() {
#ifndef SOFTWARE_SPI
spiInit(spiRate_);
#endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW);
WRITE(SDSS, 0);
}
//------------------------------------------------------------------------------
/** Erase a range of blocks.
@ -283,26 +283,25 @@ bool Sd2Card::eraseSingleBlockEnable() {
* the value zero, false, is returned for failure. The reason for failure
* can be determined by calling errorCode() and errorData().
*/
bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
bool Sd2Card::init(uint8_t sckRateID) {
errorCode_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute
uint16_t t0 = (uint16_t)_millis();
uint32_t arg;
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
chipSelectHigh();
pinMode(SPI_MISO_PIN, INPUT);
pinMode(SPI_MOSI_PIN, OUTPUT);
pinMode(SPI_SCK_PIN, OUTPUT);
SET_OUTPUT(SDSS);
SET_INPUT(MISO);
SET_OUTPUT(MOSI);
SET_OUTPUT(SCK);
#ifndef SOFTWARE_SPI
// SS must be in output mode even it is not chip select
pinMode(SS_PIN, OUTPUT);
SET_OUTPUT(SS);
// set SS high - may be chip select for another SPI device
#if SET_SPI_SS_HIGH
digitalWrite(SS_PIN, HIGH);
WRITE(SS, 1);
#endif // SET_SPI_SS_HIGH
// set SCK rate for initialization commands
spiRate_ = SPI_SD_INIT_RATE;

View File

@ -28,7 +28,6 @@
* \brief Sd2Card class for V2 SD/SDHC cards
*/
#include "SdFatConfig.h"
#include "Sd2PinMap.h"
#include "SdInfo.h"
//------------------------------------------------------------------------------
// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
@ -133,22 +132,7 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
//------------------------------------------------------------------------------
// SPI pin definitions - do not edit here - change in SdFatConfig.h
//
#ifndef SOFTWARE_SPI
// hardware pin defs
/** The default chip select pin for the SD card is SS. */
uint8_t const SD_CHIP_SELECT_PIN = SS_PIN;
// The following three pins must not be redefined for hardware SPI.
/** SPI Master Out Slave In pin */
uint8_t const SPI_MOSI_PIN = MOSI_PIN;
/** SPI Master In Slave Out pin */
uint8_t const SPI_MISO_PIN = MISO_PIN;
/** SPI Clock pin */
uint8_t const SPI_SCK_PIN = SCK_PIN;
#else // SOFTWARE_SPI
/** SPI chip select pin */
uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
#ifdef SOFTWARE_SPI
/** SPI Master Out Slave In pin */
uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
/** SPI Master In Slave Out pin */
@ -176,17 +160,16 @@ class Sd2Card {
/**
* \return error code for last error. See Sd2Card.h for a list of error codes.
*/
int errorCode() const {return errorCode_;}
uint8_t errorCode() const {return errorCode_;}
/** \return error data for last error. */
int errorData() const {return status_;}
uint8_t errorData() const {return status_;}
/**
* Initialize an SD flash memory card with default clock rate and chip
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
* select pin. See sd2Card::init(uint8_t sckRateID).
*
* \return true for success or false for failure.
*/
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
bool init(uint8_t sckRateID = SPI_FULL_SPEED);
bool readBlock(uint32_t block, uint8_t* dst);
/**
* Read a card's CID register. The CID contains card identification
@ -232,7 +215,6 @@ class Sd2Card {
private:
//----------------------------------------------------------------------------
uint8_t chipSelectPin_;
uint8_t errorCode_;
uint8_t spiRate_;
uint8_t status_;

View File

@ -1,364 +0,0 @@
/* Arduino SdFat Library
* Copyright (C) 2010 by William Greiman
*
* This file is part of the Arduino SdFat Library
*
* This Library 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 Library 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 the Arduino SdFat Library. If not, see
* <http://www.gnu.org/licenses/>.
*/
// Warning this file was generated by a program.
#include "Marlin.h"
#ifdef SDSUPPORT
#ifndef Sd2PinMap_h
#define Sd2PinMap_h
#include <avr/io.h>
//------------------------------------------------------------------------------
/** struct for mapping digital pins */
struct pin_map_t {
volatile uint8_t* ddr;
volatile uint8_t* pin;
volatile uint8_t* port;
uint8_t bit;
};
//------------------------------------------------------------------------------
#if defined(__AVR_ATmega1280__)\
|| defined(__AVR_ATmega2560__)
// Mega
#undef MOSI_PIN
#undef MISO_PIN
// SPI port
uint8_t const SS_PIN = 53; // B0
uint8_t const MOSI_PIN = 51; // B2
uint8_t const MISO_PIN = 50; // B3
uint8_t const SCK_PIN = 52; // B1
static const pin_map_t digitalPinMap[] = {
{&DDRE, &PINE, &PORTE, 0}, // E0 0
{&DDRE, &PINE, &PORTE, 1}, // E1 1
{&DDRE, &PINE, &PORTE, 4}, // E4 2
{&DDRE, &PINE, &PORTE, 5}, // E5 3
{&DDRG, &PING, &PORTG, 5}, // G5 4
{&DDRE, &PINE, &PORTE, 3}, // E3 5
{&DDRH, &PINH, &PORTH, 3}, // H3 6
{&DDRH, &PINH, &PORTH, 4}, // H4 7
{&DDRH, &PINH, &PORTH, 5}, // H5 8
{&DDRH, &PINH, &PORTH, 6}, // H6 9
{&DDRB, &PINB, &PORTB, 4}, // B4 10
{&DDRB, &PINB, &PORTB, 5}, // B5 11
{&DDRB, &PINB, &PORTB, 6}, // B6 12
{&DDRB, &PINB, &PORTB, 7}, // B7 13
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
{&DDRH, &PINH, &PORTH, 1}, // H1 16
{&DDRH, &PINH, &PORTH, 0}, // H0 17
{&DDRD, &PIND, &PORTD, 3}, // D3 18
{&DDRD, &PIND, &PORTD, 2}, // D2 19
{&DDRD, &PIND, &PORTD, 1}, // D1 20
{&DDRD, &PIND, &PORTD, 0}, // D0 21
{&DDRA, &PINA, &PORTA, 0}, // A0 22
{&DDRA, &PINA, &PORTA, 1}, // A1 23
{&DDRA, &PINA, &PORTA, 2}, // A2 24
{&DDRA, &PINA, &PORTA, 3}, // A3 25
{&DDRA, &PINA, &PORTA, 4}, // A4 26
{&DDRA, &PINA, &PORTA, 5}, // A5 27
{&DDRA, &PINA, &PORTA, 6}, // A6 28
{&DDRA, &PINA, &PORTA, 7}, // A7 29
{&DDRC, &PINC, &PORTC, 7}, // C7 30
{&DDRC, &PINC, &PORTC, 6}, // C6 31
{&DDRC, &PINC, &PORTC, 5}, // C5 32
{&DDRC, &PINC, &PORTC, 4}, // C4 33
{&DDRC, &PINC, &PORTC, 3}, // C3 34
{&DDRC, &PINC, &PORTC, 2}, // C2 35
{&DDRC, &PINC, &PORTC, 1}, // C1 36
{&DDRC, &PINC, &PORTC, 0}, // C0 37
{&DDRD, &PIND, &PORTD, 7}, // D7 38
{&DDRG, &PING, &PORTG, 2}, // G2 39
{&DDRG, &PING, &PORTG, 1}, // G1 40
{&DDRG, &PING, &PORTG, 0}, // G0 41
{&DDRL, &PINL, &PORTL, 7}, // L7 42
{&DDRL, &PINL, &PORTL, 6}, // L6 43
{&DDRL, &PINL, &PORTL, 5}, // L5 44
{&DDRL, &PINL, &PORTL, 4}, // L4 45
{&DDRL, &PINL, &PORTL, 3}, // L3 46
{&DDRL, &PINL, &PORTL, 2}, // L2 47
{&DDRL, &PINL, &PORTL, 1}, // L1 48
{&DDRL, &PINL, &PORTL, 0}, // L0 49
{&DDRB, &PINB, &PORTB, 3}, // B3 50
{&DDRB, &PINB, &PORTB, 2}, // B2 51
{&DDRB, &PINB, &PORTB, 1}, // B1 52
{&DDRB, &PINB, &PORTB, 0}, // B0 53
{&DDRF, &PINF, &PORTF, 0}, // F0 54
{&DDRF, &PINF, &PORTF, 1}, // F1 55
{&DDRF, &PINF, &PORTF, 2}, // F2 56
{&DDRF, &PINF, &PORTF, 3}, // F3 57
{&DDRF, &PINF, &PORTF, 4}, // F4 58
{&DDRF, &PINF, &PORTF, 5}, // F5 59
{&DDRF, &PINF, &PORTF, 6}, // F6 60
{&DDRF, &PINF, &PORTF, 7}, // F7 61
{&DDRK, &PINK, &PORTK, 0}, // K0 62
{&DDRK, &PINK, &PORTK, 1}, // K1 63
{&DDRK, &PINK, &PORTK, 2}, // K2 64
{&DDRK, &PINK, &PORTK, 3}, // K3 65
{&DDRK, &PINK, &PORTK, 4}, // K4 66
{&DDRK, &PINK, &PORTK, 5}, // K5 67
{&DDRK, &PINK, &PORTK, 6}, // K6 68
{&DDRK, &PINK, &PORTK, 7} // K7 69
};
//------------------------------------------------------------------------------
#elif defined(__AVR_ATmega644P__)\
|| defined(__AVR_ATmega644__)\
|| defined(__AVR_ATmega1284P__)
// Sanguino
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 17; // C1
uint8_t const SCL_PIN = 18; // C2
// SPI port
uint8_t const SS_PIN = 4; // B4
uint8_t const MOSI_PIN = 5; // B5
uint8_t const MISO_PIN = 6; // B6
uint8_t const SCK_PIN = 7; // B7
static const pin_map_t digitalPinMap[] = {
{&DDRB, &PINB, &PORTB, 0}, // B0 0
{&DDRB, &PINB, &PORTB, 1}, // B1 1
{&DDRB, &PINB, &PORTB, 2}, // B2 2
{&DDRB, &PINB, &PORTB, 3}, // B3 3
{&DDRB, &PINB, &PORTB, 4}, // B4 4
{&DDRB, &PINB, &PORTB, 5}, // B5 5
{&DDRB, &PINB, &PORTB, 6}, // B6 6
{&DDRB, &PINB, &PORTB, 7}, // B7 7
{&DDRD, &PIND, &PORTD, 0}, // D0 8
{&DDRD, &PIND, &PORTD, 1}, // D1 9
{&DDRD, &PIND, &PORTD, 2}, // D2 10
{&DDRD, &PIND, &PORTD, 3}, // D3 11
{&DDRD, &PIND, &PORTD, 4}, // D4 12
{&DDRD, &PIND, &PORTD, 5}, // D5 13
{&DDRD, &PIND, &PORTD, 6}, // D6 14
{&DDRD, &PIND, &PORTD, 7}, // D7 15
{&DDRC, &PINC, &PORTC, 0}, // C0 16
{&DDRC, &PINC, &PORTC, 1}, // C1 17
{&DDRC, &PINC, &PORTC, 2}, // C2 18
{&DDRC, &PINC, &PORTC, 3}, // C3 19
{&DDRC, &PINC, &PORTC, 4}, // C4 20
{&DDRC, &PINC, &PORTC, 5}, // C5 21
{&DDRC, &PINC, &PORTC, 6}, // C6 22
{&DDRC, &PINC, &PORTC, 7}, // C7 23
{&DDRA, &PINA, &PORTA, 7}, // A7 24
{&DDRA, &PINA, &PORTA, 6}, // A6 25
{&DDRA, &PINA, &PORTA, 5}, // A5 26
{&DDRA, &PINA, &PORTA, 4}, // A4 27
{&DDRA, &PINA, &PORTA, 3}, // A3 28
{&DDRA, &PINA, &PORTA, 2}, // A2 29
{&DDRA, &PINA, &PORTA, 1}, // A1 30
{&DDRA, &PINA, &PORTA, 0} // A0 31
};
//------------------------------------------------------------------------------
#elif defined(__AVR_ATmega32U4__)
// Teensy 2.0
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 6; // D1
uint8_t const SCL_PIN = 5; // D0
// SPI port
uint8_t const SS_PIN = 0; // B0
uint8_t const MOSI_PIN = 2; // B2
uint8_t const MISO_PIN = 3; // B3
uint8_t const SCK_PIN = 1; // B1
static const pin_map_t digitalPinMap[] = {
{&DDRB, &PINB, &PORTB, 0}, // B0 0
{&DDRB, &PINB, &PORTB, 1}, // B1 1
{&DDRB, &PINB, &PORTB, 2}, // B2 2
{&DDRB, &PINB, &PORTB, 3}, // B3 3
{&DDRB, &PINB, &PORTB, 7}, // B7 4
{&DDRD, &PIND, &PORTD, 0}, // D0 5
{&DDRD, &PIND, &PORTD, 1}, // D1 6
{&DDRD, &PIND, &PORTD, 2}, // D2 7
{&DDRD, &PIND, &PORTD, 3}, // D3 8
{&DDRC, &PINC, &PORTC, 6}, // C6 9
{&DDRC, &PINC, &PORTC, 7}, // C7 10
{&DDRD, &PIND, &PORTD, 6}, // D6 11
{&DDRD, &PIND, &PORTD, 7}, // D7 12
{&DDRB, &PINB, &PORTB, 4}, // B4 13
{&DDRB, &PINB, &PORTB, 5}, // B5 14
{&DDRB, &PINB, &PORTB, 6}, // B6 15
{&DDRF, &PINF, &PORTF, 7}, // F7 16
{&DDRF, &PINF, &PORTF, 6}, // F6 17
{&DDRF, &PINF, &PORTF, 5}, // F5 18
{&DDRF, &PINF, &PORTF, 4}, // F4 19
{&DDRF, &PINF, &PORTF, 1}, // F1 20
{&DDRF, &PINF, &PORTF, 0}, // F0 21
{&DDRD, &PIND, &PORTD, 4}, // D4 22
{&DDRD, &PIND, &PORTD, 5}, // D5 23
{&DDRE, &PINE, &PORTE, 6} // E6 24
};
//------------------------------------------------------------------------------
#elif defined(__AVR_AT90USB646__)\
|| defined(__AVR_AT90USB1286__)
// Teensy++ 1.0 & 2.0
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 1; // D1
uint8_t const SCL_PIN = 0; // D0
// SPI port
uint8_t const SS_PIN = 20; // B0
uint8_t const MOSI_PIN = 22; // B2
uint8_t const MISO_PIN = 23; // B3
uint8_t const SCK_PIN = 21; // B1
static const pin_map_t digitalPinMap[] = {
{&DDRD, &PIND, &PORTD, 0}, // D0 0
{&DDRD, &PIND, &PORTD, 1}, // D1 1
{&DDRD, &PIND, &PORTD, 2}, // D2 2
{&DDRD, &PIND, &PORTD, 3}, // D3 3
{&DDRD, &PIND, &PORTD, 4}, // D4 4
{&DDRD, &PIND, &PORTD, 5}, // D5 5
{&DDRD, &PIND, &PORTD, 6}, // D6 6
{&DDRD, &PIND, &PORTD, 7}, // D7 7
{&DDRE, &PINE, &PORTE, 0}, // E0 8
{&DDRE, &PINE, &PORTE, 1}, // E1 9
{&DDRC, &PINC, &PORTC, 0}, // C0 10
{&DDRC, &PINC, &PORTC, 1}, // C1 11
{&DDRC, &PINC, &PORTC, 2}, // C2 12
{&DDRC, &PINC, &PORTC, 3}, // C3 13
{&DDRC, &PINC, &PORTC, 4}, // C4 14
{&DDRC, &PINC, &PORTC, 5}, // C5 15
{&DDRC, &PINC, &PORTC, 6}, // C6 16
{&DDRC, &PINC, &PORTC, 7}, // C7 17
{&DDRE, &PINE, &PORTE, 6}, // E6 18
{&DDRE, &PINE, &PORTE, 7}, // E7 19
{&DDRB, &PINB, &PORTB, 0}, // B0 20
{&DDRB, &PINB, &PORTB, 1}, // B1 21
{&DDRB, &PINB, &PORTB, 2}, // B2 22
{&DDRB, &PINB, &PORTB, 3}, // B3 23
{&DDRB, &PINB, &PORTB, 4}, // B4 24
{&DDRB, &PINB, &PORTB, 5}, // B5 25
{&DDRB, &PINB, &PORTB, 6}, // B6 26
{&DDRB, &PINB, &PORTB, 7}, // B7 27
{&DDRA, &PINA, &PORTA, 0}, // A0 28
{&DDRA, &PINA, &PORTA, 1}, // A1 29
{&DDRA, &PINA, &PORTA, 2}, // A2 30
{&DDRA, &PINA, &PORTA, 3}, // A3 31
{&DDRA, &PINA, &PORTA, 4}, // A4 32
{&DDRA, &PINA, &PORTA, 5}, // A5 33
{&DDRA, &PINA, &PORTA, 6}, // A6 34
{&DDRA, &PINA, &PORTA, 7}, // A7 35
{&DDRE, &PINE, &PORTE, 4}, // E4 36
{&DDRE, &PINE, &PORTE, 5}, // E5 37
{&DDRF, &PINF, &PORTF, 0}, // F0 38
{&DDRF, &PINF, &PORTF, 1}, // F1 39
{&DDRF, &PINF, &PORTF, 2}, // F2 40
{&DDRF, &PINF, &PORTF, 3}, // F3 41
{&DDRF, &PINF, &PORTF, 4}, // F4 42
{&DDRF, &PINF, &PORTF, 5}, // F5 43
{&DDRF, &PINF, &PORTF, 6}, // F6 44
{&DDRF, &PINF, &PORTF, 7} // F7 45
};
//------------------------------------------------------------------------------
#elif defined(__AVR_ATmega168__)\
||defined(__AVR_ATmega168P__)\
||defined(__AVR_ATmega328P__)
// 168 and 328 Arduinos
// Two Wire (aka I2C) ports
uint8_t const SDA_PIN = 18; // C4
uint8_t const SCL_PIN = 19; // C5
// SPI port
uint8_t const SS_PIN = 10; // B2
uint8_t const MOSI_PIN = 11; // B3
uint8_t const MISO_PIN = 12; // B4
uint8_t const SCK_PIN = 13; // B5
static const pin_map_t digitalPinMap[] = {
{&DDRD, &PIND, &PORTD, 0}, // D0 0
{&DDRD, &PIND, &PORTD, 1}, // D1 1
{&DDRD, &PIND, &PORTD, 2}, // D2 2
{&DDRD, &PIND, &PORTD, 3}, // D3 3
{&DDRD, &PIND, &PORTD, 4}, // D4 4
{&DDRD, &PIND, &PORTD, 5}, // D5 5
{&DDRD, &PIND, &PORTD, 6}, // D6 6
{&DDRD, &PIND, &PORTD, 7}, // D7 7
{&DDRB, &PINB, &PORTB, 0}, // B0 8
{&DDRB, &PINB, &PORTB, 1}, // B1 9
{&DDRB, &PINB, &PORTB, 2}, // B2 10
{&DDRB, &PINB, &PORTB, 3}, // B3 11
{&DDRB, &PINB, &PORTB, 4}, // B4 12
{&DDRB, &PINB, &PORTB, 5}, // B5 13
{&DDRC, &PINC, &PORTC, 0}, // C0 14
{&DDRC, &PINC, &PORTC, 1}, // C1 15
{&DDRC, &PINC, &PORTC, 2}, // C2 16
{&DDRC, &PINC, &PORTC, 3}, // C3 17
{&DDRC, &PINC, &PORTC, 4}, // C4 18
{&DDRC, &PINC, &PORTC, 5} // C5 19
};
#else // defined(__AVR_ATmega1280__)
#error unknown chip
#endif // defined(__AVR_ATmega1280__)
//------------------------------------------------------------------------------
static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
uint8_t badPinNumber(void)
__attribute__((error("Pin number is too large or not a constant")));
static inline __attribute__((always_inline))
bool getPinMode(uint8_t pin) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
} else {
return badPinNumber();
}
}
static inline __attribute__((always_inline))
void setPinMode(uint8_t pin, uint8_t mode) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
if (mode) {
*digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;
} else {
*digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);
}
} else {
badPinNumber();
}
}
static inline __attribute__((always_inline))
bool fastDigitalRead(uint8_t pin) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
} else {
return badPinNumber();
}
}
static inline __attribute__((always_inline))
void fastDigitalWrite(uint8_t pin, uint8_t value) {
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
if (value) {
*digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;
} else {
*digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);
}
} else {
badPinNumber();
}
}
#endif // Sd2PinMap_h
#endif

View File

@ -231,7 +231,7 @@ static void finISR(timer16_Sequence_t timer)
#endif
}
static boolean isTimerActive(timer16_Sequence_t timer)
static bool isTimerActive(timer16_Sequence_t timer)
{
// returns true if any servo is active on this timer
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {

View File

@ -1,24 +1,21 @@
#pragma once
#include <stdint.h>
#include "macros.h"
#ifdef __AVR_ATmega2560__
// return the current PC (on AVRs with 22bit PC)
static inline void GETPC(uint32_t* v)
FORCE_INLINE __uint24 GETPC(void)
{
uint8_t a, b, c;
asm
(
__uint24 ret;
asm (
"rcall .\n"
"pop %2\n"
"pop %1\n"
"pop %0\n"
: "=r" (a), "=r" (b), "=r" (c)
"pop %A0\n"
"pop %B0\n"
"pop %C0\n"
: "=&r" (ret)
);
((uint8_t*)v)[0] = a;
((uint8_t*)v)[1] = b;
((uint8_t*)v)[2] = c;
((uint8_t*)v)[3] = 0;
return ret;
}
#endif

View File

@ -25,7 +25,6 @@ CardReader::CardReader()
cardOK = false;
saving = false;
logging = false;
autostart_atmillis=0;
workDirDepth = 0;
file_subcall_ctr=0;
memset(workDirParents, 0, sizeof(workDirParents));
@ -39,7 +38,7 @@ CardReader::CardReader()
WRITE(SDPOWER,HIGH);
#endif //SDPOWER
autostart_atmillis=_millis()+5000;
autostart_atmillis.start(); // reset timer
}
char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
@ -204,20 +203,13 @@ void CardReader::initsd(bool doPresort/* = true*/)
if(root.isOpen())
root.close();
#ifdef SDSLOW
if (!card.init(SPI_HALF_SPEED,SDSS)
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
&& !card.init(SPI_HALF_SPEED,LCD_SDSS)
#endif
if (!card.init(SPI_HALF_SPEED)
)
#else
if (!card.init(SPI_FULL_SPEED,SDSS)
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
&& !card.init(SPI_FULL_SPEED,LCD_SDSS)
#endif
if (!card.init(SPI_FULL_SPEED)
)
#endif
{
//if (!card.init(SPI_HALF_SPEED,SDSS))
SERIAL_ECHO_START;
SERIAL_ECHOLNRPGM(_n("SD init fail"));////MSG_SD_INIT_FAIL
}
@ -626,7 +618,7 @@ void CardReader::checkautostart(bool force)
{
if(!autostart_stilltocheck)
return;
if(autostart_atmillis<_millis())
if(autostart_atmillis.expired(5000))
return;
}
autostart_stilltocheck=false;
@ -697,11 +689,11 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/)
}
void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/)
void CardReader::getfilename_simple(uint16_t entry, const char * const match/*=NULL*/)
{
curDir = &workDir;
nrFiles = 0;
curDir->seekSet(position);
curDir->seekSet((uint32_t)entry << 5);
lsDive("", *curDir, match, LS_GetFilename);
}
@ -783,7 +775,7 @@ void CardReader::updir()
*/
void CardReader::getfilename_sorted(const uint16_t nr, uint8_t sdSort) {
if (nr < sort_count)
getfilename_simple(sort_positions[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
getfilename_simple(sort_entries[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
else
getfilename(nr);
}
@ -840,7 +832,7 @@ void CardReader::presort() {
else
getfilename_next(position);
sort_order[i] = i;
sort_positions[i] = position;
sort_entries[i] = position >> 5;
#if HAS_FOLDER_SORTING
if (filenameIsDir) dirCnt++;
#endif
@ -890,7 +882,7 @@ void CardReader::presort() {
manage_heater();
uint8_t orderBckp = sort_order[i];
getfilename_simple(sort_positions[orderBckp]);
getfilename_simple(sort_entries[orderBckp]);
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
crmod_date_bckp = crmodDate;
crmod_time_bckp = crmodTime;
@ -899,7 +891,7 @@ void CardReader::presort() {
#endif
uint16_t j = i;
getfilename_simple(sort_positions[sort_order[j - gap]]);
getfilename_simple(sort_entries[sort_order[j - gap]]);
char *name2 = LONGEST_FILENAME; // use the string in-place
#if HAS_FOLDER_SORTING
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_DIR(FOLDER_SORTING):_SORT_CMP_DIR(FOLDER_SORTING)))
@ -917,7 +909,7 @@ void CardReader::presort() {
printf_P(PSTR("i%2d j%2d gap%2d orderBckp%2d\n"), i, j, gap, orderBckp);
#endif
if (j < gap) break;
getfilename_simple(sort_positions[sort_order[j - gap]]);
getfilename_simple(sort_entries[sort_order[j - gap]]);
name2 = LONGEST_FILENAME; // use the string in-place
}
sort_order[j] = orderBckp;
@ -958,14 +950,14 @@ void CardReader::presort() {
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
counter++;
getfilename_simple(sort_positions[o1]);
getfilename_simple(sort_entries[o1]);
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
crmod_date_bckp = crmodDate;
crmod_time_bckp = crmodTime;
#if HAS_FOLDER_SORTING
bool dir1 = filenameIsDir;
#endif
getfilename_simple(sort_positions[o2]);
getfilename_simple(sort_entries[o2]);
char *name2 = LONGEST_FILENAME; // use the string in-place
// Sort the current pair according to settings.
@ -1003,26 +995,26 @@ void CardReader::presort() {
{
if (sort_order_reverse_index[i] != i)
{
uint32_t el = sort_positions[i];
uint32_t el = sort_entries[i];
uint8_t idx = sort_order_reverse_index[i];
while (idx != i)
{
uint32_t el1 = sort_positions[idx];
uint32_t el1 = sort_entries[idx];
uint8_t idx1 = sort_order_reverse_index[idx];
sort_order_reverse_index[idx] = idx;
sort_positions[idx] = el;
sort_entries[idx] = el;
idx = idx1;
el = el1;
}
sort_order_reverse_index[idx] = idx;
sort_positions[idx] = el;
sort_entries[idx] = el;
}
}
menu_progressbar_finish();
}
else {
getfilename(0);
sort_positions[0] = position;
sort_entries[0] = position >> 5;
}
sort_count = fileCnt;
@ -1030,7 +1022,6 @@ void CardReader::presort() {
lcd_update(2);
KEEPALIVE_STATE(NOT_BUSY);
lcd_timeoutToStatus.start();
}
void CardReader::flush_presort() {

View File

@ -46,7 +46,7 @@ public:
void printingHasFinished();
void getfilename(uint16_t nr, const char* const match=NULL);
void getfilename_simple(uint32_t position, const char * const match = NULL);
void getfilename_simple(uint16_t entry, const char * const match = NULL);
void getfilename_next(uint32_t position, const char * const match = NULL);
uint16_t getnrfilenames();
@ -111,7 +111,7 @@ private:
// Sort files and folders alphabetically.
#ifdef SDCARD_SORT_ALPHA
uint16_t sort_count; // Count of sorted items in the current directory
uint32_t sort_positions[SDSORT_LIMIT];
uint16_t sort_entries[SDSORT_LIMIT];
#endif // SDCARD_SORT_ALPHA
@ -130,13 +130,12 @@ private:
char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
uint32_t filesize;
//int16_t n;
unsigned long autostart_atmillis;
ShortTimer autostart_atmillis;
uint32_t sdpos ;
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
char* diveDirName;
uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
bool diveSubfolder (const char *&fileName);
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL, LsAction lsAction = LS_GetFilename, ls_param lsParams = ls_param());

View File

@ -2,8 +2,6 @@
#include "cardreader.h"
#include "ultralcd.h"
extern bool Stopped;
// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
// Head of the circular buffer, where to read.
@ -23,11 +21,10 @@ bool cmdbuffer_front_already_processed = false;
bool cmdqueue_serial_disabled = false;
int serial_count = 0; //index of character read from serial line
boolean comment_mode = false;
bool comment_mode = false;
char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
unsigned long TimeSent = _millis();
unsigned long TimeNow = _millis();
ShortTimer farm_incomplete_command_timeout_timer;
long gcode_N = 0;
long gcode_LastN = 0;
@ -97,7 +94,7 @@ void cmdqueue_reset()
{
while (buflen)
{
// printf_P(PSTR("dumping: \"%s\" of type %hu\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
// printf_P(PSTR("dumping: \"%s\" of type %u\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
ClearToSend();
cmdqueue_pop_front();
}
@ -396,14 +393,8 @@ void get_command()
while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) && !cmdqueue_serial_disabled) { //is print is saved (crash detection or filament detection), dont process data from serial line
char serial_char = MYSERIAL.read();
/* if (selectedSerialPort == 1)
{
selectedSerialPort = 0;
MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
selectedSerialPort = 1;
} */ //RP - removed
TimeSent = _millis();
TimeNow = _millis();
farm_incomplete_command_timeout_timer.start();
if (serial_char < 0)
// Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
@ -450,7 +441,7 @@ void get_command()
char *p = cmdbuffer+bufindw+CMDHDRSIZE;
while (p != strchr_pointer)
checksum = checksum^(*p++);
if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
if (code_value_short() != (int16_t)checksum) {
SERIAL_ERROR_START;
SERIAL_ERRORRPGM(_n("checksum mismatch, Last Line: "));////MSG_ERR_CHECKSUM_MISMATCH
SERIAL_ERRORLN(gcode_LastN);
@ -493,8 +484,7 @@ void get_command()
is_usb_printing = true;
}
if (Stopped == true) {
int gcode = strtol(strchr_pointer+1, NULL, 10);
if (gcode >= 0 && gcode <= 3) {
if (code_value_uint8() <= 3) {
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
LCD_MESSAGERPGM(_T(MSG_STOPPED));
}
@ -537,9 +527,8 @@ void get_command()
}
} // end of serial line processing loop
if(farm_mode){
TimeNow = _millis();
if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
if(farm_mode && (serial_count > 0)){
if (farm_incomplete_command_timeout_timer.expired(800)) {
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);

View File

@ -49,12 +49,9 @@ extern bool cmdqueue_serial_disabled;
extern uint32_t sdpos_atomic;
extern int serial_count;
extern boolean comment_mode;
extern bool comment_mode;
extern char *strchr_pointer;
extern unsigned long TimeSent;
extern unsigned long TimeNow;
extern long gcode_N;
extern long gcode_LastN;
extern long Stopped_gcode_LastN;

View File

@ -100,6 +100,11 @@ if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_u
if (eeprom_read_dword((uint32_t*)EEPROM_JOB_ID) == EEPROM_EMPTY_VALUE32)
eeprom_update_dword((uint32_t*)EEPROM_JOB_ID, 0);
if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255) {
eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
}
}
//! @brief Get default sheet name for index

View File

@ -931,10 +931,10 @@ pins
#define TXD DIO1
// SPI
#define SCK DIO52
#define MISO DIO50
#define MOSI DIO51
#define SS DIO53
#define SCK 52
#define MISO 50
#define MOSI 51
#define SS 53
// TWI (I2C)
#define SCL DIO21

View File

@ -124,7 +124,7 @@ uint16_t fsensor_oq_sh_sum;
ClFsensorPCB oFsensorPCB;
ClFsensorActionNA oFsensorActionNA;
bool bIRsensorStateFlag=false;
unsigned long nIRsensorLastTime;
ShortTimer tIRsensorCheckTimer;
#endif //IR_SENSOR_ANALOG
void fsensor_stop_and_save_print(void)
@ -188,7 +188,7 @@ void fsensor_init(void)
{
#ifdef PAT9125
uint8_t pat9125 = pat9125_init();
printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
printf_P(PSTR("PAT9125_init:%u\n"), pat9125);
#endif //PAT9125
uint8_t fsensor_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR);
fsensor_autoload_enabled=eeprom_read_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED);
@ -237,7 +237,7 @@ bool fsensor_enable(bool bUpdateEEPROM)
if (mmu_enabled == false) { //filament sensor is pat9125, enable only if it is working
uint8_t pat9125 = pat9125_init();
printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
printf_P(PSTR("PAT9125_init:%u\n"), pat9125);
if (pat9125)
fsensor_not_responding = false;
else
@ -349,7 +349,7 @@ bool fsensor_check_autoload(void)
if (!fsensor_enabled) return false;
if (!fsensor_autoload_enabled) return false;
if (ir_sensor_detected) {
if (digitalRead(IR_SENSOR_PIN) == 1) {
if (READ(IR_SENSOR_PIN)) {
fsensor_watch_autoload = true;
}
else if (fsensor_watch_autoload == true) {
@ -435,8 +435,8 @@ void fsensor_oq_meassure_stop(void)
{
if (!fsensor_enabled) return;
if (!fsensor_oq_meassure_enabled) return;
printf_P(PSTR("fsensor_oq_meassure_stop, %hhu samples\n"), fsensor_oq_samples);
printf_P(_N(" st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max);
printf_P(PSTR("fsensor_oq_meassure_stop, %u samples\n"), fsensor_oq_samples);
printf_P(_N(" st_sum=%u yd_sum=%u er_sum=%u er_max=%u\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max);
printf_P(_N(" yd_min=%u yd_max=%u yd_avg=%u sh_avg=%u\n"), fsensor_oq_yd_min, fsensor_oq_yd_max, (uint16_t)((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum), (uint16_t)(fsensor_oq_sh_sum / fsensor_oq_samples));
fsensor_oq_meassure = false;
}
@ -453,10 +453,10 @@ bool fsensor_oq_result(void)
bool res_er_sum = (fsensor_oq_er_sum <= FSENSOR_OQ_MAX_ES);
printf_P(_N(" er_sum = %u %S\n"), fsensor_oq_er_sum, (res_er_sum?_OK:_NG));
bool res_er_max = (fsensor_oq_er_max <= FSENSOR_OQ_MAX_EM);
printf_P(_N(" er_max = %hhu %S\n"), fsensor_oq_er_max, (res_er_max?_OK:_NG));
printf_P(_N(" er_max = %u %S\n"), fsensor_oq_er_max, (res_er_max?_OK:_NG));
uint8_t yd_avg = ((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum);
bool res_yd_avg = (yd_avg >= FSENSOR_OQ_MIN_YD) && (yd_avg <= FSENSOR_OQ_MAX_YD);
printf_P(_N(" yd_avg = %hhu %S\n"), yd_avg, (res_yd_avg?_OK:_NG));
printf_P(_N(" yd_avg = %u %S\n"), yd_avg, (res_yd_avg?_OK:_NG));
bool res_yd_max = (fsensor_oq_yd_max <= (yd_avg * FSENSOR_OQ_MAX_PD));
printf_P(_N(" yd_max = %u %S\n"), fsensor_oq_yd_max, (res_yd_max?_OK:_NG));
bool res_yd_min = (fsensor_oq_yd_min >= (yd_avg / FSENSOR_OQ_MAX_ND));
@ -472,7 +472,7 @@ bool fsensor_oq_result(void)
bool res_sh_avg = (sh_avg <= FSENSOR_OQ_MAX_SH);
if (yd_qua >= 8) res_sh_avg = true;
printf_P(_N(" sh_avg = %hhu %S\n"), sh_avg, (res_sh_avg?_OK:_NG));
printf_P(_N(" sh_avg = %u %S\n"), sh_avg, (res_sh_avg?_OK:_NG));
bool res = res_er_sum && res_er_max && res_yd_avg && res_yd_max && res_yd_min && res_sh_avg;
printf_P(_N("fsensor_oq_result %S\n"), (res?_OK:_NG));
return res;
@ -559,8 +559,8 @@ FORCE_INLINE static void fsensor_isr(int st_cnt)
#ifdef DEBUG_FSENSOR_LOG
if (fsensor_log)
{
printf_P(_N("FSENSOR cnt=%d dy=%d err=%hhu %S\n"), st_cnt, pat9125_y, fsensor_err_cnt, (fsensor_err_cnt > old_err_cnt)?_N("NG!"):_N("OK"));
if (fsensor_oq_meassure) printf_P(_N("FSENSOR st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu yd_max=%u\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max, fsensor_oq_yd_max);
printf_P(_N("FSENSOR cnt=%d dy=%d err=%u %S\n"), st_cnt, pat9125_y, fsensor_err_cnt, (fsensor_err_cnt > old_err_cnt)?_N("NG!"):_N("OK"));
if (fsensor_oq_meassure) printf_P(_N("FSENSOR st_sum=%u yd_sum=%u er_sum=%u er_max=%u yd_max=%u\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max, fsensor_oq_yd_max);
}
#endif //DEBUG_FSENSOR_LOG
@ -591,9 +591,8 @@ ISR(FSENSOR_INT_PIN_VECT)
void fsensor_setup_interrupt(void)
{
pinMode(FSENSOR_INT_PIN, OUTPUT);
digitalWrite(FSENSOR_INT_PIN, LOW);
WRITE(FSENSOR_INT_PIN, 0);
SET_OUTPUT(FSENSOR_INT_PIN);
fsensor_int_pin_old = 0;
//pciSetup(FSENSOR_INT_PIN);
@ -687,17 +686,17 @@ void fsensor_update(void)
#else //PAT9125
if (CHECK_FSENSOR && ir_sensor_detected)
{
if(digitalRead(IR_SENSOR_PIN))
if (READ(IR_SENSOR_PIN))
{ // IR_SENSOR_PIN ~ H
#ifdef IR_SENSOR_ANALOG
if(!bIRsensorStateFlag)
{
bIRsensorStateFlag=true;
nIRsensorLastTime=_millis();
tIRsensorCheckTimer.start();
}
else
{
if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
if(tIRsensorCheckTimer.expired(IR_SENSOR_STEADY))
{
uint8_t nMUX1,nMUX2;
uint16_t nADC;

View File

@ -331,7 +331,7 @@ void lcd_no_autoscroll(void)
void lcd_set_cursor(uint8_t col, uint8_t row)
{
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
uint8_t row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
if (row >= LCD_HEIGHT)
row = LCD_HEIGHT - 1; // we count rows starting w/0
lcd_currline = row;
@ -344,7 +344,7 @@ void lcd_createChar_P(uint8_t location, const uint8_t* charmap)
{
location &= 0x7; // we only have 8 locations 0-7
lcd_command(LCD_SETCGRAMADDR | (location << 3));
for (int i=0; i<8; i++)
for (uint8_t i = 0; i < 8; i++)
lcd_send(pgm_read_byte(&charmap[i]), HIGH);
}
@ -644,8 +644,6 @@ uint8_t lcd_status_update_delay = 0;
lcd_longpress_func_t lcd_longpress_func = 0;
lcd_charsetup_func_t lcd_charsetup_func = 0;
lcd_lcdupdate_func_t lcd_lcdupdate_func = 0;
static ShortTimer buttonBlanking;
@ -718,8 +716,6 @@ void lcd_update_enable(uint8_t enabled)
lcd_next_update_millis = _millis() - 1;
// Full update.
lcd_clear();
if (lcd_charsetup_func)
lcd_charsetup_func();
lcd_update(2);
} else
{
@ -741,7 +737,6 @@ void lcd_buttons_update(void)
if (READ(BTN_ENC) == 0)
{ //button is pressed
lcd_timeoutToStatus.start();
if (!buttonBlanking.running() || buttonBlanking.expired(BUTTON_BLANKING_TIME)) {
buttonBlanking.start();
safetyTimer.start();
@ -924,28 +919,6 @@ const uint8_t lcd_chardata_clock[8] PROGMEM = {
B00000,
B00000}; //thanks Sonny Mounicou
const uint8_t lcd_chardata_arrup[8] PROGMEM = {
B00100,
B01110,
B11111,
B00000,
B00000,
B00000,
B00000,
B00000};
const uint8_t lcd_chardata_arrdown[8] PROGMEM = {
B00000,
B00000,
B00000,
B00000,
B00000,
B10001,
B01010,
B00100};
void lcd_set_custom_characters(void)
{
lcd_createChar_P(LCD_STR_BEDTEMP[0], lcd_chardata_bedTemp);
@ -956,13 +929,6 @@ void lcd_set_custom_characters(void)
lcd_createChar_P(LCD_STR_FOLDER[0], lcd_chardata_folder);
lcd_createChar_P(LCD_STR_FEEDRATE[0], lcd_chardata_feedrate);
lcd_createChar_P(LCD_STR_CLOCK[0], lcd_chardata_clock);
//lcd_createChar_P(LCD_STR_ARROW_UP[0], lcd_chardata_arrup);
//lcd_createChar_P(LCD_STR_ARROW_DOWN[0], lcd_chardata_arrdown);
}
void lcd_set_custom_characters_arrows(void)
{
lcd_createChar_P(1, lcd_chardata_arrdown);
}
const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
@ -986,12 +952,7 @@ const uint8_t lcd_chardata_confirm[8] PROGMEM = {
void lcd_set_custom_characters_nextpage(void)
{
lcd_createChar_P(1, lcd_chardata_arr2down);
lcd_createChar_P(2, lcd_chardata_confirm);
}
void lcd_set_custom_characters_degree(void)
{
lcd_createChar_P(1, lcd_chardata_degree);
lcd_createChar_P(LCD_STR_ARROW_2_DOWN[0], lcd_chardata_arr2down);
lcd_createChar_P(LCD_STR_CONFIRM[0], lcd_chardata_confirm);
}

View File

@ -112,8 +112,6 @@ extern uint8_t lcd_status_update_delay;
extern lcd_longpress_func_t lcd_longpress_func;
extern bool lcd_longpress_trigger;
extern lcd_charsetup_func_t lcd_charsetup_func;
extern lcd_lcdupdate_func_t lcd_lcdupdate_func;
@ -191,22 +189,21 @@ private:
//Custom characters defined in the first 8 characters of the LCD
#define LCD_STR_BEDTEMP "\x00"
#define LCD_STR_DEGREE "\x01"
#define LCD_STR_THERMOMETER "\x02"
#define LCD_STR_UPLEVEL "\x03"
#define LCD_STR_REFRESH "\x04"
#define LCD_STR_FOLDER "\x05"
#define LCD_STR_FEEDRATE "\x06"
#define LCD_STR_CLOCK "\x07"
#define LCD_STR_ARROW_UP "\x0B"
#define LCD_STR_ARROW_DOWN "\x01"
#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
#define LCD_STR_BEDTEMP "\x00"
#define LCD_STR_DEGREE "\x01"
#define LCD_STR_ARROW_2_DOWN "\x01"
#define LCD_STR_THERMOMETER "\x02"
#define LCD_STR_CONFIRM "\x02"
#define LCD_STR_UPLEVEL "\x03"
#define LCD_STR_REFRESH "\x04"
#define LCD_STR_FOLDER "\x05"
#define LCD_STR_FEEDRATE "\x06"
#define LCD_STR_CLOCK "\x07"
#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
#define LCD_STR_SOLID_BLOCK "\xFF" //from the default character set
extern void lcd_set_custom_characters(void);
extern void lcd_set_custom_characters_arrows(void);
extern void lcd_set_custom_characters_nextpage(void);
extern void lcd_set_custom_characters_degree(void);
//! @brief Consume click event
inline void lcd_consume_click()

View File

@ -14,8 +14,6 @@
#include "static_assert.h"
#include "sound.h"
extern int32_t lcd_encoder;
#define MENU_DEPTH_MAX 7
static menu_record_t menu_stack[MENU_DEPTH_MAX];
@ -152,9 +150,7 @@ void menu_submenu_no_reset(menu_func_t submenu)
uint8_t menu_item_ret(void)
{
lcd_beeper_quick_feedback();
lcd_draw_update = 2;
lcd_button_pressed = false;
lcd_quick_feedback();
return 1;
}
@ -513,7 +509,7 @@ static void _menu_edit_P(void)
if (lcd_draw_update)
{
if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
else if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
lcd_set_cursor(0, 1);
menu_draw_P<T>(' ', _md->editLabel, (int)lcd_encoder);
}
@ -572,7 +568,7 @@ void menu_progressbar_update(uint16_t newVal)
newCnt = LCD_WIDTH;
while (newCnt > progressbar_block_count)
{
lcd_print('\xFF');
lcd_print(LCD_STR_SOLID_BLOCK[0]);
progressbar_block_count++;
}
}

View File

@ -993,7 +993,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
// we have to let the planner know where we are right now as it is not where we said to go.
update_current_position_z();
//printf_P(PSTR("Zs: %f, Z: %f, delta Z: %f"), z_bckp, current_position[Z_AXIS], (z_bckp - current_position[Z_AXIS]));
if (abs(current_position[Z_AXIS] - z_bckp) < 0.025) {
if (fabs(current_position[Z_AXIS] - z_bckp) < 0.025) {
//printf_P(PSTR("PINDA triggered immediately, move Z higher and repeat measurement\n"));
current_position[Z_AXIS] += 0.5;
go_to_current(homing_feedrate[Z_AXIS]/60);
@ -1019,7 +1019,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
// SERIAL_ECHOPGM("Bed find_bed_induction_sensor_point_z low, height: ");
// MYSERIAL.print(current_position[Z_AXIS], 5);
// SERIAL_ECHOLNPGM("");
float dz = i?abs(current_position[Z_AXIS] - (z / i)):0;
float dz = i?fabs(current_position[Z_AXIS] - (z / i)):0;
z += current_position[Z_AXIS];
//printf_P(PSTR("Z[%d] = %d, dz=%d\n"), i, (int)(current_position[Z_AXIS] * 1000), (int)(dz * 1000));
//printf_P(PSTR("Z- measurement deviation from avg value %f um\n"), dz);
@ -2240,7 +2240,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
/// Retry point scanning if a point with bad data appears.
/// Bad data could be cause by "cold" sensor.
/// This behavior vanishes after few point scans so retry will help.
for (int retries = 0; retries <= 1; ++retries) {
for (uint8_t retries = 0; retries <= 1; ++retries) {
bool retry = false;
for (int k = 0; k < 4; ++k) {
// Don't let the manage_inactivity() function remove power from the motors.
@ -2852,7 +2852,7 @@ bool sample_mesh_and_store_reference()
current_position[Y_AXIS] = BED_Y0;
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
go_to_current(homing_feedrate[X_AXIS]/60);
memcpy(destination, current_position, sizeof(destination));
set_destination_to_current();
enable_endstops(true);
homeaxis(Z_AXIS);
@ -2872,14 +2872,15 @@ bool sample_mesh_and_store_reference()
}
mbl.set_z(0, 0, current_position[Z_AXIS]);
}
for (int8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
static_assert(MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS <= 255, "overflow.....");
for (uint8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
// Don't let the manage_inactivity() function remove power from the motors.
refresh_cmd_timeout();
// Print the decrasing ID of the measurement point.
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
go_to_current(homing_feedrate[Z_AXIS]/60);
int8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
int8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag
current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);

View File

@ -129,16 +129,15 @@ inline bool world2machine_clamp(float &x, float &y)
if (tmpx < X_MIN_POS) {
tmpx = X_MIN_POS;
clamped = true;
}
if (tmpy < Y_MIN_POS) {
tmpy = Y_MIN_POS;
clamped = true;
}
if (tmpx > X_MAX_POS) {
} else if (tmpx > X_MAX_POS) {
tmpx = X_MAX_POS;
clamped = true;
}
if (tmpy > Y_MAX_POS) {
if (tmpy < Y_MIN_POS) {
tmpy = Y_MIN_POS;
clamped = true;
} else if (tmpy > Y_MAX_POS) {
tmpy = Y_MAX_POS;
clamped = true;
}

View File

@ -10,9 +10,7 @@ mesh_bed_leveling::mesh_bed_leveling() { reset(); }
void mesh_bed_leveling::reset() {
active = 0;
for (int y = 0; y < MESH_NUM_Y_POINTS; y++)
for (int x = 0; x < MESH_NUM_X_POINTS; x++)
z_values[y][x] = 0;
memset(z_values, 0, sizeof(float) * MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS);
}
static inline bool vec_undef(const float v[2])

View File

@ -24,12 +24,7 @@ public:
static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); }
static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); }
// Measurement point for the Z probe.
// If use_default=true, then the default positions for a correctly built printer are used.
// Otherwise a correction matrix is pulled from the EEPROM if available.
static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default);
void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; }
void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; }
int select_x_index(float x) {
int i = 1;

View File

@ -1,10 +1,8 @@
//messages.c
#include "language.h"
#include "lcd.h" // Needed for LCD_STR_REFRESH
//this is because we need include Configuration_prusa.h (CUSTOM_MENDEL_NAME)
#define bool char
#define true 1
#define false 0
#include "Configuration_prusa.h"
//internationalized messages
@ -80,7 +78,7 @@ const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unl
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\x04Refresh"); ////c=18
const char MSG_REFRESH[] PROGMEM_I1 = ISTR(LCD_STR_REFRESH "Refresh"); ////c=18
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
const char MSG_RESET[] PROGMEM_I1 = ISTR("Reset"); ////c=14
const char MSG_RESUME_PRINT[] PROGMEM_I1 = ISTR("Resume print"); ////c=18
@ -170,7 +168,7 @@ const char MSG_AUTO_DEPLETE[] PROGMEM_N1 = ISTR("SpoolJoin"); ////c=13
const char MSG_FIRMWARE[] PROGMEM_N1 = ISTR("Firmware"); ////c=8
const char MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY[] PROGMEM_N1 = ISTR("FlashAir"); ////c=8
const char MSG_PINDA[] PROGMEM_N1 = ISTR("PINDA");////c=5
const char WELCOME_MSG[] PROGMEM_N1 = ISTR(CUSTOM_MENDEL_NAME " OK."); ////c=20
const char MSG_WELCOME[] PROGMEM_N1 = WELCOME_MSG; ////c=20
const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////
const char MSG_BROWNOUT_RESET[] PROGMEM_N1 = " Brown out Reset"; ////
const char MSG_EXTERNAL_RESET[] PROGMEM_N1 = " External Reset"; ////
@ -204,3 +202,4 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
const char MSG_UNKNOWN_CODE[] PROGMEM_N1 = "Unknown %c code: %s\n";

View File

@ -7,6 +7,8 @@
extern "C" {
#endif //defined(__cplusplus)
#define WELCOME_MSG (CUSTOM_MENDEL_NAME " OK.")
// LCD Menu Messages
//internationalized messages
extern const char MSG_AUTO_HOME[];
@ -123,7 +125,7 @@ extern const char MSG_WIZARD_WELCOME[];
extern const char MSG_WIZARD_WELCOME_SHIPPING[];
extern const char MSG_YES[];
extern const char MSG_V2_CALIBRATION[];
extern const char WELCOME_MSG[];
extern const char MSG_WELCOME[];
extern const char MSG_OFF[];
extern const char MSG_ON[];
extern const char MSG_NA[];
@ -204,6 +206,7 @@ extern const char MSG_M112_KILL[];
extern const char MSG_ADVANCE_K[];
extern const char MSG_POWERPANIC_DETECTED[];
extern const char MSG_LCD_STATUS_CHANGED[];
extern const char MSG_UNKNOWN_CODE[];
#if defined(__cplusplus)
}

View File

@ -70,14 +70,14 @@ uint8_t mmu_extruder = MMU_FILAMENT_UNKNOWN;
uint8_t tmp_extruder = MMU_FILAMENT_UNKNOWN;
int8_t mmu_finda = -1;
uint32_t mmu_last_finda_response = 0;
int16_t mmu_version = -1;
int16_t mmu_buildnr = -1;
uint32_t mmu_last_request = 0;
uint32_t mmu_last_response = 0;
ShortTimer mmu_last_request;
ShortTimer mmu_last_response;
ShortTimer mmu_last_finda_response;
MmuCmd mmu_last_cmd = MmuCmd::None;
uint16_t mmu_power_failures = 0;
@ -113,7 +113,7 @@ int mmu_puts_P(const char* str)
{
mmu_clr_rx_buf(); //clear rx buffer
int r = fputs_P(str, uart2io); //send command
mmu_last_request = _millis();
mmu_last_request.start();
return r;
}
@ -125,7 +125,7 @@ int mmu_printf_P(const char* format, ...)
mmu_clr_rx_buf(); //clear rx buffer
int r = vfprintf_P(uart2io, format, args); //send command
va_end(args);
mmu_last_request = _millis();
mmu_last_request.start();
return r;
}
@ -133,7 +133,7 @@ int mmu_printf_P(const char* format, ...)
int8_t mmu_rx_ok(void)
{
int8_t res = uart2_rx_str_P(PSTR("ok\n"));
if (res == 1) mmu_last_response = _millis();
if (res == 1) mmu_last_response.start();
return res;
}
@ -141,7 +141,7 @@ int8_t mmu_rx_ok(void)
int8_t mmu_rx_start(void)
{
int8_t res = uart2_rx_str_P(PSTR("start\n"));
if (res == 1) mmu_last_response = _millis();
if (res == 1) mmu_last_response.start();
return res;
}
@ -149,8 +149,8 @@ int8_t mmu_rx_start(void)
void mmu_init(void)
{
#ifdef MMU_HWRESET
digitalWrite(MMU_RST_PIN, HIGH);
pinMode(MMU_RST_PIN, OUTPUT); //setup reset pin
WRITE(MMU_RST_PIN, 1);
SET_OUTPUT(MMU_RST_PIN); //setup reset pin
#endif //MMU_HWRESET
uart2_init(); //init uart2
_delay_ms(10); //wait 10ms for sure
@ -264,8 +264,8 @@ void mmu_loop(void)
case S::GetFindaInit:
if (mmu_rx_ok() > 0)
{
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
mmu_last_finda_response = _millis();
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer. MUST BE %hhu!!!
mmu_last_finda_response.start();
FDEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_finda);
puts_P(PSTR("MMU - ENABLED"));
mmu_enabled = true;
@ -350,7 +350,7 @@ void mmu_loop(void)
mmu_printf_P(PSTR("M%d\n"), SilentModeMenu_MMU);
mmu_state = S::SwitchMode;
}
else if ((mmu_last_response + 300) < _millis()) //request every 300ms
else if (mmu_last_response.expired(300)) //request every 300ms
{
#ifndef IR_SENSOR
if(check_for_ir_sensor()) ir_sensor_detected = true;
@ -377,8 +377,8 @@ void mmu_loop(void)
}
if (mmu_rx_ok() > 0)
{
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
mmu_last_finda_response = _millis();
fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer. MUST BE %hhu!!!
mmu_last_finda_response.start();
FDEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_finda);
//printf_P(PSTR("Eact: %d\n"), int(e_active()));
if (!mmu_finda && CHECK_FSENSOR && fsensor_enabled) {
@ -398,7 +398,7 @@ void mmu_loop(void)
if (mmu_cmd == MmuCmd::None)
mmu_ready = true;
}
else if ((mmu_last_request + MMU_P0_TIMEOUT) < _millis())
else if (mmu_last_request.expired(MMU_P0_TIMEOUT))
{ //resend request after timeout (30s)
mmu_state = S::Idle;
}
@ -424,7 +424,7 @@ void mmu_loop(void)
mmu_ready = true;
mmu_state = S::Idle;
}
else if ((mmu_last_request + MMU_CMD_TIMEOUT) < _millis())
else if (mmu_last_request.expired(MMU_CMD_TIMEOUT))
{ //resend request after timeout (5 min)
if (mmu_last_cmd != MmuCmd::None)
{
@ -467,7 +467,7 @@ void mmu_loop(void)
mmu_ready = true;
mmu_state = S::Idle;
}
else if ((mmu_last_request + MMU_CMD_TIMEOUT) < _millis())
else if (mmu_last_request.expired(MMU_CMD_TIMEOUT))
{ //timeout 45 s
mmu_state = S::Idle;
}
@ -479,7 +479,7 @@ void mmu_loop(void)
eeprom_update_byte((uint8_t*)EEPROM_MMU_STEALTH, SilentModeMenu_MMU);
mmu_state = S::Idle;
}
else if ((mmu_last_request + MMU_CMD_TIMEOUT) < _millis())
else if (mmu_last_request.expired(MMU_CMD_TIMEOUT))
{ //timeout 45 s
mmu_state = S::Idle;
}
@ -490,9 +490,9 @@ void mmu_loop(void)
void mmu_reset(void)
{
#ifdef MMU_HWRESET //HW - pulse reset pin
digitalWrite(MMU_RST_PIN, LOW);
WRITE(MMU_RST_PIN, 0);
_delay_us(100);
digitalWrite(MMU_RST_PIN, HIGH);
WRITE(MMU_RST_PIN, 1);
#else //SW - send X0 command
mmu_puts_P(PSTR("X0\n"));
#endif
@ -728,9 +728,6 @@ void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move)
screen=0;
}
lcd_set_degree();
//5 seconds delay
for (uint8_t i = 0; i < 5; i++) {
if (lcd_clicked()) {
@ -927,8 +924,8 @@ void change_extr(int
mmu_extruder = extr;
pinMode(E_MUX0_PIN, OUTPUT);
pinMode(E_MUX1_PIN, OUTPUT);
SET_OUTPUT(E_MUX0_PIN);
SET_OUTPUT(E_MUX1_PIN);
switch (extr) {
case 1:
@ -1366,7 +1363,7 @@ void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
lcd_return_to_status();
lcd_update_enable(true);
lcd_load_filament_color_check();
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
}
else

View File

@ -4,6 +4,7 @@
#define MMU_H
#include <inttypes.h>
#include "Timer.h"
extern bool mmu_enabled;
@ -14,7 +15,7 @@ extern uint8_t mmu_extruder;
extern uint8_t tmp_extruder;
extern int8_t mmu_finda;
extern uint32_t mmu_last_finda_response;
extern ShortTimer mmu_last_finda_response;
extern bool ir_sensor_detected;
extern int16_t mmu_version;

View File

@ -26,7 +26,7 @@
// The arc is approximated by generating a huge number of tiny, linear segments. The length of each
// segment is configured in settings.mm_per_arc_segment.
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
uint8_t axis_linear, float feed_rate, float radius, uint8_t isclockwise, uint8_t extruder)
uint8_t axis_linear, float feed_rate, float radius, bool isclockwise, uint8_t extruder)
{
// int acceleration_manager_was_enabled = plan_is_acceleration_manager_enabled();
// plan_set_acceleration_manager_enabled(false); // disable acceleration management for the duration of the arc

View File

@ -26,7 +26,7 @@
// offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is
// the direction of helical travel, radius == circle radius, isclockwise boolean. Used
// for vector transformation direction.
void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1,
unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder);
void mc_arc(float *position, float *target, float *offset, uint8_t axis_0, uint8_t axis_1,
uint8_t axis_linear, float feed_rate, float radius, bool isclockwise, uint8_t extruder);
#endif

View File

@ -188,8 +188,8 @@ uint8_t pat9125_init(void)
pat9125_wr_reg(PAT9125_RES_X, PAT9125_XRES);
pat9125_wr_reg(PAT9125_RES_Y, PAT9125_YRES);
fprintf_P(uartout, PSTR("PAT9125_RES_X=%hhu\n"), pat9125_rd_reg(PAT9125_RES_X));
fprintf_P(uartout, PSTR("PAT9125_RES_Y=%hhu\n"), pat9125_rd_reg(PAT9125_RES_Y));
fprintf_P(uartout, PSTR("PAT9125_RES_X=%u\n"), pat9125_rd_reg(PAT9125_RES_X));
fprintf_P(uartout, PSTR("PAT9125_RES_Y=%u\n"), pat9125_rd_reg(PAT9125_RES_Y));
return 1;
}

View File

@ -459,10 +459,7 @@ void plan_init() {
#ifdef LIN_ADVANCE
memset(position_float, 0, sizeof(position_float)); // clear position
#endif
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
memset(previous_speed, 0, sizeof(previous_speed));
previous_nominal_speed = 0.0;
plan_reset_next_e_queue = false;
plan_reset_next_e_sched = false;
@ -678,10 +675,7 @@ void planner_abort_hard()
#endif
// Resets planner junction speeds. Assumes start from rest.
previous_nominal_speed = 0.0;
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
memset(previous_speed, 0, sizeof(previous_speed));
plan_reset_next_e_queue = false;
plan_reset_next_e_sched = false;
@ -1023,7 +1017,7 @@ Having the real displacement of the head, we can calculate the total movement le
// Calculate speed in mm/second for each axis. No divide by zero due to previous checks.
float inverse_second = feed_rate * inverse_millimeters;
int moves_queued = moves_planned();
uint8_t moves_queued = moves_planned();
// slow down when de buffer starts to empty, rather than wait at the corner for a buffer refill
#ifdef SLOWDOWN
@ -1044,14 +1038,12 @@ Having the real displacement of the head, we can calculate the total movement le
// Calculate and limit speed in mm/sec for each axis
float current_speed[4];
float speed_factor = 1.0; //factor <=1 do decrease speed
// maxlimit_status &= ~0xf;
for(int i=0; i < 4; i++)
{
current_speed[i] = delta_mm[i] * inverse_second;
if(fabs(current_speed[i]) > max_feedrate[i])
{
speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i]));
maxlimit_status |= (1 << i);
}
}
@ -1095,7 +1087,7 @@ Having the real displacement of the head, we can calculate the total movement le
*/
block->use_advance_lead = extruder_advance_K > 0
&& delta_mm[E_AXIS] >= 0
&& abs(delta_mm[Z_AXIS]) < 0.5;
&& fabs(delta_mm[Z_AXIS]) < 0.5;
if (block->use_advance_lead) {
#ifdef LA_FLOWADJ
// M221/FLOW should change uniformly the extrusion thickness
@ -1133,13 +1125,13 @@ Having the real displacement of the head, we can calculate the total movement le
// Limit acceleration per axis
//FIXME Vojtech: One shall rather limit a projection of the acceleration vector instead of using the limit.
if(((float)block->acceleration_st * (float)block->steps_x.wide / (float)block->step_event_count.wide) > axis_steps_per_sqr_second[X_AXIS])
{ block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; maxlimit_status |= (X_AXIS_MASK << 4); }
{ block->acceleration_st = axis_steps_per_sqr_second[X_AXIS]; }
if(((float)block->acceleration_st * (float)block->steps_y.wide / (float)block->step_event_count.wide) > axis_steps_per_sqr_second[Y_AXIS])
{ block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; maxlimit_status |= (Y_AXIS_MASK << 4); }
{ block->acceleration_st = axis_steps_per_sqr_second[Y_AXIS]; }
if(((float)block->acceleration_st * (float)block->steps_e.wide / (float)block->step_event_count.wide) > axis_steps_per_sqr_second[E_AXIS])
{ block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; maxlimit_status |= (Z_AXIS_MASK << 4); }
{ block->acceleration_st = axis_steps_per_sqr_second[E_AXIS]; }
if(((float)block->acceleration_st * (float)block->steps_z.wide / (float)block->step_event_count.wide ) > axis_steps_per_sqr_second[Z_AXIS])
{ block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; maxlimit_status |= (E_AXIS_MASK << 4); }
{ block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS]; }
}
// Acceleration of the segment, in mm/sec^2
block->acceleration = block->acceleration_st / steps_per_mm;
@ -1414,10 +1406,7 @@ void plan_set_position(float x, float y, float z, const float &e)
#endif
st_set_position(position[X_AXIS], position[Y_AXIS], position[Z_AXIS], position[E_AXIS]);
previous_nominal_speed = 0.0; // Resets planner junction speeds. Assumes start from rest.
previous_speed[0] = 0.0;
previous_speed[1] = 0.0;
previous_speed[2] = 0.0;
previous_speed[3] = 0.0;
memset(previous_speed, 0, sizeof(previous_speed));
}
// Only useful in the bed leveling routine, when the mesh bed leveling is off.

View File

@ -192,7 +192,6 @@ extern unsigned long* max_acceleration_units_per_sq_second;
extern unsigned long axis_steps_per_sqr_second[NUM_AXIS];
extern long position[NUM_AXIS];
extern uint8_t maxlimit_status;
#ifdef AUTOTEMP

View File

@ -4,13 +4,13 @@
#define e_SOUND_MODE_NULL 0xFF
typedef enum
typedef enum : uint8_t
{e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_BLIND} eSOUND_MODE;
#define e_SOUND_MODE_DEFAULT e_SOUND_MODE_LOUD
typedef enum
typedef enum : uint8_t
{e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert,e_SOUND_TYPE_EncoderMove,e_SOUND_TYPE_BlindAlert} eSOUND_TYPE;
typedef enum
typedef enum : uint8_t
{e_SOUND_CLASS_Echo,e_SOUND_CLASS_Prompt,e_SOUND_CLASS_Confirm,e_SOUND_CLASS_Warning,e_SOUND_CLASS_Alert} eSOUND_CLASS;
@ -19,7 +19,6 @@ extern eSOUND_MODE eSoundMode;
extern void Sound_Init(void);
extern void Sound_Default(void);
extern void Sound_Save(void);
extern void Sound_CycleState(void);
extern void Sound_MakeSound(eSOUND_TYPE eSoundType);
extern void Sound_MakeCustom(uint16_t ms,uint16_t tone_ ,bool critical);

View File

@ -8,86 +8,101 @@ extern const uint16_t speed_lookuptable_slow[256][2] PROGMEM;
#ifndef _NO_ASM
// intRes = intIn1 * intIn2 >> 16
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
#define MultiU16X8toH16(intRes, charIn1, intIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %A1, %A2 \n\t" \
"add %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r0 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"clr r1 \n\t" \
: \
"=&r" (intRes) \
: \
"d" (charIn1), \
"d" (intIn2) \
: \
"r26" \
)
// return ((x * y) >> 8) with rounding when shifting right
FORCE_INLINE uint16_t MUL8x16R8(uint8_t x, uint16_t y) {
uint16_t out;
__asm__ (
// %0 out
// %1 x
// %2 y
// uint8_t: %An or %n
// uint16_t: %Bn %An
// __uint24: %Cn %Bn %An
// uint32_t: %Dn %Cn %Bn %An
//
//
// B2 A2 *
// A1
//---------
// B0 A0 RR
"mul %B2, %A1" "\n\t"
"movw %0, r0" "\n\t"
"mul %A2, %A1" "\n\t"
"lsl r0" "\n\t" //push MSB to carry for rounding
"adc %A0, r1" "\n\t" //add with carry (for rounding)
"clr r1" "\n\t" //make r1 __zero_reg__ again
"adc %B0, r1" "\n\t" //propagate carry of addition (add 0 with carry)
: "=&r" (out)
: "r" (x), "r" (y)
: "r0", "r1" //clobbers: Technically these are either scratch registers or always 0 registers, but I'm making sure the compiler knows just in case.
);
return out;
}
// intRes = longIn1 * longIn2 >> 24
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 48bit result
#define MultiU24X24toH16(intRes, longIn1, longIn2) \
asm volatile ( \
"clr r26 \n\t" \
"mul %A1, %B2 \n\t" \
"mov r27, r1 \n\t" \
"mul %B1, %C2 \n\t" \
"movw %A0, r0 \n\t" \
"mul %C1, %C2 \n\t" \
"add %B0, r0 \n\t" \
"mul %C1, %B2 \n\t" \
"add %A0, r0 \n\t" \
"adc %B0, r1 \n\t" \
"mul %A1, %C2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %B2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %C1, %A2 \n\t" \
"add r27, r0 \n\t" \
"adc %A0, r1 \n\t" \
"adc %B0, r26 \n\t" \
"mul %B1, %A2 \n\t" \
"add r27, r1 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"lsr r27 \n\t" \
"adc %A0, r26 \n\t" \
"adc %B0, r26 \n\t" \
"clr r1 \n\t" \
: \
"=&r" (intRes) \
: \
"d" (longIn1), \
"d" (longIn2) \
: \
"r26" , "r27" \
)
// return ((x * y) >> 24) with rounding when shifting right
FORCE_INLINE uint16_t MUL24x24R24(__uint24 x, __uint24 y) {
uint16_t out;
__asm__ (
// %0 out
// %1 x
// %2 y
// uint8_t: %An or %n
// uint16_t: %Bn %An
// __uint24: %Cn %Bn %An
// uint32_t: %Dn %Cn %Bn %An
//
//
// C2 B2 A2 *
// C1 B1 A1
//------------------
// -- B0 A0 RR RR RR
"clr r26 \n\t"
"mul %A1, %B2 \n\t"
"mov r27, r1 \n\t"
"mul %B1, %C2 \n\t"
"movw %A0, r0 \n\t"
"mul %C1, %C2 \n\t"
"add %B0, r0 \n\t"
"mul %C1, %B2 \n\t"
"add %A0, r0 \n\t"
"adc %B0, r1 \n\t"
"mul %A1, %C2 \n\t"
"add r27, r0 \n\t"
"adc %A0, r1 \n\t"
"adc %B0, r26 \n\t"
"mul %B1, %B2 \n\t"
"add r27, r0 \n\t"
"adc %A0, r1 \n\t"
"adc %B0, r26 \n\t"
"mul %C1, %A2 \n\t"
"add r27, r0 \n\t"
"adc %A0, r1 \n\t"
"adc %B0, r26 \n\t"
"mul %B1, %A2 \n\t"
"add r27, r1 \n\t"
"adc %A0, r26 \n\t"
"adc %B0, r26 \n\t"
"lsl r27 \n\t"
"adc %A0, r26 \n\t"
"adc %B0, r26 \n\t"
"clr r1 \n\t"
: "=&r" (out)
: "r" (x), "r" (y)
: "r0", "r1", "r26" , "r27" //clobbers: Technically these are either scratch registers or always 0 registers, but I'm making sure the compiler knows just in case. R26 is __zero_reg__, R27 is a temporary register.
);
return out;
}
#else //_NO_ASM
static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2)
FORCE_INLINE uint16_t MUL8x16R8(uint8_t charIn1, uint16_t intIn2)
{
intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16;
return ((uint32_t)charIn1 * (uint32_t)intIn2) >> 8;
}
static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2)
FORCE_INLINE uint16_t MUL24x24R24(uint32_t longIn1, uint32_t longIn2)
{
intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24;
return ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24;
}
#endif //_NO_ASM
@ -115,8 +130,7 @@ FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops)
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0];
unsigned char tmp_step_rate = (step_rate & 0x00ff);
uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2);
MultiU16X8toH16(timer, tmp_step_rate, gain);
timer = (unsigned short)pgm_read_word_near(table_address) - timer;
timer = (unsigned short)pgm_read_word_near(table_address) - MUL8x16R8(tmp_step_rate, gain);
}
else { // lower step rates
unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0];

View File

@ -108,12 +108,7 @@ static_assert(TMC2130_MINIMUM_DELAY 1, // this will fail to compile when non-emp
//=============================public variables ============================
//===========================================================================
block_t *current_block; // A pointer to the block currently being traced
bool x_min_endstop = false;
bool x_max_endstop = false;
bool y_min_endstop = false;
bool y_max_endstop = false;
bool z_min_endstop = false;
bool z_max_endstop = false;
//===========================================================================
//=============================private variables ============================
//===========================================================================
@ -133,11 +128,11 @@ static uint8_t step_loops;
static uint16_t OCR1A_nominal;
static uint8_t step_loops_nominal;
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
volatile long endstops_trigsteps[3]={0,0,0};
volatile long endstops_stepsTotal,endstops_stepsDone;
static volatile bool endstop_x_hit=false;
static volatile bool endstop_y_hit=false;
static volatile bool endstop_z_hit=false;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
static volatile uint8_t endstop_hit = 0;
#ifdef ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
bool abort_on_endstop_hit = false;
#endif
@ -147,17 +142,8 @@ bool abort_on_endstop_hit = false;
int motor_current_setting_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
#endif
#if ( (defined(X_MAX_PIN) && (X_MAX_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_XMAXLIMIT)
static bool old_x_max_endstop=false;
#endif
#if ( (defined(Y_MAX_PIN) && (Y_MAX_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_YMAXLIMIT)
static bool old_y_max_endstop=false;
#endif
static bool old_x_min_endstop=false;
static bool old_y_min_endstop=false;
static bool old_z_min_endstop=false;
static bool old_z_max_endstop=false;
static uint8_t endstop = 0;
static uint8_t old_endstop = 0;
static bool check_endstops = true;
@ -206,25 +192,25 @@ extern uint16_t stepper_timer_overflow_last;
void checkHitEndstops()
{
if( endstop_x_hit || endstop_y_hit || endstop_z_hit) {
if(endstop_hit) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
SERIAL_ECHO_START;
SERIAL_ECHORPGM(MSG_ENDSTOPS_HIT);
if(endstop_x_hit) {
if(endstop_hit & _BV(X_AXIS)) {
SERIAL_ECHOPAIR(" X:",(float)endstops_trigsteps[X_AXIS]/cs.axis_steps_per_unit[X_AXIS]);
// LCD_MESSAGERPGM(CAT2((MSG_ENDSTOPS_HIT), PSTR("X")));
}
if(endstop_y_hit) {
if(endstop_hit & _BV(Y_AXIS)) {
SERIAL_ECHOPAIR(" Y:",(float)endstops_trigsteps[Y_AXIS]/cs.axis_steps_per_unit[Y_AXIS]);
// LCD_MESSAGERPGM(CAT2((MSG_ENDSTOPS_HIT), PSTR("Y")));
}
if(endstop_z_hit) {
if(endstop_hit & _BV(Z_AXIS)) {
SERIAL_ECHOPAIR(" Z:",(float)endstops_trigsteps[Z_AXIS]/cs.axis_steps_per_unit[Z_AXIS]);
// LCD_MESSAGERPGM(CAT2((MSG_ENDSTOPS_HIT),PSTR("Z")));
}
SERIAL_ECHOLN("");
endstop_x_hit=false;
endstop_y_hit=false;
endstop_z_hit=false;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
endstop_hit = 0;
#if defined(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && defined(SDSUPPORT)
if (abort_on_endstop_hit)
{
@ -241,17 +227,17 @@ void checkHitEndstops()
bool endstops_hit_on_purpose()
{
bool hit = endstop_x_hit || endstop_y_hit || endstop_z_hit;
endstop_x_hit=false;
endstop_y_hit=false;
endstop_z_hit=false;
return hit;
uint8_t old = endstop_hit;
endstop_hit = 0;
return old;
}
bool endstop_z_hit_on_purpose()
{
bool hit = endstop_z_hit;
endstop_z_hit=false;
bool hit = endstop_hit & _BV(Z_AXIS);
CRITICAL_SECTION_START;
endstop_hit &= ~_BV(Z_AXIS);
CRITICAL_SECTION_END;
return hit;
}
@ -266,7 +252,9 @@ bool enable_z_endstop(bool check)
{
bool old = check_z_endstop;
check_z_endstop = check;
endstop_z_hit = false;
CRITICAL_SECTION_START;
endstop_hit &= ~_BV(Z_AXIS);
CRITICAL_SECTION_END;
return old;
}
@ -501,6 +489,9 @@ FORCE_INLINE void stepper_check_endstops()
{
if(check_endstops)
{
uint8_t _endstop_hit = endstop_hit;
uint8_t _endstop = endstop;
uint8_t _old_endstop = old_endstop;
#ifndef COREXY
if ((out_bits & (1<<X_AXIS)) != 0) // stepping along -X axis
#else
@ -510,33 +501,35 @@ FORCE_INLINE void stepper_check_endstops()
#if ( (defined(X_MIN_PIN) && (X_MIN_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_XMINLIMIT)
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
x_min_endstop = (READ(X_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, X_AXIS, (READ(X_TMC2130_DIAG) != 0));
#else
// Normal homing
x_min_endstop = (READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, X_AXIS, (READ(X_MIN_PIN) != X_MIN_ENDSTOP_INVERTING));
#endif
if(x_min_endstop && old_x_min_endstop && (current_block->steps_x.wide > 0)) {
if((_endstop & _old_endstop & _BV(X_AXIS)) && (current_block->steps_x.wide > 0)) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
endstop_x_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(X_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_x_min_endstop = x_min_endstop;
#endif
} else { // +direction
#if ( (defined(X_MAX_PIN) && (X_MAX_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_XMAXLIMIT)
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
x_max_endstop = (READ(X_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, X_AXIS + 4, (READ(X_TMC2130_DIAG) != 0));
#else
// Normal homing
x_max_endstop = (READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, X_AXIS + 4, (READ(X_MAX_PIN) != X_MAX_ENDSTOP_INVERTING));
#endif
if(x_max_endstop && old_x_max_endstop && (current_block->steps_x.wide > 0)){
if((_endstop & _old_endstop & _BV(X_AXIS + 4)) && (current_block->steps_x.wide > 0)){
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[X_AXIS] = count_position[X_AXIS];
endstop_x_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(X_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_x_max_endstop = x_max_endstop;
#endif
}
@ -545,37 +538,39 @@ FORCE_INLINE void stepper_check_endstops()
#else
if ((((out_bits & (1<<X_AXIS)) != 0)&&(out_bits & (1<<Y_AXIS)) == 0)) // -Y occurs for -A and +B
#endif
{
{
#if ( (defined(Y_MIN_PIN) && (Y_MIN_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_YMINLIMIT)
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
y_min_endstop = (READ(Y_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, Y_AXIS, (READ(Y_TMC2130_DIAG) != 0));
#else
// Normal homing
y_min_endstop = (READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, Y_AXIS, (READ(Y_MIN_PIN) != Y_MIN_ENDSTOP_INVERTING));
#endif
if(y_min_endstop && old_y_min_endstop && (current_block->steps_y.wide > 0)) {
if((_endstop & _old_endstop & _BV(Y_AXIS)) && (current_block->steps_y.wide > 0)) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(Y_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_y_min_endstop = y_min_endstop;
#endif
} else { // +direction
#if ( (defined(Y_MAX_PIN) && (Y_MAX_PIN > -1)) || defined(TMC2130_SG_HOMING) ) && !defined(DEBUG_DISABLE_YMAXLIMIT)
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
y_max_endstop = (READ(Y_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, Y_AXIS + 4, (READ(Y_TMC2130_DIAG) != 0));
#else
// Normal homing
y_max_endstop = (READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, Y_AXIS + 4, (READ(Y_MAX_PIN) != Y_MAX_ENDSTOP_INVERTING));
#endif
if(y_max_endstop && old_y_max_endstop && (current_block->steps_y.wide > 0)){
if((_endstop & _old_endstop & _BV(Y_AXIS + 4)) && (current_block->steps_y.wide > 0)){
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[Y_AXIS] = count_position[Y_AXIS];
endstop_y_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(Y_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_y_max_endstop = y_max_endstop;
#endif
}
@ -586,20 +581,21 @@ FORCE_INLINE void stepper_check_endstops()
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
#ifdef TMC2130_STEALTH_Z
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
else
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING));
else
#endif //TMC2130_STEALTH_Z
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING) || (READ(Z_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING) || (READ(Z_TMC2130_DIAG) != 0));
#else
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING));
#endif //TMC2130_SG_HOMING
if(z_min_endstop && old_z_min_endstop && (current_block->steps_z.wide > 0)) {
if((_endstop & _old_endstop & _BV(Z_AXIS)) && (current_block->steps_z.wide > 0)) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(Z_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_z_min_endstop = z_min_endstop;
}
#endif
} else { // +direction
@ -607,46 +603,57 @@ FORCE_INLINE void stepper_check_endstops()
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
#ifdef TMC2130_STEALTH_Z
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
z_max_endstop = false;
else
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
SET_BIT_TO(_endstop, Z_AXIS + 4, 0);
else
#endif //TMC2130_STEALTH_Z
z_max_endstop = (READ(Z_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, Z_AXIS + 4, (READ(Z_TMC2130_DIAG) != 0));
#else
z_max_endstop = (READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, Z_AXIS + 4, (READ(Z_MAX_PIN) != Z_MAX_ENDSTOP_INVERTING));
#endif //TMC2130_SG_HOMING
if(z_max_endstop && old_z_max_endstop && (current_block->steps_z.wide > 0)) {
if((_endstop & _old_endstop & _BV(Z_AXIS + 4)) && (current_block->steps_z.wide > 0)) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(Z_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_z_max_endstop = z_max_endstop;
#endif
}
endstop = _endstop;
old_endstop = _endstop; //apply current endstop state to the old endstop
endstop_hit = _endstop_hit;
}
// Supporting stopping on a trigger of the Z-stop induction sensor, not only for the Z-minus movements.
#if defined(Z_MIN_PIN) && (Z_MIN_PIN > -1) && !defined(DEBUG_DISABLE_ZMINLIMIT)
if (check_z_endstop) {
uint8_t _endstop_hit = endstop_hit;
uint8_t _endstop = endstop;
uint8_t _old_endstop = old_endstop;
// Check the Z min end-stop no matter what.
// Good for searching for the center of an induction target.
#ifdef TMC2130_SG_HOMING
// Stall guard homing turned on
#ifdef TMC2130_STEALTH_Z
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
else
if ((tmc2130_mode == TMC2130_MODE_SILENT) && !(tmc2130_sg_homing_axes_mask & 0x04))
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING));
else
#endif //TMC2130_STEALTH_Z
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING) || (READ(Z_TMC2130_DIAG) != 0);
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING) || (READ(Z_TMC2130_DIAG) != 0));
#else
z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
SET_BIT_TO(_endstop, Z_AXIS, (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING));
#endif //TMC2130_SG_HOMING
if(z_min_endstop && old_z_min_endstop) {
if(_endstop & _old_endstop & _BV(Z_AXIS)) {
#ifdef VERBOSE_CHECK_HIT_ENDSTOPS
endstops_trigsteps[Z_AXIS] = count_position[Z_AXIS];
endstop_z_hit=true;
#endif //VERBOSE_CHECK_HIT_ENDSTOPS
_endstop_hit |= _BV(Z_AXIS);
step_events_completed.wide = current_block->step_event_count.wide;
}
old_z_min_endstop = z_min_endstop;
endstop = _endstop;
old_endstop = _endstop; //apply current endstop state to the old endstop
endstop_hit = _endstop_hit;
}
#endif
}
@ -845,7 +852,7 @@ FORCE_INLINE void isr() {
//WRITE_NC(LOGIC_ANALYZER_CH1, true);
if (step_events_completed.wide <= current_block->accelerate_until) {
// v = t * a -> acc_step_rate = acceleration_time * current_block->acceleration_rate
MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
acc_step_rate = MUL24x24R24(acceleration_time, current_block->acceleration_rate);
acc_step_rate += uint16_t(current_block->initial_rate);
// upper limit
if(acc_step_rate > uint16_t(current_block->nominal_rate))
@ -865,8 +872,7 @@ FORCE_INLINE void isr() {
#endif
}
else if (step_events_completed.wide > current_block->decelerate_after) {
uint16_t step_rate;
MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
uint16_t step_rate = MUL24x24R24(deceleration_time, current_block->acceleration_rate);
if (step_rate > acc_step_rate) { // Check step_rate stays positive
step_rate = uint16_t(current_block->final_rate);
@ -1564,9 +1570,9 @@ void st_current_init() //Initialize Digipot Motor Current
#ifdef MOTOR_CURRENT_PWM_XY_PIN
uint8_t SilentMode = eeprom_read_byte((uint8_t*)EEPROM_SILENT);
SilentModeMenu = SilentMode;
pinMode(MOTOR_CURRENT_PWM_XY_PIN, OUTPUT);
pinMode(MOTOR_CURRENT_PWM_Z_PIN, OUTPUT);
pinMode(MOTOR_CURRENT_PWM_E_PIN, OUTPUT);
SET_OUTPUT(MOTOR_CURRENT_PWM_XY_PIN);
SET_OUTPUT(MOTOR_CURRENT_PWM_Z_PIN);
SET_OUTPUT(MOTOR_CURRENT_PWM_E_PIN);
if((SilentMode == SILENT_MODE_OFF) || (farm_mode) ){
motor_current_setting[0] = motor_current_setting_loud[0];
@ -1605,20 +1611,20 @@ void microstep_init()
{
#if defined(E1_MS1_PIN) && E1_MS1_PIN > -1
pinMode(E1_MS1_PIN,OUTPUT);
pinMode(E1_MS2_PIN,OUTPUT);
SET_OUTPUT(E1_MS1_PIN);
SET_OUTPUT(E1_MS2_PIN);
#endif
#if defined(X_MS1_PIN) && X_MS1_PIN > -1
const uint8_t microstep_modes[] = MICROSTEP_MODES;
pinMode(X_MS1_PIN,OUTPUT);
pinMode(X_MS2_PIN,OUTPUT);
pinMode(Y_MS1_PIN,OUTPUT);
pinMode(Y_MS2_PIN,OUTPUT);
pinMode(Z_MS1_PIN,OUTPUT);
pinMode(Z_MS2_PIN,OUTPUT);
pinMode(E0_MS1_PIN,OUTPUT);
pinMode(E0_MS2_PIN,OUTPUT);
SET_OUTPUT(X_MS1_PIN);
SET_OUTPUT(X_MS2_PIN);
SET_OUTPUT(Y_MS1_PIN);
SET_OUTPUT(Y_MS2_PIN);
SET_OUTPUT(Z_MS1_PIN);
SET_OUTPUT(Z_MS2_PIN);
SET_OUTPUT(E0_MS1_PIN);
SET_OUTPUT(E0_MS2_PIN);
for(int i=0;i<=4;i++) microstep_mode(i,microstep_modes[i]);
#endif
}
@ -1630,22 +1636,22 @@ void microstep_ms(uint8_t driver, int8_t ms1, int8_t ms2)
{
if(ms1 > -1) switch(driver)
{
case 0: digitalWrite( X_MS1_PIN,ms1); break;
case 1: digitalWrite( Y_MS1_PIN,ms1); break;
case 2: digitalWrite( Z_MS1_PIN,ms1); break;
case 3: digitalWrite(E0_MS1_PIN,ms1); break;
case 0: WRITE( X_MS1_PIN,ms1); break;
case 1: WRITE( Y_MS1_PIN,ms1); break;
case 2: WRITE( Z_MS1_PIN,ms1); break;
case 3: WRITE(E0_MS1_PIN,ms1); break;
#if defined(E1_MS1_PIN) && E1_MS1_PIN > -1
case 4: digitalWrite(E1_MS1_PIN,ms1); break;
case 4: WRITE(E1_MS1_PIN,ms1); break;
#endif
}
if(ms2 > -1) switch(driver)
{
case 0: digitalWrite( X_MS2_PIN,ms2); break;
case 1: digitalWrite( Y_MS2_PIN,ms2); break;
case 2: digitalWrite( Z_MS2_PIN,ms2); break;
case 3: digitalWrite(E0_MS2_PIN,ms2); break;
case 0: WRITE( X_MS2_PIN,ms2); break;
case 1: WRITE( Y_MS2_PIN,ms2); break;
case 2: WRITE( Z_MS2_PIN,ms2); break;
case 3: WRITE(E0_MS2_PIN,ms2); break;
#if defined(E1_MS2_PIN) && E1_MS2_PIN > -1
case 4: digitalWrite(E1_MS2_PIN,ms2); break;
case 4: WRITE(E1_MS2_PIN,ms2); break;
#endif
}
}
@ -1664,23 +1670,23 @@ void microstep_mode(uint8_t driver, uint8_t stepping_mode)
void microstep_readings()
{
SERIAL_PROTOCOLPGM("MS1,MS2 Pins\n");
SERIAL_PROTOCOLLNPGM("MS1,MS2 Pins");
SERIAL_PROTOCOLPGM("X: ");
SERIAL_PROTOCOL( digitalRead(X_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(X_MS2_PIN));
SERIAL_PROTOCOL( READ(X_MS1_PIN));
SERIAL_PROTOCOLLN( READ(X_MS2_PIN));
SERIAL_PROTOCOLPGM("Y: ");
SERIAL_PROTOCOL( digitalRead(Y_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(Y_MS2_PIN));
SERIAL_PROTOCOL( READ(Y_MS1_PIN));
SERIAL_PROTOCOLLN( READ(Y_MS2_PIN));
SERIAL_PROTOCOLPGM("Z: ");
SERIAL_PROTOCOL( digitalRead(Z_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(Z_MS2_PIN));
SERIAL_PROTOCOL( READ(Z_MS1_PIN));
SERIAL_PROTOCOLLN( READ(Z_MS2_PIN));
SERIAL_PROTOCOLPGM("E0: ");
SERIAL_PROTOCOL( digitalRead(E0_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(E0_MS2_PIN));
SERIAL_PROTOCOL( READ(E0_MS1_PIN));
SERIAL_PROTOCOLLN( READ(E0_MS2_PIN));
#if defined(E1_MS1_PIN) && E1_MS1_PIN > -1
SERIAL_PROTOCOLPGM("E1: ");
SERIAL_PROTOCOL( digitalRead(E1_MS1_PIN));
SERIAL_PROTOCOLLN( digitalRead(E1_MS2_PIN));
SERIAL_PROTOCOL( READ(E1_MS1_PIN));
SERIAL_PROTOCOLLN( READ(E1_MS2_PIN));
#endif
}
#endif //TMC2130

View File

@ -70,10 +70,6 @@ void invert_z_endstop(bool endstop_invert);
void checkStepperErrors(); //Print errors detected by the stepper
extern block_t *current_block; // A pointer to the block currently being traced
extern bool x_min_endstop;
extern bool x_max_endstop;
extern bool y_min_endstop;
extern bool y_max_endstop;
extern volatile long count_position[NUM_AXIS];
void quickStop();

View File

@ -204,7 +204,7 @@ static float analog2tempAmbient(int raw);
#endif
static void updateTemperaturesFromRawValues();
enum TempRunawayStates
enum TempRunawayStates : uint8_t
{
TempRunaway_INACTIVE = 0,
TempRunaway_PREHEAT = 1,
@ -220,12 +220,12 @@ enum TempRunawayStates
//===========================================================================
#if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0)
static float temp_runaway_status[4];
static float temp_runaway_target[4];
static float temp_runaway_timer[4];
static int temp_runaway_error_counter[4];
static uint8_t temp_runaway_status[1 + EXTRUDERS];
static float temp_runaway_target[1 + EXTRUDERS];
static uint32_t temp_runaway_timer[1 + EXTRUDERS];
static uint16_t temp_runaway_error_counter[1 + EXTRUDERS];
static void temp_runaway_check(int _heater_id, float _target_temperature, float _current_temperature, float _output, bool _isbed);
static void temp_runaway_check(uint8_t _heater_id, float _target_temperature, float _current_temperature, float _output, bool _isbed);
static void temp_runaway_stop(bool isPreheat, bool isBed);
#endif
@ -472,7 +472,7 @@ void __attribute__((noinline)) PID_autotune(float temp, int extruder, int ncycle
//SERIAL_ECHOPGM("s. Difference between current and ambient T: ");
//MYSERIAL.println(input - temp_ambient);
if (abs(input - temp_ambient) < 5.0) {
if (fabs(input - temp_ambient) < 5.0) {
temp_runaway_stop(false, (extruder<0));
pid_tuning_finished = true;
return;
@ -615,7 +615,7 @@ void fanSpeedError(unsigned char _fan) {
if (get_message_level() != 0 && isPrintPaused) return;
//to ensure that target temp. is not set to zero in case that we are resuming print
if (card.sdprinting || is_usb_printing) {
if (heating_status != 0) {
if (heating_status != HeatingStatus::NO_HEATING) {
lcd_print_stop();
}
else {
@ -625,7 +625,7 @@ void fanSpeedError(unsigned char _fan) {
else {
// SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED); //Why pause octoprint? is_usb_printing would be true in that case, so there is no need for this.
setTargetHotend0(0);
heating_status = 0;
heating_status = HeatingStatus::NO_HEATING;
fan_check_error = EFCE_REPORTED;
}
switch (_fan) {
@ -683,7 +683,7 @@ void manage_heater()
temp_runaway_check(0, target_temperature_bed, current_temperature_bed, (int)soft_pwm_bed, true);
#endif
for(int e = 0; e < EXTRUDERS; e++)
for(uint8_t e = 0; e < EXTRUDERS; e++)
{
#ifdef TEMP_RUNAWAY_EXTRUDER_HYSTERESIS
@ -1240,15 +1240,15 @@ void tp_init()
}
#if (defined (TEMP_RUNAWAY_BED_HYSTERESIS) && TEMP_RUNAWAY_BED_TIMEOUT > 0) || (defined (TEMP_RUNAWAY_EXTRUDER_HYSTERESIS) && TEMP_RUNAWAY_EXTRUDER_TIMEOUT > 0)
void temp_runaway_check(int _heater_id, float _target_temperature, float _current_temperature, float _output, bool _isbed)
void temp_runaway_check(uint8_t _heater_id, float _target_temperature, float _current_temperature, float _output, bool _isbed)
{
float __delta;
float __hysteresis = 0;
int __timeout = 0;
uint16_t __timeout = 0;
bool temp_runaway_check_active = false;
static float __preheat_start[2] = { 0,0}; //currently just bed and one extruder
static int __preheat_counter[2] = { 0,0};
static int __preheat_errors[2] = { 0,0};
static uint8_t __preheat_counter[2] = { 0,0};
static uint8_t __preheat_errors[2] = { 0,0};
if (_millis() - temp_runaway_timer[_heater_id] > 2000)
@ -1381,33 +1381,15 @@ void temp_runaway_check(int _heater_id, float _target_temperature, float _curren
void temp_runaway_stop(bool isPreheat, bool isBed)
{
cancel_heatup = true;
quickStop();
if (card.sdprinting)
disable_heater();
Sound_MakeCustom(200,0,true);
if (isPreheat)
{
card.sdprinting = false;
card.closefile();
}
// Clean the input command queue
// This is necessary, because in command queue there can be commands which would later set heater or bed temperature.
cmdqueue_reset();
disable_heater();
disable_x();
disable_y();
disable_e0();
disable_e1();
disable_e2();
manage_heater();
lcd_update(0);
Sound_MakeCustom(200,0,true);
if (isPreheat)
{
Stop();
isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR");
lcd_setalertstatuspgm(isBed? PSTR("BED PREHEAT ERROR") : PSTR("PREHEAT ERROR"), LCD_STATUS_CRITICAL);
SERIAL_ERROR_START;
isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY ( PREHEAT HOTEND)");
isBed ? SERIAL_ERRORLNPGM(" THERMAL RUNAWAY (PREHEAT HEATBED)") : SERIAL_ERRORLNPGM(" THERMAL RUNAWAY (PREHEAT HOTEND)");
#ifdef EXTRUDER_ALTFAN_DETECT
altfanStatus.altfanOverride = 1; //full speed
#endif //EXTRUDER_ALTFAN_DETECT
@ -1418,16 +1400,16 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
#else //FAN_SOFT_PWM
analogWrite(FAN_PIN, 255);
#endif //FAN_SOFT_PWM
fanSpeed = 255;
delayMicroseconds(2000);
}
else
{
isBed ? LCD_ALERTMESSAGEPGM("BED THERMAL RUNAWAY") : LCD_ALERTMESSAGEPGM("THERMAL RUNAWAY");
lcd_setalertstatuspgm(isBed? PSTR("BED THERMAL RUNAWAY") : PSTR("THERMAL RUNAWAY"), LCD_STATUS_CRITICAL);
SERIAL_ERROR_START;
isBed ? SERIAL_ERRORLNPGM(" HEATBED THERMAL RUNAWAY") : SERIAL_ERRORLNPGM(" HOTEND THERMAL RUNAWAY");
}
Stop();
}
#endif
@ -1483,13 +1465,12 @@ uint8_t last_alert_sent_to_lcd = LCDALERT_NONE;
//! update the current temperature error message
//! @param type short error abbreviation (PROGMEM)
//! @param func optional lcd update function (lcd_setalertstatus when first setting the error)
void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*) = lcd_updatestatus)
void temp_update_messagepgm(const char* PROGMEM type)
{
char msg[LCD_WIDTH];
strcpy_P(msg, PSTR("Err: "));
strcat_P(msg, type);
(*func)(msg);
lcd_setalertstatus(msg, LCD_STATUS_CRITICAL);
}
//! signal a temperature error on both the lcd and serial
@ -1497,7 +1478,7 @@ void temp_update_messagepgm(const char* PROGMEM type, void (*func)(const char*)
//! @param e optional extruder index for hotend errors
void temp_error_messagepgm(const char* PROGMEM type, uint8_t e = EXTRUDERS)
{
temp_update_messagepgm(type, lcd_setalertstatus);
temp_update_messagepgm(type);
SERIAL_ERROR_START;

View File

@ -23,9 +23,8 @@
#include "Marlin.h"
#include "planner.h"
#ifdef PID_ADD_EXTRUSION_RATE
#include "stepper.h"
#endif
#include "stepper.h"
#include "config.h"
@ -67,7 +66,7 @@ bool has_temperature_compensation();
#endif
#ifdef AMBIENT_THERMISTOR
//extern int current_temperature_raw_ambient;
extern int current_temperature_raw_ambient;
extern float current_temperature_ambient;
#endif
@ -91,7 +90,10 @@ extern bool bedPWMDisabled;
#ifdef PIDTEMP
extern int pid_cycle, pid_number_of_cycles;
extern float Kc,_Kp,_Ki,_Kd;
extern float _Kp,_Ki,_Kd;
#ifdef PID_ADD_EXTRUSION_RATE
extern float Kc;
#endif
extern bool pid_tuning_finished;
float scalePID_i(float i);
float scalePID_d(float d);
@ -166,7 +168,7 @@ static inline void setTargetHotendSafe(const float &celsius, uint8_t extruder)
// Doesn't save FLASH when not inlined.
static inline void setAllTargetHotends(const float &celsius)
{
for(int i=0;i<EXTRUDERS;i++) setTargetHotend(celsius,i);
for(uint8_t i = 0; i < EXTRUDERS; i++) setTargetHotend(celsius, i);
}
FORCE_INLINE void setTargetBed(const float &celsius) {
@ -220,7 +222,7 @@ FORCE_INLINE bool isCoolingBed() {
#define CHECK_ALL_HEATERS (checkAllHotends()||(target_temperature_bed!=0))
int getHeaterPower(int heater);
void disable_heater();
void disable_heater(); // Disable all heaters
void updatePID();

View File

@ -8,6 +8,7 @@
#include "ultralcd.h"
#include "language.h"
#include "spi.h"
#include "Timer.h"
#define TMC2130_GCONF_NORMAL 0x00000000 // spreadCycle
#define TMC2130_GCONF_SGSENS 0x00003180 // spreadCycle with stallguard (stall activates DIAG0 and DIAG1 [pushpull])
@ -71,7 +72,8 @@ uint16_t tmc2130_sg_cnt[4] = {0, 0, 0, 0};
bool tmc2130_sg_change = false;
#endif
bool skip_debug_msg = false;
//used for triggering a periodic check (1s) of the overtemperature pre-warning flag at ~120C (+-20C)
ShortTimer tmc2130_overtemp_timer;
#define DBG(args...)
//printf_P(args)
@ -243,8 +245,6 @@ uint8_t tmc2130_sample_diag()
return mask;
}
extern bool is_usb_printing;
void tmc2130_st_isr()
{
if (tmc2130_mode == TMC2130_MODE_SILENT || tmc2130_sg_stop_on_crash == false) return;
@ -394,16 +394,13 @@ bool tmc2130_wait_standstill_xy(int timeout)
return standstill;
}
void tmc2130_check_overtemp()
{
static uint32_t checktime = 0;
if (_millis() - checktime > 1000 )
if (tmc2130_overtemp_timer.expired(1000) || !tmc2130_overtemp_timer.running())
{
for (uint_least8_t i = 0; i < 4; i++)
{
uint32_t drv_status = 0;
skip_debug_msg = true;
tmc2130_rd(i, TMC2130_REG_DRV_STATUS, &drv_status);
if (drv_status & ((uint32_t)1 << 26))
{ // BIT 26 - over temp prewarning ~120C (+-20C)
@ -415,7 +412,7 @@ void tmc2130_check_overtemp()
}
}
checktime = _millis();
tmc2130_overtemp_timer.start();
#ifdef DEBUG_CRASHDET_COUNTERS
tmc2130_sg_change = true;
#endif
@ -474,8 +471,8 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
intpol = 0;
}
#endif
// DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r);
// DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl);
// DBG(_n("tmc2130_setup_chopper(axis=%d, mres=%d, curh=%d, curr=%d\n"), axis, mres, current_h, current_r);
// DBG(_n(" toff=%d, hstr=%d, hend=%d, tbl=%d\n"), toff, hstrt, hend, tbl);
if (current_r <= 31)
{
tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, dedge, 0);
@ -514,7 +511,7 @@ void tmc2130_print_currents()
void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
{
// DBG(_n("tmc2130_set_pwm_ampl(axis=%hhd, pwm_ampl=%hhd\n"), axis, pwm_ampl);
// DBG(_n("tmc2130_set_pwm_ampl(axis=%d, pwm_ampl=%d\n"), axis, pwm_ampl);
tmc2130_pwm_ampl[axis] = pwm_ampl;
if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@ -522,7 +519,7 @@ void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_grad)
{
// DBG(_n("tmc2130_set_pwm_grad(axis=%hhd, pwm_grad=%hhd\n"), axis, pwm_grad);
// DBG(_n("tmc2130_set_pwm_grad(axis=%d, pwm_grad=%d\n"), axis, pwm_grad);
tmc2130_pwm_grad[axis] = pwm_grad;
if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@ -896,7 +893,7 @@ void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000)
{
// TMC2130 wave compression algorithm
// optimized for minimal memory requirements
// printf_P(PSTR("tmc2130_set_wave %hhd %hhd\n"), axis, fac1000);
// printf_P(PSTR("tmc2130_set_wave %d %d\n"), axis, fac1000);
if (fac1000 < TMC2130_WAVE_FAC1000_MIN) fac1000 = 0;
if (fac1000 > TMC2130_WAVE_FAC1000_MAX) fac1000 = TMC2130_WAVE_FAC1000_MAX;
float fac = 0;
@ -910,11 +907,11 @@ void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000)
uint8_t x[3] = {255,255,255}; //X segment bounds (MSLUTSEL)
uint8_t s = 0; //current segment
int8_t b; //encoded bit value
int8_t dA; //delta value
int i; //microstep index
int8_t dA; //delta value
uint8_t i = 0; //microstep index
uint32_t reg = 0; //tmc2130 register
tmc2130_wr_MSLUTSTART(axis, 0, amp);
for (i = 0; i < 256; i++)
do
{
if ((i & 0x1f) == 0)
reg = 0;
@ -966,7 +963,7 @@ void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000)
else
reg >>= 1;
// printf("%3d\t%3d\t%2d\t%2d\t%2d\t%2d %08x\n", i, vA, dA, b, w[s], s, reg);
}
} while (i++ != 255);
tmc2130_wr_MSLUTSEL(axis, x[0], x[1], x[2], w[0], w[1], w[2], w[3]);
}

View File

@ -55,7 +55,7 @@
int clock_interval = 0;
static ShortTimer NcTime;
static void lcd_sd_updir();
static void lcd_mesh_bed_leveling_settings();
#ifdef LCD_BL_PIN
@ -78,16 +78,14 @@ LcdCommands lcd_commands_type = LcdCommands::Idle;
static uint8_t lcd_commands_step = 0;
CustomMsg custom_message_type = CustomMsg::Status;
unsigned int custom_message_state = 0;
uint8_t custom_message_state = 0;
bool isPrintPaused = false;
uint8_t farm_mode = 0;
int farm_timer = 8;
uint8_t farm_status = 0;
uint8_t farm_timer = 8;
bool printer_connected = true;
unsigned long display_time; //just timer for showing pid finished message on lcd;
static ShortTimer display_time; //just timer for showing pid finished message on lcd;
float pid_temp = DEFAULT_PID_TEMP;
static bool forceMenuExpire = false;
@ -99,8 +97,7 @@ static float manual_feedrate[] = MANUAL_FEEDRATE;
/* !Configuration settings */
uint8_t lcd_status_message_level;
char lcd_status_message[LCD_WIDTH + 1] = ""; //////WELCOME!
unsigned char firstrun = 1;
char lcd_status_message[LCD_WIDTH + 1] = WELCOME_MSG;
static uint8_t lay1cal_filament = 0;
@ -127,7 +124,7 @@ static void lcd_control_temperature_menu();
#ifdef TMC2130
static void lcd_settings_linearity_correction_menu_save();
#endif
static void prusa_stat_printerstatus(int _status);
static void prusa_stat_printerstatus(uint8_t _status);
static void prusa_stat_farm_number();
static void prusa_stat_diameter();
static void prusa_stat_temperatures();
@ -161,8 +158,8 @@ static void lcd_belttest_v();
static void lcd_selftest_v();
#ifdef TMC2130
static void reset_crash_det(unsigned char axis);
static bool lcd_selfcheck_axis_sg(unsigned char axis);
static void reset_crash_det(uint8_t axis);
static bool lcd_selfcheck_axis_sg(uint8_t axis);
#else
static bool lcd_selfcheck_axis(int _axis, int _travel);
static bool lcd_selfcheck_pulleys(int axis);
@ -206,8 +203,8 @@ enum class TestError : uint_least8_t
FsensorLevel
};
static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay);
static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name, const char *_indicator);
static uint8_t lcd_selftest_screen(TestScreen screen, uint8_t _progress, uint8_t _progress_scale, bool _clear, uint16_t _delay);
static void lcd_selftest_screen_step(uint8_t _row, uint8_t _col, uint8_t _state, const char *_name, const char *_indicator);
static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
bool _default=false);
@ -241,9 +238,7 @@ static void lcd_detect_IRsensor();
#endif //IR_SENSOR_ANALOG
static void lcd_selftest_error(TestError error, const char *_error_1, const char *_error_2);
static void lcd_colorprint_change();
#ifdef SNMM
static int get_ext_nr();
#endif //SNMM
#if defined (SNMM) || defined(SNMM_V2)
static void fil_load_menu();
static void fil_unload_menu();
@ -458,7 +453,7 @@ void lcdui_print_percent_done(void)
const char* src = is_usb_printing?_N("USB"):(IS_SD_PRINTING?_N(" SD"):_N(" "));
char per[4];
bool num = IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT));
if (!num || heating_status) // either not printing or heating
if (!num || heating_status != HeatingStatus::NO_HEATING) // either not printing or heating
{
const int8_t sheetNR = eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet));
const int8_t nextSheet = eeprom_next_initialized_sheet(sheetNR);
@ -471,7 +466,7 @@ void lcdui_print_percent_done(void)
return; //do not also print the percentage
}
}
sprintf_P(per, num?_N("%3hhd"):_N("---"), calc_percent_done());
sprintf_P(per, num?_N("%3d"):_N("---"), calc_percent_done());
lcd_printf_P(_N("%3S%3s%%"), src, per);
}
@ -575,7 +570,7 @@ void lcdui_print_time(void)
//! @Brief Print status line on status screen
void lcdui_print_status_line(void)
{
if (heating_status) { // If heating flag, show progress of heating
if (heating_status != HeatingStatus::NO_HEATING) { // If heating flag, show progress of heating
heating_status_counter++;
if (heating_status_counter > 13) {
heating_status_counter = 0;
@ -583,24 +578,24 @@ void lcdui_print_status_line(void)
lcd_set_cursor(7, 3);
lcd_space(13);
for (unsigned int dots = 0; dots < heating_status_counter; dots++) {
for (uint8_t dots = 0; dots < heating_status_counter; dots++) {
lcd_putc_at(7 + dots, 3, '.');
}
switch (heating_status) {
case 1:
case HeatingStatus::EXTRUDER_HEATING:
lcd_puts_at_P(0, 3, _T(MSG_HEATING));
break;
case 2:
case HeatingStatus::EXTRUDER_HEATING_COMPLETE:
lcd_puts_at_P(0, 3, _T(MSG_HEATING_COMPLETE));
heating_status = 0;
heating_status = HeatingStatus::NO_HEATING;
heating_status_counter = 0;
break;
case 3:
case HeatingStatus::BED_HEATING:
lcd_puts_at_P(0, 3, _T(MSG_BED_HEATING));
break;
case 4:
case HeatingStatus::BED_HEATING_COMPLETE:
lcd_puts_at_P(0, 3, _T(MSG_BED_DONE));
heating_status = 0;
heating_status = HeatingStatus::NO_HEATING;
heating_status_counter = 0;
break;
default:
@ -610,15 +605,14 @@ void lcdui_print_status_line(void)
else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
if(strlen(longFilenameOLD) > LCD_WIDTH) {
int inters = 0;
int gh = scrollstuff;
while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0)) {
uint8_t gh = scrollstuff;
while (((gh - scrollstuff) < LCD_WIDTH)) {
if (longFilenameOLD[gh] == '\0') {
lcd_set_cursor(gh - scrollstuff, 3);
lcd_print(longFilenameOLD[gh - 1]);
scrollstuff = 0;
gh = scrollstuff;
inters = 1;
break;
} else {
lcd_set_cursor(gh - scrollstuff, 3);
lcd_print(longFilenameOLD[gh - 1]);
@ -646,8 +640,7 @@ void lcdui_print_status_line(void)
} else {
if (custom_message_state == 3)
{
lcd_puts_P(_T(WELCOME_MSG));
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
}
if (custom_message_state > 3 && custom_message_state <= 10 ) {
@ -694,7 +687,7 @@ void lcdui_print_status_line(void)
}
// Fill the rest of line to have nice and clean output
for(int fillspace = 0; fillspace < LCD_WIDTH; fillspace++)
for(uint8_t fillspace = 0; fillspace < LCD_WIDTH; fillspace++)
if ((lcd_status_message[fillspace] <= 31 ))
lcd_print(' ');
}
@ -775,21 +768,6 @@ void lcdui_print_status_screen(void)
// Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent
void lcd_status_screen() // NOT static due to using inside "Marlin_main" module ("manage_inactivity()")
{
if (firstrun == 1)
{
firstrun = 0;
if(lcd_status_message_level == 0)
{
strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH);
lcd_finishstatus();
}
if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255)
{
eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
}
}
#ifdef ULTIPANEL_FEEDMULTIPLY
// Dead zone at 100% feedrate
if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
@ -1166,7 +1144,7 @@ void lcd_commands()
if (lcd_commands_step == 1 && !blocks_queued() && cmd_buffer_empty())
{
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
lcd_commands_step = 0;
lcd_commands_type = 0;
if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) == 1) {
@ -1255,7 +1233,7 @@ void lcd_commands()
lcd_commands_step = 1;
break;
case 1:
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
lcd_commands_step = 0;
lcd_commands_type = LcdCommands::Idle;
if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) == 1)
@ -1345,11 +1323,11 @@ void lcd_commands()
else {
SERIAL_ECHOPGM("Invalid PID cal. results. Not stored to EEPROM.");
}
display_time = _millis();
display_time.start();
lcd_commands_step = 1;
}
if ((lcd_commands_step == 1) && ((_millis()- display_time)>2000)) { //calibration finished message
lcd_setstatuspgm(_T(WELCOME_MSG));
if ((lcd_commands_step == 1) && display_time.expired(2000)) { //calibration finished message
lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
pid_temp = DEFAULT_PID_TEMP;
lcd_commands_step = 0;
@ -1386,8 +1364,6 @@ void lcd_pause_usb_print()
SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSE);
}
float move_menu_scale;
static void lcd_move_menu_axis();
@ -1399,7 +1375,6 @@ static void lcd_cooldown()
setAllTargetHotends(0);
setTargetBed(0);
fanSpeed = 0;
eFilamentAction = FilamentAction::None;
lcd_return_to_status();
}
@ -2317,8 +2292,10 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed)
}
}
lcd_set_cursor(0, 0);
lcdui_print_temp(LCD_STR_THERMOMETER[0], (int) degHotend(0), (int) degTargetHotend(0));
if (bFilamentWaitingFlag) {
lcd_set_cursor(0, 0);
lcdui_print_temp(LCD_STR_THERMOMETER[0], (int) degHotend(0), (int) degTargetHotend(0));
}
if (lcd_clicked())
{
@ -2707,7 +2684,7 @@ void lcd_menu_statistics()
"%S:\n"
"%18.2fm \n"
"%S:\n"
"%10ldh %02hhdm %02hhds"
"%10ldh %02dm %02ds"
),
_i("Filament used"), _met, ////MSG_FILAMENT_USED c=19
_i("Print time"), _h, _m, _s); ////MSG_PRINT_TIME c=19
@ -2729,7 +2706,7 @@ void lcd_menu_statistics()
"%S:\n"
"%18.2fm \n"
"%S:\n"
"%10ldd %02hhdh %02hhdm"
"%10ldd %02dh %02dm"
),
_i("Total filament"), _filament_m, ////MSG_TOTAL_FILAMENT c=19
_i("Total print time"), _days, _hours, _minutes); ////MSG_TOTAL_PRINT_TIME c=19
@ -2738,7 +2715,7 @@ void lcd_menu_statistics()
}
static void _lcd_move(const char *name, int axis, int min, int max)
static void _lcd_move(const char *name, uint8_t axis, int min, int max)
{
if (homing_flag || mesh_bed_leveling_flag)
{
@ -2764,7 +2741,7 @@ static void _lcd_move(const char *name, int axis, int min, int max)
refresh_cmd_timeout();
if (! planner_queue_full())
{
current_position[axis] += float((int)lcd_encoder) * move_menu_scale;
current_position[axis] += float((int)lcd_encoder);
if (min_software_endstops && current_position[axis] < min) current_position[axis] = min;
if (max_software_endstops && current_position[axis] > max) current_position[axis] = max;
lcd_encoder = 0;
@ -2792,7 +2769,7 @@ void lcd_move_e()
refresh_cmd_timeout();
if (! planner_queue_full())
{
current_position[E_AXIS] += float((int)lcd_encoder) * move_menu_scale;
current_position[E_AXIS] += float((int)lcd_encoder);
lcd_encoder = 0;
plan_buffer_line_curposXYZE(manual_feedrate[E_AXIS] / 60);
lcd_draw_update = 1;
@ -3218,7 +3195,6 @@ void lcd_adjust_z() {
#ifdef PINDA_THERMISTOR
bool lcd_wait_for_pinda(float temp) {
lcd_set_custom_characters_degree();
setAllTargetHotends(0);
setTargetBed(0);
LongTimer pinda_timeout;
@ -3233,7 +3209,7 @@ bool lcd_wait_for_pinda(float temp) {
lcd_print(ftostr3(current_temperature_pinda));
lcd_print('/');
lcd_print(ftostr3(temp));
lcd_print(LCD_STR_DEGREE);
lcd_print(LCD_STR_DEGREE[0]);
delay_keep_alive(1000);
serialecho_temperatures();
if (pinda_timeout.expired(8 * 60 * 1000ul)) { //PINDA cooling from 60 C to 35 C takes about 7 minutes
@ -3241,7 +3217,6 @@ bool lcd_wait_for_pinda(float temp) {
break;
}
}
lcd_set_custom_characters_arrows();
lcd_update_enable(true);
return target_temp_reached;
}
@ -3249,17 +3224,15 @@ bool lcd_wait_for_pinda(float temp) {
void lcd_wait_for_heater() {
lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
lcd_set_degree();
lcd_set_cursor(0, 4);
lcd_print(LCD_STR_THERMOMETER[0]);
lcd_print(ftostr3(degHotend(active_extruder)));
lcd_print('/');
lcd_print(ftostr3(degTargetHotend(active_extruder)));
lcd_print(LCD_STR_DEGREE);
lcd_print(LCD_STR_DEGREE[0]);
}
void lcd_wait_for_cool_down() {
lcd_set_custom_characters_degree();
setAllTargetHotends(0);
setTargetBed(0);
int fanSpeedBckp = fanSpeed;
@ -3271,19 +3244,17 @@ void lcd_wait_for_cool_down() {
lcd_print(LCD_STR_THERMOMETER[0]);
lcd_print(ftostr3(degHotend(0)));
lcd_print("/0");
lcd_print(LCD_STR_DEGREE);
lcd_print(LCD_STR_DEGREE[0]);
lcd_set_cursor(9, 4);
lcd_print(LCD_STR_BEDTEMP[0]);
lcd_print(ftostr3(degBed()));
lcd_print("/0");
lcd_print(LCD_STR_DEGREE);
lcd_set_custom_characters();
lcd_print(LCD_STR_DEGREE[0]);
delay_keep_alive(1000);
serialecho_temperatures();
}
fanSpeed = fanSpeedBckp;
lcd_set_custom_characters_arrows();
lcd_update_enable(true);
}
@ -3426,11 +3397,10 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
if (multi_screen) {
// Display the "next screen" indicator character.
// lcd_set_custom_characters_arrows();
lcd_set_custom_characters_nextpage();
lcd_set_cursor(19, 3);
// Display the down arrow.
lcd_print(char(1));
// Display the double down arrow.
lcd_print(LCD_STR_ARROW_2_DOWN[0]);
}
nlines = row;
@ -3471,7 +3441,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
if (!multi_screen) {
lcd_set_cursor(19, 3);
// Display the confirm char.
lcd_print(char(2));
lcd_print(LCD_STR_CONFIRM[0]);
}
// Wait for 5 seconds before displaying the next text.
for (uint8_t i = 0; i < 100; ++ i) {
@ -3497,7 +3467,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
lcd_set_cursor(19, 3);
// Display the confirm char.
lcd_print(char(2));
lcd_print(LCD_STR_CONFIRM[0]);
}
}
}
@ -3826,7 +3796,7 @@ static void lcd_show_sensors_state()
uint8_t idler_state = STATE_NA;
pinda_state = READ(Z_MIN_PIN);
if (mmu_enabled && ((_millis() - mmu_last_finda_response) < 1000ul) )
if (mmu_enabled && mmu_last_finda_response.expired(1000))
{
finda_state = mmu_finda;
}
@ -3907,7 +3877,7 @@ static void prusa_statistics_case0(uint8_t statnr){
prusa_stat_printinfo();
}
void prusa_statistics(int _message, uint8_t _fil_nr) {
void prusa_statistics(uint8_t _message, uint8_t _fil_nr) {
#ifdef DEBUG_DISABLE_PRUSA_STATISTICS
return;
#endif //DEBUG_DISABLE_PRUSA_STATISTICS
@ -3938,7 +3908,6 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
break;
case 1: // 1 heating
farm_status = 2;
SERIAL_ECHO('{');
prusa_stat_printerstatus(2);
prusa_stat_farm_number();
@ -3947,7 +3916,6 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
break;
case 2: // heating done
farm_status = 3;
SERIAL_ECHO('{');
prusa_stat_printerstatus(3);
prusa_stat_farm_number();
@ -3957,7 +3925,6 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
if (IS_SD_PRINTING || loading_flag)
{
farm_status = 4;
SERIAL_ECHO('{');
prusa_stat_printerstatus(4);
prusa_stat_farm_number();
@ -4053,7 +4020,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
}
static void prusa_stat_printerstatus(int _status)
static void prusa_stat_printerstatus(uint8_t _status)
{
SERIAL_ECHOPGM("[PRN:");
SERIAL_ECHO(_status);
@ -4222,12 +4189,6 @@ void lcd_move_menu_axis()
MENU_END();
}
static void lcd_move_menu_1mm()
{
move_menu_scale = 1.0;
lcd_move_menu_axis();
}
#ifdef SDCARD_SORT_ALPHA
static void lcd_sort_type_set() {
uint8_t sdSort;
@ -4386,10 +4347,6 @@ static void lcd_fsensor_state_set()
}
#endif //FILAMENT_SENSOR
void lcd_set_degree() {
lcd_set_custom_characters_degree();
}
#if (LANG_MODE != 0)
void menu_setlang(unsigned char lang)
@ -4469,7 +4426,6 @@ static void lcd_language_menu()
void lcd_mesh_bedleveling()
{
mesh_bed_run_from_menu = true;
enquecommand_P(PSTR("G80"));
lcd_return_to_status();
}
@ -4684,7 +4640,7 @@ void lcd_v2_calibration()
bool loaded = false;
if (fsensor_enabled && ir_sensor_detected)
{
loaded = (digitalRead(IR_SENSOR_PIN) == 0);
loaded = !READ(IR_SENSOR_PIN);
}
else
{
@ -4758,8 +4714,7 @@ static void wait_preheat()
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60);
delay_keep_alive(2000);
lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
lcd_set_custom_characters();
while (abs(degHotend(0) - degTargetHotend(0)) > 3) {
while (fabs(degHotend(0) - degTargetHotend(0)) > 3) {
lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
lcd_set_cursor(0, 4);
@ -5019,7 +4974,7 @@ void lcd_wizard(WizState state)
msg = _T(MSG_WIZARD_DONE);
lcd_reset_alert_level();
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
lcd_return_to_status();
break;
@ -5638,7 +5593,7 @@ static void lcd_settings_menu()
if (!PRINTER_ACTIVE || isPrintPaused)
{
MENU_ITEM_SUBMENU_P(_i("Move axis"), lcd_move_menu_1mm);////MSG_MOVE_AXIS c=18
MENU_ITEM_SUBMENU_P(_i("Move axis"), lcd_move_menu_axis);////MSG_MOVE_AXIS c=18
MENU_ITEM_GCODE_P(_i("Disable steppers"), PSTR("M84"));////MSG_DISABLE_STEPPERS c=18
}
@ -6286,90 +6241,11 @@ void unload_filament(bool automatic)
lcd_update_enable(true);
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
}
unsigned char lcd_choose_color() {
//function returns index of currently chosen item
//following part can be modified from 2 to 255 items:
//-----------------------------------------------------
unsigned char items_no = 2;
const char *item[items_no];
item[0] = "Orange";
item[1] = "Black";
//-----------------------------------------------------
uint_least8_t active_rows;
static int first = 0;
int enc_dif = 0;
unsigned char cursor_pos = 1;
enc_dif = lcd_encoder_diff;
lcd_clear();
lcd_putc_at(0, 1, '>');
active_rows = items_no < 3 ? items_no : 3;
lcd_consume_click();
while (1) {
lcd_puts_at_P(0, 0, PSTR("Choose color:"));
for (uint_least8_t i = 0; i < active_rows; i++) {
lcd_set_cursor(1, i+1);
lcd_print(item[first + i]);
}
manage_heater();
manage_inactivity(true);
proc_commands();
if (abs((enc_dif - lcd_encoder_diff)) > 12) {
if (enc_dif > lcd_encoder_diff) {
cursor_pos--;
}
if (enc_dif < lcd_encoder_diff) {
cursor_pos++;
}
if (cursor_pos > active_rows) {
cursor_pos = active_rows;
Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
if (first < items_no - active_rows) {
first++;
lcd_clear();
}
}
if (cursor_pos < 1) {
cursor_pos = 1;
Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
if (first > 0) {
first--;
lcd_clear();
}
}
lcd_putc_at(0, 1, ' ');
lcd_putc_at(0, 2, ' ');
lcd_putc_at(0, 3, ' ');
lcd_putc_at(0, cursor_pos, '>');
Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
enc_dif = lcd_encoder_diff;
_delay(100);
}
if (lcd_clicked()) {
Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
switch(cursor_pos + first - 1) {
case 0: return 1; break;
case 1: return 0; break;
default: return 99; break;
}
}
}
}
#include "xflash.h"
#ifdef LCD_TEST
@ -7051,24 +6927,11 @@ static void lcd_sd_updir()
void lcd_print_stop()
{
if (!card.sdprinting) {
SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint
SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); // for Octoprint
}
cmdqueue_serial_disabled = false; //for when canceling a print with a fancheck
CRITICAL_SECTION_START;
// Clear any saved printing state
cancel_saved_printing();
// Abort the planner/queue/sd
planner_abort_hard();
cmdqueue_reset();
card.sdprinting = false;
card.closefile();
st_reset_timer();
CRITICAL_SECTION_END;
UnconditionalStop();
// TODO: all the following should be moved in the main marlin loop!
#ifdef MESH_BED_LEVELING
mbl.active = false; //also prevents undoing the mbl compensation a second time in the second planner_abort_hard()
#endif
@ -7079,11 +6942,11 @@ void lcd_print_stop()
pause_time = 0;
save_statistics(total_filament_used, t);
// reset current command
lcd_commands_step = 0;
lcd_commands_type = LcdCommands::Idle;
lcd_cooldown(); //turns off heaters and fan; goes to status screen.
cancel_heatup = true; //unroll temperature wait loop stack.
current_position[Z_AXIS] += 10; //lift Z.
plan_buffer_line_curposXYZE(manual_feedrate[Z_AXIS] / 60);
@ -7100,7 +6963,7 @@ void lcd_print_stop()
finishAndDisableSteppers(); //M84
lcd_setstatuspgm(_T(WELCOME_MSG));
lcd_setstatuspgm(MSG_WELCOME);
custom_message_type = CustomMsg::Status;
planner_abort_hard(); //needs to be done since plan_buffer_line resets waiting_inside_plan_buffer_line_print_aborted to false. Also copies current to destination.
@ -7323,7 +7186,7 @@ void lcd_belttest()
Y = eeprom_read_word((uint16_t*)(EEPROM_BELTSTATUS_Y));
lcd_set_cursor(10,3),lcd_printf_P(PSTR("%u"),Y);
lcd_set_cursor(19, 3);
lcd_print(LCD_STR_UPLEVEL);
lcd_print(LCD_STR_UPLEVEL[0]);
lcd_wait_for_click_delay(10);
}
}
@ -7401,7 +7264,7 @@ static void lcd_selftest_v()
bool lcd_selftest()
{
int _progress = 0;
uint8_t _progress = 0;
bool _result = true;
bool _swapped_fan = false;
#ifdef IR_SENSOR_ANALOG
@ -7669,14 +7532,14 @@ bool lcd_selftest()
#ifdef TMC2130
static void reset_crash_det(unsigned char axis) {
static void reset_crash_det(uint8_t axis) {
current_position[axis] += 10;
plan_buffer_line_curposXYZE(manual_feedrate[0] / 60);
st_synchronize();
if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_DET)) tmc2130_sg_stop_on_crash = true;
}
static bool lcd_selfcheck_axis_sg(unsigned char axis) {
static bool lcd_selfcheck_axis_sg(uint8_t axis) {
// each axis length is measured twice
float axis_length, current_position_init, current_position_final;
float measured_axis_length[2];
@ -7723,7 +7586,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
eeprom_write_word(((uint16_t*)((axis == X_AXIS)?EEPROM_BELTSTATUS_X:EEPROM_BELTSTATUS_Y)), sg1);
current_position_final = st_get_position_mm(axis);
measured_axis_length[0] = abs(current_position_final - current_position_init);
measured_axis_length[0] = fabs(current_position_final - current_position_init);
// first measurement end and second measurement begin
@ -7740,7 +7603,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
current_position_init = st_get_position_mm(axis);
measured_axis_length[1] = abs(current_position_final - current_position_init);
measured_axis_length[1] = fabs(current_position_final - current_position_init);
tmc2130_home_exit();
@ -7748,7 +7611,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
for(uint_least8_t i = 0; i < 2; i++){ //check if measured axis length corresponds to expected length
printf_P(_N("Measured axis length:%.3f\n"), measured_axis_length[i]);
if (abs(measured_axis_length[i] - axis_length) > max_error_mm) {
if (fabs(measured_axis_length[i] - axis_length) > max_error_mm) {
enable_endstops(false);
const char *_error_1;
@ -7767,9 +7630,9 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
}
}
printf_P(_N("Axis length difference:%.3f\n"), abs(measured_axis_length[0] - measured_axis_length[1]));
printf_P(_N("Axis length difference:%.3f\n"), fabs(measured_axis_length[0] - measured_axis_length[1]));
if (abs(measured_axis_length[0] - measured_axis_length[1]) > 1) { //check if difference between first and second measurement is low
if (fabs(measured_axis_length[0] - measured_axis_length[1]) > 1) { //check if difference between first and second measurement is low
//loose pulleys
const char *_error_1;
@ -7799,7 +7662,7 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
// printf_P(PSTR("lcd_selfcheck_axis %d, %d\n"), _axis, _travel);
bool _stepdone = false;
bool _stepresult = false;
int _progress = 0;
uint8_t _progress = 0;
int _travel_done = 0;
int _err_endstop = 0;
int _lcd_refresh = 0;
@ -8010,14 +7873,14 @@ static bool lcd_selfcheck_endstops()
static bool lcd_selfcheck_check_heater(bool _isbed)
{
int _counter = 0;
int _progress = 0;
uint8_t _counter = 0;
uint8_t _progress = 0;
bool _stepresult = false;
bool _docycle = true;
int _checked_snapshot = (_isbed) ? degBed() : degHotend(0);
int _opposite_snapshot = (_isbed) ? degHotend(0) : degBed();
int _cycles = (_isbed) ? 180 : 60; //~ 90s / 30s
uint8_t _cycles = (_isbed) ? 180 : 60; //~ 90s / 30s
target_temperature[0] = (_isbed) ? 0 : 200;
target_temperature_bed = (_isbed) ? 100 : 0;
@ -8438,7 +8301,7 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
#endif //FANCHECK
static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay)
static uint8_t lcd_selftest_screen(TestScreen screen, uint8_t _progress, uint8_t _progress_scale, bool _clear, uint16_t _delay)
{
lcd_update_enable(false);
@ -8510,7 +8373,7 @@ static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_s
return (_progress >= _progress_scale * 2) ? 0 : _progress;
}
static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name_PROGMEM, const char *_indicator)
static void lcd_selftest_screen_step(uint8_t _row, uint8_t _col, uint8_t _state, const char *_name_PROGMEM, const char *_indicator)
{
lcd_set_cursor(_col, _row);
uint8_t strlenNameP = strlen_P(_name_PROGMEM);
@ -8565,7 +8428,7 @@ static bool check_file(const char* filename) {
cmdqueue_serial_disabled = false;
card.printingHasFinished();
strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH);
lcd_setstatuspgm(MSG_WELCOME);
lcd_finishstatus();
return result;
}
@ -8638,10 +8501,8 @@ void ultralcd_init()
lcd_init();
lcd_refresh();
lcd_longpress_func = menu_lcd_longpress_func;
lcd_charsetup_func = menu_lcd_charsetup_func;
lcd_lcdupdate_func = menu_lcd_lcdupdate_func;
menu_menu = lcd_status_screen;
menu_lcd_charsetup_func();
SET_INPUT(BTN_EN1);
SET_INPUT(BTN_EN2);
@ -8653,7 +8514,7 @@ void ultralcd_init()
#endif
#if defined (SDSUPPORT) && defined(SDCARDDETECT) && (SDCARDDETECT > 0)
pinMode(SDCARDDETECT, INPUT);
SET_INPUT(SDCARDDETECT);
WRITE(SDCARDDETECT, HIGH);
lcd_oldcardstatus = IS_SD_INSERTED;
#endif//(SDCARDDETECT > 0)
@ -8669,10 +8530,10 @@ void lcd_printer_connected() {
}
static void lcd_send_status() {
if (farm_mode && no_response && ((_millis() - NcTime) > (NC_TIME * 1000))) {
if (farm_mode && no_response && (NcTime.expired(NC_TIME * 1000))) {
//send important status messages periodicaly
prusa_statistics(important_status, saved_filament_type);
NcTime = _millis();
NcTime.start();
#ifdef FARM_CONNECT_MESSAGE
lcd_connect_printer();
#endif //FARM_CONNECT_MESSAGE
@ -8702,7 +8563,7 @@ static void lcd_connect_printer() {
i = 0;
lcd_puts_at_P(0, 3, PSTR(" "));
}
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\xFF");
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, LCD_STR_SOLID_BLOCK[0]);
if (i == NC_BUTTON_LONG_PRESS * 10) {
no_response = false;
}
@ -8774,18 +8635,22 @@ void lcd_updatestatus(const char *message){
lcd_draw_update = 1;
}
void lcd_setalertstatuspgm(const char* message)
void lcd_setalertstatuspgm(const char* message, uint8_t severity)
{
lcd_setstatuspgm(message);
lcd_status_message_level = 1;
lcd_return_to_status();
if (severity > lcd_status_message_level) {
lcd_updatestatuspgm(message);
lcd_status_message_level = severity;
lcd_return_to_status();
}
}
void lcd_setalertstatus(const char* message)
void lcd_setalertstatus(const char* message, uint8_t severity)
{
lcd_setstatus(message);
lcd_status_message_level = 1;
lcd_return_to_status();
if (severity > lcd_status_message_level) {
lcd_updatestatus(message);
lcd_status_message_level = severity;
lcd_return_to_status();
}
}
void lcd_reset_alert_level()
@ -8844,7 +8709,6 @@ void menu_lcd_longpress_func(void)
#endif
|| menu_menu == lcd_support_menu
){
move_menu_scale = 1.0;
menu_submenu(lcd_move_z);
} else {
// otherwise consume the long press as normal click
@ -8854,14 +8718,6 @@ void menu_lcd_longpress_func(void)
}
}
void menu_lcd_charsetup_func(void)
{
if (menu_menu == lcd_status_screen)
lcd_set_custom_characters_degree();
else
lcd_set_custom_characters_arrows();
}
static inline bool z_menu_expired()
{
return (menu_menu == lcd_babystep_z
@ -8886,6 +8742,22 @@ void menu_lcd_lcdupdate_func(void)
#if (SDCARDDETECT > 0)
if ((IS_SD_INSERTED != lcd_oldcardstatus))
{
if(menu_menu == lcd_sdcard_menu) {
// If the user is either inside the submenus
// 1. 'Print from SD' --> and SD card is removed
// 2. 'No SD card' --> and SD card is inserted
//
// 1. 'Print from SD': We want to back out of this submenu
// and instead show the submenu title 'No SD card'.
//
// 2. 'No SD card': When the user inserts the SD card we want
// to back out of this submenu. Not only to show
// 'Print from SD' submenu title but also because the user
// will be prompted with another menu with the sorted list of files.
// Without backing out of the menu, the list will appear empty and
// The user will need to back out of two nested submenus.
menu_back();
}
lcd_draw_update = 2;
lcd_oldcardstatus = IS_SD_INSERTED;
lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
@ -8897,14 +8769,13 @@ void menu_lcd_lcdupdate_func(void)
card.initsd(false); //delay the sorting to the sd menu. Otherwise, removing the SD card while sorting will not menu_back()
card.presort_flag = true; //force sorting of the SD menu
}
LCD_MESSAGERPGM(_T(WELCOME_MSG));
LCD_MESSAGERPGM(MSG_WELCOME);
bMain=false; // flag (i.e. 'fake parameter') for 'lcd_sdcard_menu()' function
menu_submenu(lcd_sdcard_menu);
lcd_timeoutToStatus.start();
}
else
{
if(menu_menu==lcd_sdcard_menu)
menu_back();
card.release();
LCD_MESSAGERPGM(_i("Card removed"));////MSG_SD_REMOVED c=20
}

View File

@ -5,20 +5,26 @@
#include "config.h"
extern void menu_lcd_longpress_func(void);
extern void menu_lcd_charsetup_func(void);
extern void menu_lcd_lcdupdate_func(void);
// Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
void ultralcd_init();
void lcd_setstatus(const char* message);
void lcd_setstatuspgm(const char* message);
//! LCD status severities
#define LCD_STATUS_CRITICAL 2 //< Heater failure
#define LCD_STATUS_ALERT 1 //< Other hardware issue
#define LCD_STATUS_NONE 0 //< No alert message set
//! return to the main status screen and display the alert message
//! Beware - it has sideeffects:
//! - always returns the display to the main status screen
//! - always makes lcd_reset (which is slow and causes flicker)
//! - does not update the message if there is already one (i.e. lcd_status_message_level > 0)
void lcd_setalertstatus(const char* message);
void lcd_setalertstatuspgm(const char* message);
//! - does not update the message if there is one with the same (or higher) severity present
void lcd_setalertstatus(const char* message, uint8_t severity = LCD_STATUS_ALERT);
void lcd_setalertstatuspgm(const char* message, uint8_t severity = LCD_STATUS_ALERT);
//! only update the alert message on the main status screen
//! has no sideeffects, may be called multiple times
void lcd_updatestatus(const char *message);
@ -39,8 +45,7 @@ void lcd_pause_print();
void lcd_pause_usb_print();
void lcd_resume_print();
void lcd_print_stop();
void prusa_statistics(int _message, uint8_t _col_nr = 0);
unsigned char lcd_choose_color();
void prusa_statistics(uint8_t _message, uint8_t _col_nr = 0);
void lcd_load_filament_color_check();
//void lcd_mylang();
@ -119,11 +124,9 @@ enum class CustomMsg : uint_least8_t
};
extern CustomMsg custom_message_type;
extern unsigned int custom_message_state;
extern uint8_t custom_message_state;
extern uint8_t farm_mode;
extern int farm_timer;
extern uint8_t farm_status;
extern bool UserECoolEnabled();
extern bool FarmOrUserECool();
@ -160,15 +163,6 @@ void lcd_commands();
extern bool bSettings; // flag (i.e. 'fake parameter') for 'lcd_hw_setup_menu()' function
void lcd_hw_setup_menu(void); // NOT static due to using inside "util" module ("nozzle_diameter_check()")
void change_extr(int extr);
#ifdef SNMM
void extr_unload_all();
void extr_unload_used();
#endif //SNMM
void extr_unload();
enum class FilamentAction : uint_least8_t
{
None, //!< 'none' state is used as flag for (filament) autoLoad (i.e. opposite for 'autoLoad' state)
@ -216,10 +210,6 @@ void lcd_pinda_calibration_menu();
void lcd_calibrate_pinda();
void lcd_temp_calibration_set();
void display_loading();
void lcd_set_degree();
#if (LANG_MODE != 0)
void lcd_language();
#endif

View File

@ -224,6 +224,7 @@
#define TMC2130_INTPOL_XY 1 // extrapolate 256 for XY axes
#define TMC2130_INTPOL_Z 1 // extrapolate 256 for Z axis
#define TMC2130_INTPOL_E 1 // extrapolate 256 for E axis
// #define ALLOW_ALL_MRES
#define TMC2130_PWM_GRAD_X 2 // PWMCONF
#define TMC2130_PWM_AMPL_X 230 // PWMCONF

View File

@ -226,6 +226,7 @@
#define TMC2130_INTPOL_XY 1 // extrapolate 256 for XY axes
#define TMC2130_INTPOL_Z 1 // extrapolate 256 for Z axis
#define TMC2130_INTPOL_E 1 // extrapolate 256 for E axis
// #define ALLOW_ALL_MRES
#define TMC2130_PWM_GRAD_X 2 // PWMCONF
#define TMC2130_PWM_AMPL_X 230 // PWMCONF

View File

@ -59,7 +59,7 @@ static void __attribute__((noinline)) xfdump_dump_core(dump_header_t& hdr, uint3
// sample SP/PC
hdr.sp = SP;
GETPC(&hdr.pc);
hdr.pc = GETPC();
// write header
static_assert(sizeof(hdr) <= 256, "header is larger than a single page write");

546
MK404-build.sh Executable file
View File

@ -0,0 +1,546 @@
#!/bin/bash
# This bash script is used to compile automatically and run the MK404 simulator
#
# Supported OS: Linux64 bit
#
# Linux:
# Linux Ubuntu
# 1. Follow these instructions
# 2. Open Ubuntu bash and get latest updates with 'sudo apt-get update'
# 3. Install latest updates with 'sudo apt-get upgrade'
#
#
# Version: 1.0.0-Build_13
# Change log:
# 11 Feb 2021, 3d-gussner, Inital
# 11 Feb 2021, 3d-gussner, Optional flags to check for updates
# 12 Feb 2021, 3d-gussner, Update cmake
# 13 Feb 2021, 3d-gussner, Auto build SD cards
# 18 Jun 2021, 3d-gussner, Documentation and version number
# 18 Jun 2021, 3d-gussner, Added some arguments and checks
# 18 Jun 2021, 3d-gussner, Default extrusion graphics to line. Thanks @vintagepc point it out
# 18 Jun 2021, 3d-gussner, Added -g 3 and 4 for more details extrusion lines
# 18 Jun 2021, 3d-gussner, Check for updates is default. Fix update if internet connection is lost.
# 21 Jun 2021, 3d-gussner, Change board_flash argument to 'y' and firmware_version to 'f'
#### Start: Failures
failures()
{
case "$1" in
0) echo "$(tput setaf 2)MK404-build.sh finished with success$(tput sgr0)" ;;
2) echo "$(tput setaf 1)Unsupported OS: Linux $(uname -m)" ; echo "Please refer to the notes of MK404-build.sh$(tput sgr0)" ; exit 2 ;;
3) echo "$(tput setaf 1)This script doesn't support your Operating system!"; echo "Please use Linux 64-bit"; echo "Read the notes of MK404-build.sh$(tput sgr0)" ; exit 2 ;;
4) echo "$(tput setaf 1)Some packages are missing please install these!$(tput sgr0)" ; exit 4 ;;
5) echo "$(tput setaf 1)Wrong printer chosen.$(tput sgr0) Following Printers are supported: MK25, MK25S, MK3 and MK3S" ; exit 5 ;;
6) echo "$(tput setaf 1)Unsupported board flash size chosen.$(tput sgr0) Only '256', '384', '512', '1024' and '32M' are allowed." ; exit 6 ;;
7) echo "$(tput setaf 1)Unsupported board mem size chosen.$(tput sgr0) Only '8', '16', '32' and '64' are allowed." ; exit 7 ;;
8) echo "$(tput setaf 1)No firmware version file selected!$(tput sgr0)" ; echo "Add argument -f with path and hex filename to start MK404" ; exit 8 ;;
9) echo "$(tput setaf 1)Tried to determine MK404 printer from hex file, but failed!$(tput sgr0)" ; "Add argument -p with 'MK25', 'MK25S', 'MK3' or 'MK3S' to start MK404" ; exit 9 ;;
10) echo "$(tput setaf 1)Missing printer$(tput sgr0)" ; exit 10 ;;
esac
}
#### End: Failures
#### Start: Check options
##check_options()
##{
while getopts c:f:g:m:n:p:u:x:y:?h flag
do
case "${flag}" in
c) check_flag=${OPTARG};;
f) firmware_version_flag=${OPTARG};;
g) mk404_graphics_flag=${OPTARG};;
h) help_flag=1;;
m) mk404_flag=${OPTARG};;
n) new_build_flag=${OPTARG};;
p) mk404_printer_flag=${OPTARG};;
u) update_flag=${OPTARG};;
x) board_mem_flag=${OPTARG};;
y) board_flash_flag=${OPTARG};;
?) help_flag=1;;
esac
done
#Debug echos
#echo "c: $check_flag"
#echo "f: $firmware_version_flag"
#echo "g: $mk404_graphics_flag"
#echo "m: $mk404_flag"
#echo "n: $new_build_flag"
#echo "p: $mk404_printer_flag"
#echo "u: $update_flag"
#echo "x: $board_mem_flag"
#echo "y: $board_flash_flag"
# '?' 'h' argument usage and help
if [ "$help_flag" == "1" ] ; then
echo "***************************************"
echo "* MK404-build.sh Version: 1.0.0-Build_13 *"
echo "***************************************"
echo "Arguments:"
echo "$(tput setaf 2)-c$(tput sgr0) Check for update"
echo "$(tput setaf 2)-f$(tput sgr0) Prusa-Firmware version"
echo "$(tput setaf 2)-g$(tput sgr0) Start MK404 graphics"
echo "$(tput setaf 2)-h$(tput sgr0) Help"
echo "$(tput setaf 2)-m$(tput sgr0) Start MK404 sim"
echo "$(tput setaf 2)-n$(tput sgr0) Force new build"
echo "$(tput setaf 2)-p$(tput sgr0) MK404 Printer"
echo "$(tput setaf 2)-u$(tput sgr0) Update MK404"
echo "$(tput setaf 2)-x$(tput sgr0) Board memory size"
echo "$(tput setaf 2)-y$(tput sgr0) Board flash size"
echo "$(tput setaf 2)-?$(tput sgr0) Help"
echo
echo "Brief USAGE:"
echo " $(tput setaf 2)./MK404-build.sh$(tput sgr0) [-c] [-f] [-g] [-m] [-n] [-p] [-u] [-v] [-x] [-h] [-?]"
echo
echo " -c : '$(tput setaf 2)0$(tput sgr0)' no, '$(tput setaf 2)1$(tput sgr0)' yes"
echo " -f : '$(tput setaf 2)path+file name$(tput sgr0)'"
echo " -g : '$(tput setaf 2)0$(tput sgr0)' no, '$(tput setaf 2)1$(tput sgr0)' lite, '$(tput setaf 2)2$(tput sgr0)' fancy, '$(tput setaf 2)3$(tput sgr0)' lite with Quad_HR, '$(tput setaf 2)4$(tput sgr0)' fancy with Quad_HR"
echo " -m : '$(tput setaf 2)0$(tput sgr0)' no, '$(tput setaf 2)1$(tput sgr0)' yes '$(tput setaf 2)2$(tput sgr0)' with MMU2"
echo " -n : '$(tput setaf 2)0$(tput sgr0)' no, '$(tput setaf 2)1$(tput sgr0)' yes"
echo " -p : '$(tput setaf 2)MK25$(tput sgr0)', '$(tput setaf 2)MK25S$(tput sgr0)', '$(tput setaf 2)MK3$(tput sgr0)' or '$(tput setaf 2)MK3S$(tput sgr0)'"
echo " -u : '$(tput setaf 2)0$(tput sgr0)' no, '$(tput setaf 2)1$(tput sgr0)' yes '"
echo " -x : '$(tput setaf 2)8$(tput sgr0)',$(tput setaf 2)16$(tput sgr0)',$(tput setaf 2)32$(tput sgr0)' or '$(tput setaf 2)64$(tput sgr0)' Kb."
echo " -y : '$(tput setaf 2)256$(tput sgr0)','$(tput setaf 2)384$(tput sgr0)','$(tput setaf 2)512$(tput sgr0)','$(tput setaf 2)1024$(tput sgr0)''$(tput setaf 2)32M$(tput sgr0)'"
echo
echo "Example:"
echo " $(tput setaf 2)./MK404-build.sh -f 1$(tput sgr0)"
echo " Will force an update and rebuild the MK404 SIM"
echo
echo " $(tput setaf 2)./MK404-build.sh -m 1 -g 1 -f ../../../../Prusa-Firmware/PF-build-hex/FW3100-Build4481/BOARD_EINSY_1_0a/FW3100-Build4481-1_75mm_MK3S-EINSy10a-E3Dv6full.hex$(tput sgr0)"
echo " Will start MK404 with Prusa_MK3S and Prusa-Firmware 3.10.0-Build4481"
exit 1
fi
#Check MK404 agruments
#Set Check for updates as default
check_flag=1
#Start: Check mk404_printer_flag
if [ ! -z $mk404_printer_flag ]; then
if [[ "$mk404_printer_flag" == "MK3" || "$mk404_printer_flag" == "MK3S" || "$mk404_printer_flag" == "MK25" || "$mk404_printer_flag" == "MK25S" ]]; then
MK404_PRINTER_TEMP=$mk404_printer_flag
else
failures 5
fi
fi
#End: Check mk404_printer_flag
#Start: Check if Build is selected with argument '-f'
if [ ! -z "$board_flash_flag" ] ; then
if [ "$board_flash_flag" == "256" ] ; then
BOARD_FLASH="0x3FFFF"
echo "Board flash size : $board_flash_flag Kb, $BOARD_FLASH (hex)"
elif [ "$board_flash_flag" == "384" ] ; then
BOARD_FLASH="0x5FFFF"
echo "Board flash size : $board_flash_flag Kb, $BOARD_FLASH (hex)"
elif [ "$board_flash_flag" == "512" ] ; then
BOARD_FLASH="0x7FFFF"
echo "Board flash size : $board_flash_flag Kb, $BOARD_FLASH (hex)"
elif [ "$board_flash_flag" == "1024" ] ; then
BOARD_FLASH="0xFFFFF"
echo "Board flash size : $board_flash_flag Kb, $BOARD_FLASH (hex)"
elif [[ "$board_flash_flag" == "32M" || "$board_flash_flag" == "32768" ]] ; then
BOARD_FLASH="0x1FFFFFF"
echo "Board flash size : 32 Mb, $BOARD_FLASH (hex)"
else
failures 6
fi
fi
#End: Check if Build is selected with argument '-f'
#Start: Check if Build is selected with argument '-x'
if [ ! -z "$board_mem_flag" ] ; then
if [ "$board_mem_flag" == "8" ] ; then
BOARD_MEM="0x21FF"
echo "Board mem size : $board_mem_flag Kb, $BOARD_MEM (hex)"
elif [ "$board_mem_flag" == "16" ] ; then
BOARD_MEM="0x3DFF"
echo "Board mem size : $board_mem_flag Kb, $BOARD_MEM (hex)"
elif [ "$board_mem_flag" == "32" ] ; then
BOARD_MEM="0x7DFF"
echo "Board mem size : $board_mem_flag Kb, $BOARD_MEM (hex)"
elif [ "$board_mem_flag" == "64" ] ; then
BOARD_MEM="0xFFFF"
echo "Board mem size : $board_mem_flag Kb, $BOARD_MEM (hex)"
else
failures 7
fi
fi
#End: Check if Build is selected with argument '-x'
#Start: Check if new build is selected
if [ "$new_build_flag" == "1" ]; then
check_flag=1
update_flag=1
fi
if [ "$update_flag" == "1" ]; then
check_flag=1
fi
#End: Check if new build is selected
# Prepare run MK404
#Check MK404_Printer
if [ ! -z $firmware_version_flag ]; then
MK404_PRINTER_TEMP=$(echo $firmware_version_flag | sed 's/\(.*\)\///' | grep 'MK3')
if [ ! -z $MK404_PRINTER_TEMP ]; then
MK404_PRINTER=MK3
fi
MK404_PRINTER_TEMP=$(echo $firmware_version_flag | sed 's/\(.*\)\///' | grep 'MK3S')
if [ ! -z $MK404_PRINTER_TEMP ]; then
MK404_PRINTER=MK3S
fi
MK404_PRINTER_TEMP=$(echo $firmware_version_flag | sed 's/\(.*\)\///' | grep 'MK25')
if [ ! -z $MK404_PRINTER_TEMP ]; then
MK404_PRINTER=MK25
fi
MK404_PRINTER_TEMP=$(echo $firmware_version_flag | sed 's/\(.*\)\///' | grep 'MK25S')
if [ ! -z $MK404_PRINTER_TEMP ]; then
MK404_PRINTER=MK25S
fi
else
failures 8
fi
if [ -z "$MK404_PRINTER" ]; then
failures 9
fi
if [ ! -z $mk404_printer_flag ]; then
if [ "$mk404_printer_flag" != "$MK404_PRINTER" ]; then
echo "$(tput setaf 3)You defined a different printer type than the firmware!"
echo "This can cause unexpected issues.$(tput sgr 0)"
echo
PS3="Select $(tput setaf 2)printer$(tput sgr 0) you want to use."
select which in "$(tput setaf 2)$MK404_PRINTER$(tput sgr 0)" "$mk404_printer_flag"; do
case $which in
$MK404_PRINTER)
echo "Set $MK404_PRINTER as printer"
break
;;
$mk404_printer_flag)
echo "Set $(tput setaf 3)$mk404_printer_flag$(tput sgr 0) as printer"
echo "$(tput setaf 3)This firmware file isn't correct for this printer!!!$(tput sgr 0)"
echo
MK404_PRINTER=$mk404_printer_flag
read -p "Press Enter to continue."
break
;;
*)
break
;;
esac
done
fi
fi
if [ -z $MK404_PRINTER ]; then
failures 10
fi
if [[ "$MK404_PRINTER" == "MK25" || "$MK404_PRINTER" == "MK25S" ]]; then
MK404_PRINTER="${MK404_PRINTER}_mR13"
else
if [ "$mk404_flag" == "2" ]; then # Check if MMU2 is selected only for MK3/S
MK404_PRINTER="${MK404_PRINTER}MMU2"
fi
fi
# Run MK404 with 'debugcore' and/or 'bootloader-file'
if [[ ! -z $MK404_DEBUG && "$MK404_DEBUG" == "atmega404" || ! -z $BOARD_MEM && "$BOARD_MEM" == "0xFFFF" ]]; then
MK404_options="--debugcore"
fi
if [[ ! -z $MK404_DEBUG && "$MK404_DEBUG" == "atmega404_no_bootloader" || ! -z $BOARD_FLASH && "$BOARD_FLASH" != "0x3FFFF" ]]; then
MK404_options='--debugcore --bootloader-file ""'
fi
# Run MK404 with graphics
if [ ! -z "$mk404_graphics_flag" ]; then
if [ ! -z "$MK404_options" ]; then
MK404_options="${MK404_options} -g "
else
MK404_options=" -g "
fi
if [[ "$mk404_graphics_flag" == "1" || "$mk404_graphics_flag" == "lite" || "$mk404_graphics_flag" == "3" ]]; then
MK404_options="${MK404_options}lite"
elif [[ "$mk404_graphics_flag" == "2" || "$mk404_graphics_flag" == "fancy" || "$mk404_graphics_flag" == "4" ]]; then
MK404_options="${MK404_options}fancy"
else
echo "$(tput setaf 1)Unsupported MK404 graphics option $mk404_graphics_flag$(tput sgr 0)"
fi
if [[ "$mk404_graphics_flag" == "3" || "$mk404_graphics_flag" == "4" ]]; then
MK404_options="${MK404_options} --colour-extrusion --extrusion Quad_HR"
else
MK404_options="${MK404_options} --extrusion Line"
fi
fi
if [ ! -z $firmware_version_flag ]; then
MK404_firmware_file=" -f $firmware_version_flag"
fi
#End: Check MK404 agruments
##}
#### End: Check for options/flags
#### Start: Check if OSTYPE is supported
check_OS()
{
OS_FOUND=$( command -v uname)
case $( "${OS_FOUND}" | tr '[:upper:]' '[:lower:]') in
linux*)
TARGET_OS="linux"
;;
*)
TARGET_OS='unknown'
;;
esac
# Linux
if [ $TARGET_OS == "linux" ]; then
if [ $(uname -m) == "x86_64" ]; then
echo "$(tput setaf 2)Linux 64-bit found$(tput sgr0)"
Processor="64"
#elif [[ $(uname -m) == "i386" || $(uname -m) == "i686" ]]; then
# echo "$(tput setaf 2)Linux 32-bit found$(tput sgr0)"
# Processor="32"
else
failures 2
fi
else
failures 3
fi
sleep 2
}
#### End: Check if OSTYPE is supported
#### Start: Check MK404 dependencies
check_packages()
{
packages=(
"libelf-dev"
"gcc-7"
"gcc-avr"
"libglew-dev"
"freeglut3-dev"
"libsdl-sound1.2-dev"
"libpng-dev"
"cmake"
"zip"
"wget"
"git"
"build-essential"
"lcov"
"mtools"
)
for check_package in ${packages[@]}; do
if dpkg-query -W -f'${db:Status-Abbrev}\n' $check_package 2>/dev/null \
| grep -q '^.i $'; then
echo "$(tput setaf 2)$check_package: Installed$(tput sgr0)"
else
echo "$(tput setaf 1)$check_package: Not installed use $(tput setaf 3)'sudo apt install $check_package'$(tput setaf 1) to install missing package$(tput sgr0)"
not_installed=1;
fi
done
if [ "$not_installed" = "1" ]; then
failures 4
fi
}
#### End: Check MK404 dependencies
#### Start: Set build environment
set_build_env_variables()
{
MK404_SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
MK404_URL="https://github.com/vintagepc/MK404.git"
MK404_owner="vintagepc"
MK404_project="MK404"
MK404_PATH="$MK404_SCRIPT_PATH/../MK404/master"
MK404_BUILD_PATH="$MK404_PATH/build"
}
#### End: Set build environment
#### Start: List few useful data
output_useful_data()
{
echo
echo "Script path :" $MK404_SCRIPT_PATH
echo "OS :" $TARGET_OS
echo ""
echo "MK404 path :" $MK404_PATH
}
#### End: List few useful data
#### Start: Clone MK404 if needed
get_MK404()
{
if [ ! -d $MK404_PATH ]; then
#release_url=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/$MK404_owner/$MK404_project/releases/latest)
#release_tag=$(basename $release_url)
#git clone -b $release_tag -- https://github.com/$MK404_owner/$MK404_project.git $MK404_PATH
git clone $MK404_URL $MK404_PATH
fi
}
#### End: Clone MK404 if needed
#### Start: Check for updates
check_for_updates()
{
if [ "$check_flag" == "1" ]; then
if [ -d $MK404_BUILD_PATH ]; then
cd $MK404_BUILD_PATH
MK404_current_version=$( command ./MK404 --version | grep "MK404" | cut -f 4 -d " ")
cd $MK404_PATH
else
echo "Cannot check current version as it has not been build."
fi
# Get local Commit_Hash
MK404_local_GIT_COMMIT_HASH=$(git log --pretty=format:"%H" -1)
# Get local Commit_Number
MK404_local_GIT_COMMIT_NUMBER=$(git rev-list HEAD --count)
# Get latest release
MK404_release_url=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/$MK404_owner/$MK404_project/releases/latest)
MK404_release_tag=$(basename $MK404_release_url)
# Get remote Commit_Hash
#MK404_remote_GIT_COMMIT_HASH=$(git ls-remote --heads $(git config --get remote.origin.url) | grep "refs/heads/master" | cut -f 1)
MK404_remote_GIT_COMMIT_HASH=$(git ls-remote | grep "refs/tags/$MK404_release_tag" | cut -f 1)
# Get remote Commit_Number
MK404_remote_GIT_COMMIT_NUMBER=$(git rev-list $MK404_release_tag --count)
# Output
echo ""
echo "Current version : $MK404_current_version"
echo ""
echo "Current local hash : $MK404_local_GIT_COMMIT_HASH"
echo "Current local commit nr : $MK404_local_GIT_COMMIT_NUMBER"
if [ "$MK404_local_GIT_COMMIT_HASH" != "$MK404_remote_GIT_COMMIT_HASH" ]; then
echo "$(tput setaf 1)"
else
echo "$(tput setaf 2)"
fi
echo "Latest release tag : $MK404_release_tag"
echo "Latest release hash : $MK404_remote_GIT_COMMIT_HASH"
echo "Latest remote commit nr : $MK404_remote_GIT_COMMIT_NUMBER"
echo "$(tput sgr 0)"
# Check for updates
if [ ! -z $MK404_remote_GIT_COMMIT_HASH ]; then
if [[ "$MK404_local_GIT_COMMIT_HASH" != "$MK404_remote_GIT_COMMIT_HASH" && -z "$update_flag" ]]; then
echo "$(tput setaf 2)Update is availible.$(tput sgr 0)"
read -t 10 -n 1 -p "$(tput setaf 3)Update now Y/n$(tput sgr 0)" update_answer
if [ "$update_answer" == "Y" ]; then
update_flag=1
fi
echo ""
fi
fi
fi
}
#### End: Check for updates
#### Start: Fetch updates and force new build
fetch_updates()
{
if [ "$update_flag" == "1" ]; then
if [ ! -z $MK404_remote_GIT_COMMIT_HASH ]; then
if [ "$MK404_local_GIT_COMMIT_HASH" != "$MK404_remote_GIT_COMMIT_HASH" ]; then
echo ""
git fetch --all
read -t 10 -p "$(tput setaf 2)Updating MK404 !$(tput sgr 0)"
echo ""
git reset --hard $MK404_release_tag
read -t 10 -p "$(tput setaf 2)Compiling MK404 !$(tput sgr 0)"
echo ""
new_build_flag=1
fi
fi
fi
}
#### End: Fetch updates and force new build
#### Start: Prepare MK404 build
prepare_MK404()
{
if [ ! -d $MK404_BUILD_PATH ]; then
mkdir -p $MK404_BUILD_PATH
fi
}
#### End: Prepare MK404 build
#### Start: Build MK404
build_MK404()
{
if [[ ! -f "$MK404_BUILD_PATH/Makefile" || "$new_build_flag" == "1" ]]; then
# Init and update submodules
if [ -d $MK404_BUILD_PATH ]; then
rm -rf $MK404_BUILD_PATH
mkdir -p $MK404_BUILD_PATH
fi
git submodule init
git submodule update
cmake -B$MK404_BUILD_PATH -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_BUILD_TYPE=Release -G "Unix Makefiles"
fi
# Make MK404
cd $MK404_BUILD_PATH
if [[ ! -f "$MK404_BUILD_PATH/MK404" || "$new_build_flag" == "1" ]]; then
make
fi
# Make SDcards
if [[ ! -f "$MK404_BUILD_PATH/Prusa_MK3S_SDcard.bin" || "$new_build_flag" == "1" ]]; then
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK3S_SDcard.bin
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK3_SDcard.bin
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK25_13_SDcard.bin
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK25S_13_SDcard.bin
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK3SMMU2_SDcard.bin
cmake --build $MK404_BUILD_PATH --config Release --target Prusa_MK3MMU2_SDcard.bin
fi
}
#### End: Build MK404
#### Start: Run MK404 SIM
run_MK404_SIM()
{
if [ ! -z $mk404_flag ]; then
# Output some useful data
echo "Printer : $MK404_PRINTER"
echo "Options : $MK404_options"
echo ""
read -t 5 -p "Press $(tput setaf 2)Enter$(tput sgr 0) to start MK404"
echo ""
# Change to MK404 build folder
cd $MK404_BUILD_PATH
# Start MK404
# default with serial output and terminal to manipulate it via terminal
echo ""
echo "./MK404 Prusa_$MK404_PRINTER -s --terminal $MK404_options $MK404_firmware_file"
sleep 5
./MK404 Prusa_$MK404_PRINTER -s --terminal $MK404_options $MK404_firmware_file || exit 10
fi
}
#### End: Run MK404 SIM
#### Check OS and needed packages
echo "Check OS"
check_OS
check_packages
#### Check for options/flags
echo "Check for options"
#### Prepare build environment
echo "Prepare build env"
set_build_env_variables
output_useful_data
get_MK404
#
cd $MK404_PATH
check_for_updates
fetch_updates
prepare_MK404
build_MK404
run_MK404_SIM
#### End of MK404 Simulator

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@ _Note: Multi language build is not supported._
**a.** Install `"Arduino Software IDE"` from the official website `https://www.arduino.cc -> Software->Downloads`
_It is recommended to use version `"1.8.5"`, as it is used on out build server to produce official builds._
_It is recommended to use version `"1.8.5"`, as it is used on our build server to produce official builds._
**b.** Setup Arduino to use Prusa Rambo board definition
@ -118,7 +118,7 @@ _notes: Script and instructions contributed by 3d-gussner. Use at your own risk.
- to install zip run `sudo apt-get install zip`
- to install dos2unix run `sudo apt-get install dos2unix`
- run `dos2unix PF-build.sh` to convert the windows line endings to unix line endings
- add few lines at the top of `~/.bashrc` by running `sudo nano ~/.bashrc`
- add a few lines at the top of `~/.bashrc` by running `sudo nano ~/.bashrc`
export OS="Linux"
export JAVA_TOOL_OPTIONS="-Djava.net.preferIPv4Stack=true"
@ -134,14 +134,14 @@ _notes: Script and instructions contributed by 3d-gussner. Use at your own risk.
- Example: You files are under `C:\Users\<your-username>\Downloads\Prusa-Firmware-MK3`
- use under Ubuntu the following command `cd /mnt/c/Users/<your-username>/Downloads/Prusa-Firmware-MK3`
to change to the right folder
- Unix and windows have different line endings (LF vs CRLF), try dos2unix to convert
- Unix and Windows have different line endings (LF vs CRLF), use dos2unix to convert
- This should fix the `"$'\r': command not found"` error
- to install run `apt-get install dos2unix`
- If your Windows isn't in English the Paths may look different
Example in other languages
- English `/mnt/c/Users/<your-username>/Downloads/Prusa-Firmware-MK3` will be on a German Windows`/mnt/c/Anwender/<your-username>/Downloads/Prusa-Firmware-MK3`
#### Compile Prusa-firmware with Ubuntu/Debian Linux subsystem installed
- open Ubuntu bash
- open Ubuntu bash shell
- change to your source code folder (case sensitive)
- run `./PF-build.sh`
- follow the instructions
@ -211,14 +211,14 @@ Q:I built firmware using Arduino and I see "?" instead of numbers in printer use
A:Step 1.c was omitted or you updated Arduino and now platform.txt located somewhere in your user profile is used.
Q:I built firmware using Arduino and printer now speaks Klingon (nonsense characters and symbols are displayed @^#$&*°;~ÿ)
Q:I built firmware using Arduino and my printer now speaks "Klingon" (nonsense characters and symbols are displayed @^#$&*°;~ÿ)
A:Step 2.c was omitted.
Q:What environment does Prusa use to build the firmware in the first place?
Q:What environment does Prusa use to build its official firmware releases?
A:Our production builds are 99.9% equivalent to https://github.com/prusa3d/Prusa-Firmware#linux this is also easiest way to build as only one step is needed - run single script, which downloads patched Arduino from github, builds using it, then extracts translated strings and creates language variants (for MK2x) or language hex file for external SPI flash (MK3x). But you need Linux or Linux in virtual machine. This is also what happens when you open pull request to our repository - all variants are built by Travis http://travis-ci.org/ (to check for compilation errors). You can see, what is happening in .travis.yml. It would be also possible to get hex built by travis, only deploy step is missing in .travis.yml. You can get inspiration how to deploy hex by travis and how to setup travis in https://github.com/prusa3d/MM-control-01/ repository. Final hex is located in ./lang/firmware.hex Community reproduced this for Windows in https://github.com/prusa3d/Prusa-Firmware#using-linux-subsystem-under-windows-10-64-bit or https://github.com/prusa3d/Prusa-Firmware#using-git-bash-under-windows-10-64-bit .
A:Our production builds are 99.9% equivalent to https://github.com/prusa3d/Prusa-Firmware#linux this is also easiest way to build as only one step is needed - run a single script, which downloads patched Arduino from GitHub, builds using it, then extracts translated strings and creates language variants (for MK2x) or language hex file for external SPI flash (MK3x). But you need Linux or Linux in a virtual machine. This is also what happens when you open a pull request to our repository - all variants are built by Travis http://travis-ci.org/ (to check for compilation errors). You can see, what is happening in .travis.yml. It would be also possible to get hex built by Travis, only the deploy step is missing in .travis.yml. You can find inspiration on how to deploy hex in Travis and how to setup Travis in https://github.com/prusa3d/MM-control-01/ repository. The final hex is located in ./lang/firmware.hex - community reproduced this for Windows in https://github.com/prusa3d/Prusa-Firmware#using-linux-subsystem-under-windows-10-64-bit or https://github.com/prusa3d/Prusa-Firmware#using-git-bash-under-windows-10-64-bit .
Q:Why are build instructions for Arduino mess.
Q:Why are build instructions for Arduino a mess?
Y:We are too lazy to ship proper board definition for Arduino. We plan to switch to cmake + ninja to be inherently multiplatform, easily integrate build tools, suport more IDEs, get 10 times shorter build times and be able to update compiler whenever we want.
Y:We are too lazy to ship a proper board definition for Arduino. We plan to switch to CMake + ninja to be inherently multiplatform, easily integrate build tools, suport more IDEs, get 10 times shorter build times and be able to update compiler whenever we want.

View File

@ -0,0 +1,37 @@
## List of Community made translations
- **Dutch / Nederlands**
- Maintainers: **@3d-gussner** and **@vintagepc**
- Co-maintainers:
- Contributors: **@stelgenhof**
- [X] **Active** since March 2021
- [X] **Maintained** since September 2019
- **Romanian / Română**
- Maintainers: **@leptun** and **@Hauzman**
- Co-maintainers: **@QuantumRoboticsFTC**
- Contributors:
- [X] **Active** since January 2022
- [X] **Maintained** since January 2022
- **Hungarian / Magyar**
- Maintainers: **@AttilaSVK**
- Co-maintainers: **@Hauzman**
- Contributors:
- [X] **Active** since January 2022
- [X] **Maintained** since January 2022
- **Croatian / Hrvatski**
- Maintainers: **@Prime1910**
- Co-maintainers: **@PRPA041**
- Contributors:
- [X] **Active** since January 2022
- [X] **Maintained** since January 2022
- **Swedish / Svenska**
- Maintainers: **@Painkiller56**
- Co-maintainers:
- Contributors:
- [ ] **Active** since January 2022
- [X] **Maintained** since January 2022

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

54
tools/README.md Normal file
View File

@ -0,0 +1,54 @@
# Host debugging tools for Prusa MK3 firmware
## Tools
### ``dump_eeprom``
Dump the content of the entire EEPROM using the D3 command.
Requires ``printcore`` from [Pronterface].
### ``dump_sram``
Dump the content of the entire SRAM using the D2 command.
Requires ``printcore`` from [Pronterface].
### ``dump_crash``
Dump the content of the last crash dump on MK3+ printers using D21.
Requires ``printcore`` from [Pronterface].
### ``elf_mem_map``
Generate a symbol table map with decoded information starting directly from an ELF firmware with DWARF debugging information (which is the default using the stock board definition).
When used along with a memory dump obtained from the D2 g-code, show the value of each symbol which is within the address range of the dump.
When used with ``--map`` and a single elf file, generate a map consisting of memory location and source location for each statically-addressed variable.
With ``--qdirstat`` and a single elf file, generate a [qdirstat](https://github.com/shundhammer/qdirstat) compatible cache file which can be loaded to inspect memory utilization interactively in a treemap.
This assumes the running firmware generating the dump and the elf file are the same.
Requires Python3 and the [pyelftools](https://github.com/eliben/pyelftools) module.
### ``dump2bin``
Parse and decode a memory dump obtained from the D2/D21/D23 g-code into readable metadata and binary. The output binary is padded and extended to fit the original address range.
### ``xfimg2dump``
Extract a crash dump from an external flash image and output the same format produced by the D21 g-code.
### ``update_eeprom``
Given one EEPROM dump, convert the dump to update instructions that can be sent to a printer.
Given two EEPROM dumps, produces only the required instructions needed to update the contents from the first to the second. This is currently quite crude and assumes dumps are aligned (starting from the same address or same stride).
Optionally writes the instructions to the specified port (requires ``printcore`` from [Pronterface]).
### ``noreset``
Set the required TTY flags on the specified port to avoid reset-on-connect for *subsequent* requests (issuing this command might still cause the printer to reset).
[Pronterface]: https://github.com/kliment/Printrun

59
tools/dump2bin Executable file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env python3
import argparse
import os, sys
from lib.dump import decode_dump
def main():
# parse the arguments
ap = argparse.ArgumentParser(description="""
Parse and decode a memory dump obtained from the D2/D21/D23 g-code
into readable metadata and binary. The output binary is padded and
extended to fit the original address range.
""")
ap.add_argument('-i', dest='info', action='store_true',
help='display crash info only')
ap.add_argument('dump')
ap.add_argument('output', nargs='?')
args = ap.parse_args()
# decode the dump data
dump = decode_dump(args.dump)
if dump is None:
return os.EX_DATAERR
# output descriptors
if args.info:
o_fd = None
o_md = sys.stdout
elif args.output is None:
o_fd = sys.stdout.buffer
o_md = sys.stderr
else:
o_fd = open(args.output, 'wb')
o_md = sys.stdout
# output binary
if o_fd:
o_fd.write(dump.data)
o_fd.close()
# metadata
print(' dump type: {typ}\n'
'crash reason: {reason}\n'
' registers: {regs}\n'
' PC: {pc}\n'
' SP: {sp}\n'
' ranges: {ranges}'.format(
typ=dump.typ,
reason=dump.reason.name if dump.reason is not None else 'N/A',
regs=dump.regs,
pc='{:#x}'.format(dump.pc) if dump.pc is not None else 'N/A',
sp='{:#x}'.format(dump.sp) if dump.sp is not None else 'N/A',
ranges=str(dump.ranges)),
file=o_md)
if __name__ == '__main__':
exit(main())

17
tools/dump_crash Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
prg=$(basename "$0")
port="$1"
if [ -z "$port" -o "$port" = "-h" ]
then
echo "usage: $0 <port>" >&2
echo "Connect to <port> and dump the content of last crash using D21 to stdout" >&2
exit 1
fi
set -e
tmp=$(mktemp)
trap "rm -f \"$tmp\"" EXIT
echo D21 > "$tmp"
printcore -v "$port" "$tmp" 2>&1 | \
sed -ne '/^RECV: D21 /,/RECV: ok$/s/^RECV: //p'

17
tools/dump_eeprom Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
prg=$(basename "$0")
port="$1"
if [ -z "$port" -o "$port" = "-h" ]
then
echo "usage: $0 <port>" >&2
echo "Connect to <port> and dump the content of the EEPROM using D3 to stdout" >&2
exit 1
fi
set -e
tmp=$(mktemp)
trap "rm -f \"$tmp\"" EXIT
echo D3 > "$tmp"
printcore -v "$port" "$tmp" 2>&1 | \
sed -ne '/^RECV: D3 /,/RECV: ok$/s/^RECV: //p'

17
tools/dump_sram Executable file
View File

@ -0,0 +1,17 @@
#!/bin/sh
prg=$(basename "$0")
port="$1"
if [ -z "$port" -o "$port" = "-h" ]
then
echo "usage: $0 <port>" >&2
echo "Connect to <port> and dump the content of the SRAM using D2 to stdout" >&2
exit 1
fi
set -e
tmp=$(mktemp)
trap "rm -f \"$tmp\"" EXIT
echo D2 > "$tmp"
printcore -v "$port" "$tmp" 2>&1 | \
sed -ne '/^RECV: D2 /,/RECV: ok$/s/^RECV: //p'

389
tools/elf_mem_map Executable file
View File

@ -0,0 +1,389 @@
#!/usr/bin/env python3
import argparse
import elftools.elf.elffile
import elftools.dwarf.descriptions
from collections import namedtuple
from struct import unpack
import os
from lib.dump import decode_dump
from lib.avr import *
Entry = namedtuple('Entry', ['name', 'loc', 'size', 'declpos'])
Member = namedtuple('Member', ['name', 'off', 'size'])
def array_inc(loc, dim, idx=0):
if idx == len(dim):
return True
loc[idx] += 1
if loc[idx] == dim[idx]:
loc[idx] = 0
return array_inc(loc, dim, idx+1)
return False
def get_type_size(type_DIE):
while True:
if 'DW_AT_byte_size' in type_DIE.attributes:
return type_DIE, type_DIE.attributes.get('DW_AT_byte_size').value
if 'DW_AT_type' not in type_DIE.attributes:
return None
type_DIE = type_DIE.get_DIE_from_attribute('DW_AT_type')
def get_type_arrsize(type_DIE):
size = get_type_size(type_DIE)
if size is None:
return None
byte_size = size[1]
if size[0].tag != 'DW_TAG_pointer_type':
array_DIE = get_type_def(type_DIE, 'DW_TAG_array_type')
if array_DIE is not None:
for range_DIE in array_DIE.iter_children():
if range_DIE.tag == 'DW_TAG_subrange_type' and \
'DW_AT_upper_bound' in range_DIE.attributes:
dim = range_DIE.attributes['DW_AT_upper_bound'].value + 1
byte_size *= dim
return byte_size
def get_type_def(type_DIE, type_tag):
while True:
if type_DIE.tag == type_tag:
return type_DIE
if 'DW_AT_type' not in type_DIE.attributes:
return None
type_DIE = type_DIE.get_DIE_from_attribute('DW_AT_type')
def get_FORM_block1(attr):
if attr.form != 'DW_FORM_block1':
return None
if attr.value[0] == 3: # OP_addr
return int.from_bytes(attr.value[1:], 'little')
if attr.value[0] == 35: # OP_plus_uconst (ULEB128)
v = 0
s = 0
for b in attr.value[1:]:
v |= (b & 0x7f) << s
if b & 0x80 == 0:
break
s += 7
return v
return None
def get_array_dims(DIE):
array_DIE = get_type_def(DIE, 'DW_TAG_array_type')
if array_DIE is None:
return []
array_dim = []
for range_DIE in array_DIE.iter_children():
if range_DIE.tag == 'DW_TAG_subrange_type' and \
'DW_AT_upper_bound' in range_DIE.attributes:
array_dim.append(range_DIE.attributes['DW_AT_upper_bound'].value + 1)
return array_dim
def get_struct_members(DIE, entry, expand_structs, struct_gaps):
struct_DIE = get_type_def(DIE, 'DW_TAG_structure_type')
if struct_DIE is None:
return []
members = []
for member_DIE in struct_DIE.iter_children():
if member_DIE.tag == 'DW_TAG_member' and 'DW_AT_name' in member_DIE.attributes:
m_name = member_DIE.attributes['DW_AT_name'].value.decode('ascii')
m_off = get_FORM_block1(member_DIE.attributes['DW_AT_data_member_location'])
m_byte_size = get_type_size(member_DIE)[1]
# still expand member arrays
m_array_dim = get_array_dims(member_DIE)
if m_byte_size == 1 and len(m_array_dim) > 1:
# likely string, remove one dimension
m_byte_size *= m_array_dim.pop()
if len(m_array_dim) == 0 or (len(m_array_dim) == 1 and m_array_dim[0] == 1):
# plain entry
members.append(Member(m_name, m_off, m_byte_size))
elif len(m_array_dim) == 1 and m_byte_size == 1:
# likely string, avoid expansion
members.append(Member(m_name + '[]', m_off, m_array_dim[0]))
else:
# expand array entries
m_array_pos = m_off
m_array_loc = [0] * len(m_array_dim)
while True:
# location index
sfx = ''
for d in range(len(m_array_dim)):
sfx += '[{}]'.format(str(m_array_loc[d]).rjust(len(str(m_array_dim[d]-1)), '0'))
members.append(Member(m_name + sfx, m_array_pos, m_byte_size))
# advance
if array_inc(m_array_loc, m_array_dim):
break
m_array_pos += m_byte_size
if struct_gaps and len(members):
# fill gaps in the middle
members = list(sorted(members, key=lambda x: x.off))
last_end = 0
for n in range(len(members)):
member = members[n]
if member.off > last_end:
members.append(Member('*UNKNOWN*', last_end, member.off - last_end))
last_end = member.off + member.size
if struct_gaps and len(members):
# fill gap at the end
members = list(sorted(members, key=lambda x: x.off))
last = members[-1]
last_end = last.off + last.size
if entry.size > last_end:
members.append(Member('*UNKNOWN*', last_end, entry.size - last_end))
return members
def get_elf_globals(path, expand_structs, struct_gaps=True):
fd = open(path, "rb")
if fd is None:
return
elffile = elftools.elf.elffile.ELFFile(fd)
if elffile is None or not elffile.has_dwarf_info():
return
# probably not needed, since we're decoding expressions manually
elftools.dwarf.descriptions.set_global_machine_arch(elffile.get_machine_arch())
dwarfinfo = elffile.get_dwarf_info()
grefs = []
for CU in dwarfinfo.iter_CUs():
file_entries = dwarfinfo.line_program_for_CU(CU).header["file_entry"]
for DIE in CU.iter_DIEs():
# handle only variable types
if DIE.tag != 'DW_TAG_variable':
continue
if 'DW_AT_location' not in DIE.attributes:
continue
if 'DW_AT_name' not in DIE.attributes and \
'DW_AT_abstract_origin' not in DIE.attributes:
continue
# handle locations encoded directly as DW_OP_addr (leaf globals)
loc = get_FORM_block1(DIE.attributes['DW_AT_location'])
if loc is None or loc < SRAM_OFFSET or loc >= EEPROM_OFFSET:
continue
loc -= SRAM_OFFSET
# variable name/type
if 'DW_AT_name' not in DIE.attributes and \
'DW_AT_abstract_origin' in DIE.attributes:
DIE = DIE.get_DIE_from_attribute('DW_AT_abstract_origin')
if 'DW_AT_location' in DIE.attributes:
# duplicate reference (handled directly), skip
continue
if 'DW_AT_name' not in DIE.attributes:
continue
if 'DW_AT_type' not in DIE.attributes:
continue
name = DIE.attributes['DW_AT_name'].value.decode('ascii')
# get final storage size
size = get_type_size(DIE)
if size is None:
continue
byte_size = size[1]
# location of main definition
declpos = ''
if 'DW_AT_decl_file' in DIE.attributes and \
'DW_AT_decl_line' in DIE.attributes:
line = DIE.attributes['DW_AT_decl_line'].value
fname = DIE.attributes['DW_AT_decl_file'].value
if fname and fname - 1 < len(file_entries):
fname = file_entries[fname-1].name.decode('ascii')
declpos = '{}:{}'.format(fname, line)
# fetch array dimensions (if known)
array_dim = get_array_dims(DIE)
# fetch structure members (one level only)
entry = Entry(name, loc, byte_size, declpos)
if not expand_structs or size[0].tag == 'DW_TAG_pointer_type':
members = []
else:
members = get_struct_members(DIE, entry, expand_structs, struct_gaps)
def expand_members(entry, members):
if len(members) == 0:
grefs.append(entry)
else:
for member in members:
grefs.append(Entry(entry.name + '.' + member.name,
entry.loc + member.off, member.size,
entry.declpos))
if byte_size == 1 and len(array_dim) > 1:
# likely string, remove one dimension
byte_size *= array_dim.pop()
if len(array_dim) == 0 or (len(array_dim) == 1 and array_dim[0] == 1):
# plain entry
expand_members(entry, members)
elif len(array_dim) == 1 and byte_size == 1:
# likely string, avoid expansion
grefs.append(Entry(entry.name + '[]', entry.loc,
array_dim[0], entry.declpos))
else:
# expand array entries
array_pos = loc
array_loc = [0] * len(array_dim)
while True:
# location index
sfx = ''
for d in range(len(array_dim)):
sfx += '[{}]'.format(str(array_loc[d]).rjust(len(str(array_dim[d]-1)), '0'))
expand_members(Entry(entry.name + sfx, array_pos,
byte_size, entry.declpos), members)
# advance
if array_inc(array_loc, array_dim):
break
array_pos += byte_size
return grefs
def annotate_refs(grefs, addr, data, width, gaps=True, overlaps=True):
last_end = None
for entry in grefs:
if entry.loc < addr:
continue
if entry.loc + entry.size > addr + len(data):
continue
pos = entry.loc-addr
end_pos = pos + entry.size
buf = data[pos:end_pos]
buf_repr = ''
if len(buf) in [1, 2, 4]:
# attempt to decode as integers
buf_repr += ' I:' + str(int.from_bytes(buf, 'little')).rjust(10)
if len(buf) in [4, 8]:
# attempt to decode as floats
typ = 'f' if len(buf) == 4 else 'd'
buf_repr += ' F:' + '{:10.3f}'.format(unpack(typ, buf)[0])
if last_end is not None:
if gaps and last_end < pos:
# decode gaps
gap_size = pos - last_end
gap_buf = data[last_end:pos]
print('{:04x} {} {:4} R:{}'.format(addr+last_end, "*UNKNOWN*".ljust(width),
gap_size, gap_buf.hex()))
if overlaps and last_end > pos + 1:
gap_size = pos - last_end
print('{:04x} {} {:4}'.format(addr+last_end, "*OVERLAP*".ljust(width), gap_size))
print('{:04x} {} {:4}{} R:{}'.format(entry.loc, entry.name.ljust(width),
entry.size, buf_repr, buf.hex()))
last_end = end_pos
def print_map(grefs):
print('OFFSET\tSIZE\tNAME\tDECLPOS')
for entry in grefs:
print('{:x}\t{}\t{}\t{}'.format(entry.loc, entry.size, entry.name, entry.declpos))
def print_qdirstat(grefs):
print('[qdirstat 1.0 cache file]')
entries = {}
for entry in grefs:
# do not output registers when looking at space usage
if entry.loc < SRAM_START:
continue
paths = list(filter(None, re.split(r'[\[\].]', entry.name)))
base = entries
for i in range(len(paths) - 1):
name = paths[i]
if name not in base:
base[name] = {}
base = base[name]
name = paths[-1]
if name in base:
name = '{}_{:x}'.format(entry.name, entry.loc)
base[name] = entry.size
def walker(root, prefix):
files = []
dirs = []
for name, entries in root.items():
if type(entries) == int:
files.append([name, entries])
else:
dirs.append([name, entries])
# print files
print('D\t{}\t{}\t0x0'.format(prefix, 0))
for name, size in files:
print('F\t{}\t{}\t0x0'.format(name, size))
# recurse directories
for name, entries in dirs:
walker(entries, prefix + '/' + name)
walker(entries, '/')
def main():
ap = argparse.ArgumentParser(description="""
Generate a symbol table map starting directly from an ELF
firmware with DWARF3 debugging information.
When used along with a memory dump obtained from the D2/D21/D23 g-code,
show the value of each symbol which is within the address range.
""")
ap.add_argument('elf', help='ELF file containing DWARF debugging information')
ap.add_argument('--no-gaps', action='store_true',
help='do not dump memory inbetween known symbols')
ap.add_argument('--no-expand-structs', action='store_true',
help='do not decode structure data')
ap.add_argument('--overlaps', action='store_true',
help='annotate overlaps greater than 1 byte')
ap.add_argument('--name-width', type=int, default=50,
help='set name column width')
g = ap.add_mutually_exclusive_group(required=True)
g.add_argument('dump', nargs='?', help='RAM dump obtained from D2 g-code')
g.add_argument('--map', action='store_true', help='dump global memory map')
g.add_argument('--qdirstat', action='store_true',
help='dump qdirstat-compatible size usage map')
args = ap.parse_args()
grefs = get_elf_globals(args.elf, expand_structs=not args.no_expand_structs)
grefs = list(sorted(grefs, key=lambda x: x.loc))
if args.map:
print_map(grefs)
elif args.qdirstat:
print_qdirstat(grefs)
else:
# fetch the memory data
dump = decode_dump(args.dump)
if dump is None:
return os.EX_DATAERR
# strip padding, if present
addr_start = dump.ranges[0][0]
addr_end = dump.ranges[-1][0]+dump.ranges[-1][1]
data = dump.data[addr_start:addr_end]
annotate_refs(grefs, addr_start, data,
width=args.name_width,
gaps=not args.no_gaps,
overlaps=args.overlaps)
if __name__ == '__main__':
exit(main())

4
tools/lib/avr.py Normal file
View File

@ -0,0 +1,4 @@
SRAM_START = 0x200
SRAM_SIZE = 0x2000
SRAM_OFFSET = 0x800000
EEPROM_OFFSET = 0x810000

169
tools/lib/dump.py Normal file
View File

@ -0,0 +1,169 @@
import sys
import re
import enum
import struct
from . import avr
FILL_BYTE = b'\0' # used to fill memory gaps in the dump
DUMP_MAGIC = 0x55525547 # XFLASH dump magic
DUMP_OFFSET = 0x3d000 # XFLASH dump offset
DUMP_SIZE = 0x2300 # XFLASH dump size
class CrashReason(enum.IntEnum):
MANUAL = 0
STACK_ERROR = 1
WATCHDOG = 2
BAD_ISR = 3
class Dump():
def __init__(self, typ, reason, regs, pc, sp, data, ranges):
self.typ = typ
self.reason = reason
self.regs = regs
self.pc = pc
self.sp = sp
self.data = data
self.ranges = ranges
# expand the buffer identified by addr+data to fill the region start+size
def region_expand(addr, data, start, size):
if start < addr:
data = FILL_BYTE * (addr - start) + data
addr = start
end = start + size
data_end = addr + len(data)
if end > data_end:
data += FILL_BYTE * (data_end - end)
return addr, data
def merge_ranges(ranges):
ranges = list(sorted(ranges, key=lambda x: x[0]))
if len(ranges) < 2:
return ranges
ret = [ranges[0]]
for cur in ranges[1:]:
last = ret[-1]
last_end = last[0] + last[1]
if last_end < cur[0]:
ret.append(cur)
else:
cur_end = cur[0] + cur[1]
last = (last[0], max(last_end, cur_end) - last[0])
ret[-1] = last
return ret
def decode_dump(path):
fd = open(path, 'r')
if fd is None:
return None
buf_addr = None # starting address
buf_data = None # data
typ = None # dump type
reason = None # crash reason
regs = None # registers present
pc = None # PC address
sp = None # SP address
ranges = [] # dumped ranges
in_dump = False
for line in enumerate(fd):
line = (line[0], line[1].rstrip())
tokens = line[1].split(maxsplit=1)
def line_error():
print('malformed line {}: {}'.format(*line), file=sys.stderr)
# handle metadata
if not in_dump:
if len(tokens) > 0 and tokens[0] in ['D2', 'D21', 'D23']:
in_dump = True
typ = tokens[0]
continue
else:
if len(tokens) == 0:
line_error()
continue
elif tokens[0] == 'ok':
break
elif tokens[0] == 'error:' and len(tokens) == 2:
values = tokens[1].split(' ')
if typ == 'D23' and len(values) >= 3:
reason = CrashReason(int(values[0], 0))
pc = int(values[1], 0)
sp = int(values[2], 0)
else:
line_error()
continue
elif len(tokens) != 2 or not re.match(r'^[0-9a-fA-F]+$', tokens[0]):
line_error()
continue
# decode hex data
addr = int.from_bytes(bytes.fromhex(tokens[0]), 'big')
data = bytes.fromhex(tokens[1])
ranges.append((addr, len(data)))
if buf_addr is None:
buf_addr = addr
buf_data = data
else:
# grow buffer as needed
buf_addr, buf_data = region_expand(buf_addr, buf_data,
addr, len(data))
# replace new part
rep_start = addr - buf_addr
rep_end = rep_start + len(data)
buf_data = buf_data[:rep_start] + data + buf_data[rep_end:]
# merge continuous ranges
ranges = merge_ranges(ranges)
if typ == 'D2':
# D2 doesn't guarantee registers to be present
regs = len(ranges) > 0 and \
ranges[0][0] == 0 and \
ranges[0][1] >= avr.SRAM_START
# fill to fit for easy loading
buf_addr, buf_data = region_expand(
buf_addr, buf_data, 0, avr.SRAM_START + avr.SRAM_SIZE)
elif typ == 'D23':
# check if the dump is complete
if len(ranges) != 1 or ranges[0][0] != 0 or \
ranges[0][1] != avr.SRAM_START + avr.SRAM_SIZE:
print('error: incomplete D23 dump', file=sys.stderr)
return None
regs = True
if reason is None:
print('warning: no error line in D23', file=sys.stderr)
elif typ == 'D21':
if len(ranges) != 1 or len(buf_data) != (avr.SRAM_START + avr.SRAM_SIZE + 256):
print('error: incomplete D21 dump', file=sys.stderr)
return None
# decode the header structure
magic, regs_present, crash_reason, pc, sp = struct.unpack('<LBBLH', buf_data[0:12])
if magic != DUMP_MAGIC:
print('error: invalid dump header in D21', file=sys.stderr)
return None
regs = bool(regs_present)
reason = CrashReason(crash_reason)
# extract the data section
buf_addr = 0
buf_data = buf_data[256:]
ranges[0] = (0, len(buf_data))
return Dump(typ, reason, regs, pc, sp, buf_data, ranges)

12
tools/noreset Executable file
View File

@ -0,0 +1,12 @@
#!/bin/sh
prg=$(basename "$0")
port="$1"
if [ -z "$port" -o "$port" = "-h" ]
then
echo "usage: $0 <port>" >&2
echo "Set TTY flags on <port> to avoid reset-on-connect" >&2
exit 1
fi
set -e
stty -F "$port" -hup

54
tools/update_eeprom Executable file
View File

@ -0,0 +1,54 @@
#!/bin/sh
prg=$(basename "$0")
# parse arguments
while getopts f:h optname
do
case $optname in
f) port="$OPTARG" ;;
*) help=1 ;;
esac
done
shift `expr $OPTIND - 1`
old="$1"
new="$2"
if [ -z "$old" -o "$help" = "-h" -o "$#" -gt 2 ]
then
echo "usage: $0 [-f <port>] <old dump> [<new dump>]" >&2
echo "Convert <old dump> to instructions to update instructions." >&2
echo "With <new dump>, generate instructions to update EEPROM changes only." >&2
echo "Optionally write such changes directly if <port> if given." >&2
exit 1
fi
set -e
instr=$(mktemp)
trap "rm -f \"$instr\"" EXIT
convert()
{
sed -ne 's/^\([0-9a-f]\{4\}\) \([0-9a-f ]*\)$/D3 Ax\1 C16 X\2/p' "$@"
}
if [ -z "$new" ]; then
# convert the instructions to updates
convert "$old" > "$instr"
else
tmp1=$(mktemp)
tmp2=$(mktemp)
trap "rm -f \"$tmp1\" \"$tmp2\"" EXIT
convert "$old" > "$tmp1"
convert "$new" > "$tmp2"
comm -13 "$tmp1" "$tmp2" > "$instr"
fi
# write the instructions if requested
if [ -z "$port" ]; then
cat "$instr"
else
printcore -v "$port" "$instr"
fi

89
tools/utils.gdb Normal file
View File

@ -0,0 +1,89 @@
# -*- gdb-script -*-
define load_dump
restore $arg0 binary 0x800000
set $pc = (((unsigned long)$arg1) - 2) << 1
set $sp = $arg2
where
end
document load_dump
Load a crash dump, setup PC/SP and show the current backtrace
Usage: load_dump <file> <PC-addr> <SP-addr>
end
define sp_skip
if $argc == 0
set $shift = 3
else
set $shift = $arg0
end
set $new_pc = ((((unsigned long)*(uint8_t*)($sp+$shift+1)) << 16) + \
(((unsigned long)*(uint8_t*)($sp+$shift+2)) << 8) + \
(((unsigned long)*(uint8_t*)($sp+$shift+3)) << 0)) << 1
set $new_sp = $sp+$shift+3
select-frame 0
set $saved_pc = $pc
set $saved_sp = $sp
set $pc = $new_pc
set $sp = $new_sp
where
end
document sp_skip
Decode the PC address at SP+offset, then show the resulting stack.
The default (and minimum) offset is 3.
Usage: sp_skip [off]
end
define sp_restore
select-frame 0
set $pc = $saved_pc
set $sp = $saved_sp
where
end
document sp_restore
Undo an sp_skip move (restore existing PC/SP positions)
Usage: sp_restore
end
define sp_test
sp_skip $arg0
set $pc = $saved_pc
set $sp = $saved_sp
end
document sp_test
Attempt to decode the PC address at SP+offset, then show the resulting stack.
The default (and minimum) offset is 3.
Usage: sp_test [off]
end
define sp_scan
dont-repeat
if $argc == 0
set $sp_end = 0x802200
else
set $sp_end = $arg0
end
set $sp_pos = $sp
while $sp_pos < ($sp_end-4)
set $sp_off = $sp_pos - $sp
printf "**** scanning %#x (+%u) ****\n", $sp_pos, $sp_off
sp_test $sp_off
set $sp_pos += 1
end
end
document sp_scan
Attempt to decode PC at any location starting from the SP+3 and up to SP-end
(by default the end of the SRAM) and show the resulting stack at all locations.
Usage: sp_scan [SP-end]
end

46
tools/xfimg2dump Executable file
View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
import argparse
import struct
import os, sys
from lib.dump import DUMP_MAGIC, DUMP_OFFSET, DUMP_SIZE
def error(msg):
print(msg, file=sys.stderr)
def main():
# parse the arguments
ap = argparse.ArgumentParser(description="""
Extract a crash dump from an external flash image and output
the same format produced by the D21 g-code.
""")
ap.add_argument('image')
args = ap.parse_args()
# read the image
off = DUMP_OFFSET
with open(args.image, 'rb') as fd:
fd.seek(off)
data = fd.read(DUMP_SIZE)
if len(data) != DUMP_SIZE:
error('incorrect image size')
return os.EX_DATAERR
# check for magic header
magic, = struct.unpack('<L', data[:4])
if magic != DUMP_MAGIC:
error('invalid dump magic or no dump')
return os.EX_DATAERR
# output D21 dump
print('D21 - read crash dump', end='')
for i in range(len(data)):
if i % 16 == 0:
print('\n{:06x} '.format(off + i), end='')
print(' {:02x}'.format(data[i]), end='')
print('\nok')
if __name__ == '__main__':
exit(main())