Fix compile error

This commit is contained in:
David Ramiro
2019-01-31 14:52:18 +01:00
parent 5893bcbcc0
commit 71b02e6e9c
79 changed files with 0 additions and 58529 deletions

View File

@@ -1,337 +0,0 @@
/* **************************************************************************
Marlin 3D Printer Firmware
Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* Description: HAL for __AVR__
*/
#ifndef _HAL_AVR_H_
#define _HAL_AVR_H_
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
#include "fastio.h"
#include <stdint.h>
#include <Arduino.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>
// --------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------
//#define analogInputToDigitalPin(IO) IO
// Bracket code that shouldn't be interrupted
#ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END SREG = _sreg
#endif
#define ISRS_ENABLED() TEST(SREG, SREG_I)
#define ENABLE_ISRS() sei()
#define DISABLE_ISRS() cli()
// --------------------------------------------------------------------------
// Types
// --------------------------------------------------------------------------
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF
typedef int8_t pin_t;
#define HAL_SERVO_LIB Servo
// --------------------------------------------------------------------------
// Public Variables
// --------------------------------------------------------------------------
//extern uint8_t MCUSR;
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
//void cli(void);
//void _delay_ms(const int delay);
inline void HAL_clear_reset_source(void) { MCUSR = 0; }
inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
// eeprom
//void eeprom_write_byte(unsigned char *pos, unsigned char value);
//unsigned char eeprom_read_byte(unsigned char *pos);
// timers
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#define STEP_TIMER_NUM 1
#define TEMP_TIMER_NUM 0
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
UNUSED(frequency);
switch (timer_num) {
case STEP_TIMER_NUM:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
// output mode = 00 (disconnected)
SET_COMA(1, NORMAL);
// Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
// Init Stepper ISR to 122 Hz for quick starting
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
OCR1A = 0x4000;
TCNT1 = 0;
break;
case TEMP_TIMER_NUM:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0B = 128;
break;
}
}
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define _CAT(a, ...) a ## __VA_ARGS__
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
/**
* On AVR there is no hardware prioritization and preemption of
* interrupts, so this emulates it. The UART has first priority
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR \
extern "C" void TIMER1_COMPA_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom (void) asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER1_COMPA_vect (void) { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("push r16") /* 2 Save TIMSK0 into the stack */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
A("sts %[timsk1], r16") /* 2 And set the new value */ \
A("push r16") /* 2 Save TIMSK1 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
A("pop r16") /* 2 Get the old SREG value */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 value */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \
); \
} \
void TIMER1_COMPA_vect_bottom(void)
/* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR \
extern "C" void TIMER0_COMPB_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPB_vect_bottom(void) asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPB_vect (void) { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
A("push r16") /* 2 Save TIMSK0 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
A("pop r16") /* 2 Get the old SREG */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \
: \
); \
} \
void TIMER0_COMPB_vect_bottom(void)
// ADC
#ifdef DIDR2
#define HAL_ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)
#else
#define HAL_ANALOG_SELECT(pin) do{ SBI(DIDR0, pin); }while(0)
#endif
inline void HAL_adc_init(void) {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
#ifdef MUX5
#define HAL_START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
#else
#define HAL_START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
#endif
#define HAL_READ_ADC() ADC
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#define HAL_SENSITIVE_PINS 0, 1
#endif // _HAL_AVR_H_

View File

@@ -1,77 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* AVR busy wait delay Cycles routines:
*
* DELAY_CYCLES(count): Delay execution in cycles
* DELAY_NS(count): Delay execution in nanoseconds
* DELAY_US(count): Delay execution in microseconds
*/
#ifndef MARLIN_DELAY_H
#define MARLIN_DELAY_H
#define nop() __asm__ __volatile__("nop;\n\t":::)
FORCE_INLINE static void __delay_4cycles(uint8_t cy) {
__asm__ __volatile__(
L("1")
A("dec %[cnt]")
A("nop")
A("brne 1b")
: [cnt] "+r"(cy) // output: +r means input+output
: // input:
: "cc" // clobbers:
);
}
/* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint16_t x) {
if (__builtin_constant_p(x)) {
#define MAXNOPS 4
if (x <= (MAXNOPS)) {
switch (x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
}
else {
const uint32_t rem = (x) % (MAXNOPS);
switch (rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
if ((x = (x) / (MAXNOPS)))
__delay_4cycles(x); // if need more then 4 nop loop is more optimal
}
#undef MAXNOPS
}
else
__delay_4cycles(x / 4);
}
#undef nop
/* ---------------- Delay in nanoseconds */
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) / 1000L )
/* ---------------- Delay in microseconds */
#define DELAY_US(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) )
#endif // MARLIN_DELAY_H

View File

@@ -1,73 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _DRIVERS_H_
#define _DRIVERS_H_
#include "MarlinConfig.h"
#define A4988 0x001
#define DRV8825 0x002
#define LV8729 0x003
#define L6470 0x104
#define TB6560 0x005
#define TB6600 0x006
#define TMC2100 0x007
#define TMC2130 0x108
#define TMC2130_STANDALONE 0x008
#define TMC2208 0x109
#define TMC2208_STANDALONE 0x009
#define TMC26X 0x10A
#define TMC26X_STANDALONE 0x00A
#define TMC2660 0x10B
#define TMC2660_STANDALONE 0x00B
#define _AXIS_DRIVER_TYPE(A,T) ( defined(A##_DRIVER_TYPE) && (A##_DRIVER_TYPE == T) )
#define AXIS_DRIVER_TYPE_X(T) _AXIS_DRIVER_TYPE(X,T)
#define AXIS_DRIVER_TYPE_Y(T) _AXIS_DRIVER_TYPE(Y,T)
#define AXIS_DRIVER_TYPE_Z(T) _AXIS_DRIVER_TYPE(Z,T)
#define AXIS_DRIVER_TYPE_X2(T) (ENABLED(X_DUAL_STEPPER_DRIVERS) || ENABLED(DUAL_X_CARRIAGE)) && _AXIS_DRIVER_TYPE(X2,T)
#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
#define AXIS_DRIVER_TYPE_Z2(T) (ENABLED(Z_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Z2,T))
#define AXIS_DRIVER_TYPE_E0(T) (E_STEPPERS > 0 && _AXIS_DRIVER_TYPE(E0,T))
#define AXIS_DRIVER_TYPE_E1(T) (E_STEPPERS > 1 && _AXIS_DRIVER_TYPE(E1,T))
#define AXIS_DRIVER_TYPE_E2(T) (E_STEPPERS > 2 && _AXIS_DRIVER_TYPE(E2,T))
#define AXIS_DRIVER_TYPE_E3(T) (E_STEPPERS > 3 && _AXIS_DRIVER_TYPE(E3,T))
#define AXIS_DRIVER_TYPE_E4(T) (E_STEPPERS > 4 && _AXIS_DRIVER_TYPE(E4,T))
#define AXIS_DRIVER_TYPE(A,T) AXIS_DRIVER_TYPE_##A(T)
#define HAS_DRIVER(T) (AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_X2(T) || \
AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Y2(T) || \
AXIS_DRIVER_TYPE_Z(T) || AXIS_DRIVER_TYPE_Z2(T) || \
AXIS_DRIVER_TYPE_E0(T) || AXIS_DRIVER_TYPE_E1(T) || \
AXIS_DRIVER_TYPE_E2(T) || AXIS_DRIVER_TYPE_E3(T) || \
AXIS_DRIVER_TYPE_E4(T) )
// Test for supported TMC drivers that require advanced configuration
// Does not match standalone configurations
#define HAS_TRINAMIC (HAS_DRIVER(TMC2130) || HAS_DRIVER(TMC2208))
#define AXIS_IS_TMC(A) ( AXIS_DRIVER_TYPE_##A(TMC2130) || \
AXIS_DRIVER_TYPE_##A(TMC2208) )
#endif // _DRIVERS_H_

View File

@@ -1,40 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* emergency_parser.cpp - Intercept special commands directly in the serial stream
*/
#include "MarlinConfig.h"
#if ENABLED(EMERGENCY_PARSER)
#include "emergency_parser.h"
// Static data members
bool EmergencyParser::killed_by_M112; // = false
EmergencyParser::State EmergencyParser::state; // = EP_RESET
// Global instance
EmergencyParser emergency_parser;
#endif // EMERGENCY_PARSER

View File

@@ -1,144 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* emergency_parser.h - Intercept special commands directly in the serial stream
*/
#ifndef _EMERGENCY_PARSER_H_
#define _EMERGENCY_PARSER_H_
// External references
extern volatile bool wait_for_user, wait_for_heatup;
void quickstop_stepper();
class EmergencyParser {
public:
// Currently looking for: M108, M112, M410
enum State : char {
EP_RESET,
EP_N,
EP_M,
EP_M1,
EP_M10,
EP_M108,
EP_M11,
EP_M112,
EP_M4,
EP_M41,
EP_M410,
EP_IGNORE // to '\n'
};
static bool killed_by_M112;
static State state;
EmergencyParser() {}
__attribute__((always_inline)) inline
static void update(const uint8_t c) {
switch (state) {
case EP_RESET:
switch (c) {
case ' ': break;
case 'N': state = EP_N; break;
case 'M': state = EP_M; break;
default: state = EP_IGNORE;
}
break;
case EP_N:
switch (c) {
case '0': case '1': case '2':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9': case '-': case ' ': break;
case 'M': state = EP_M; break;
default: state = EP_IGNORE;
}
break;
case EP_M:
switch (c) {
case ' ': break;
case '1': state = EP_M1; break;
case '4': state = EP_M4; break;
default: state = EP_IGNORE;
}
break;
case EP_M1:
switch (c) {
case '0': state = EP_M10; break;
case '1': state = EP_M11; break;
default: state = EP_IGNORE;
}
break;
case EP_M10:
state = (c == '8') ? EP_M108 : EP_IGNORE;
break;
case EP_M11:
state = (c == '2') ? EP_M112 : EP_IGNORE;
break;
case EP_M4:
state = (c == '1') ? EP_M41 : EP_IGNORE;
break;
case EP_M41:
state = (c == '0') ? EP_M410 : EP_IGNORE;
break;
case EP_IGNORE:
if (c == '\n') state = EP_RESET;
break;
default:
if (c == '\n') {
switch (state) {
case EP_M108:
wait_for_user = wait_for_heatup = false;
break;
case EP_M112:
killed_by_M112 = true;
break;
case EP_M410:
quickstop_stepper();
break;
default:
break;
}
state = EP_RESET;
}
}
}
};
extern EmergencyParser emergency_parser;
#endif // _EMERGENCY_PARSER_H_

View File

@@ -1,199 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* fwretract.cpp - Implement firmware-based retraction
*/
#include "MarlinConfig.h"
#if ENABLED(FWRETRACT)
#include "fwretract.h"
#include "Marlin.h"
#include "planner.h"
#include "stepper.h"
FWRetract fwretract; // Single instance - this calls the constructor
// private:
#if EXTRUDERS > 1
bool FWRetract::retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted
#endif
// public:
bool FWRetract::autoretract_enabled, // M209 S - Autoretract switch
FWRetract::retracted[EXTRUDERS]; // Which extruders are currently retracted
float FWRetract::retract_length, // M207 S - G10 Retract length
FWRetract::retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
FWRetract::retract_zlift, // M207 Z - G10 Retract hop size
FWRetract::retract_recover_length, // M208 S - G11 Recover length
FWRetract::retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
FWRetract::swap_retract_length, // M207 W - G10 Swap Retract length
FWRetract::swap_retract_recover_length, // M208 W - G11 Swap Recover length
FWRetract::swap_retract_recover_feedrate_mm_s, // M208 R - G11 Swap Recover feedrate
FWRetract::hop_amount;
void FWRetract::reset() {
autoretract_enabled = false;
retract_length = RETRACT_LENGTH;
retract_feedrate_mm_s = RETRACT_FEEDRATE;
retract_zlift = RETRACT_ZLIFT;
retract_recover_length = RETRACT_RECOVER_LENGTH;
retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
swap_retract_length = RETRACT_LENGTH_SWAP;
swap_retract_recover_length = RETRACT_RECOVER_LENGTH_SWAP;
swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP;
hop_amount = 0.0;
for (uint8_t i = 0; i < EXTRUDERS; ++i) {
retracted[i] = false;
#if EXTRUDERS > 1
retracted_swap[i] = false;
#endif
}
}
/**
* Retract or recover according to firmware settings
*
* This function handles retract/recover moves for G10 and G11,
* plus auto-retract moves sent from G0/G1 when E-only moves are done.
*
* To simplify the logic, doubled retract/recover moves are ignored.
*
* Note: Z lift is done transparently to the planner. Aborting
* a print between G10 and G11 may corrupt the Z position.
*
* Note: Auto-retract will apply the set Z hop in addition to any Z hop
* included in the G-code. Use M207 Z0 to to prevent double hop.
*/
void FWRetract::retract(const bool retracting
#if EXTRUDERS > 1
, bool swapping /* =false */
#endif
) {
static float hop_amount = 0.0; // Total amount lifted, for use in recover
// Prevent two retracts or recovers in a row
if (retracted[active_extruder] == retracting) return;
// Prevent two swap-retract or recovers in a row
#if EXTRUDERS > 1
// Allow G10 S1 only after G10
if (swapping && retracted_swap[active_extruder] == retracting) return;
// G11 priority to recover the long retract if activated
if (!retracting) swapping = retracted_swap[active_extruder];
#else
constexpr bool swapping = false;
#endif
/* // debugging
SERIAL_ECHOLNPAIR("retracting ", retracting);
SERIAL_ECHOLNPAIR("swapping ", swapping);
SERIAL_ECHOLNPAIR("active extruder ", active_extruder);
for (uint8_t i = 0; i < EXTRUDERS; ++i) {
SERIAL_ECHOPAIR("retracted[", i);
SERIAL_ECHOLNPAIR("] ", retracted[i]);
#if EXTRUDERS > 1
SERIAL_ECHOPAIR("retracted_swap[", i);
SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
#endif
}
SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
SERIAL_ECHOLNPAIR("current_position[e] ", current_position[E_CART]);
SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
//*/
const float old_feedrate_mm_s = feedrate_mm_s,
renormalize = RECIPROCAL(planner.e_factor[active_extruder]),
base_retract = swapping ? swap_retract_length : retract_length,
old_z = current_position[Z_AXIS],
old_e = current_position[E_CART];
// The current position will be the destination for E and Z moves
set_destination_from_current();
if (retracting) {
// Retract by moving from a faux E position back to the current E position
feedrate_mm_s = retract_feedrate_mm_s;
destination[E_CART] -= base_retract * renormalize;
prepare_move_to_destination(); // set_current_to_destination
// Is a Z hop set, and has the hop not yet been done?
if (retract_zlift > 0.01 && !hop_amount) { // Apply hop only once
hop_amount += retract_zlift; // Add to the hop total (again, only once)
destination[Z_AXIS] += retract_zlift; // Raise Z by the zlift (M207 Z) amount
feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Maximum Z feedrate
prepare_move_to_destination(); // Raise up, set_current_to_destination
}
}
else {
// If a hop was done and Z hasn't changed, undo the Z hop
if (hop_amount) {
current_position[Z_AXIS] += hop_amount; // Restore the actual Z position
SYNC_PLAN_POSITION_KINEMATIC(); // Unspoof the position planner
feedrate_mm_s = planner.max_feedrate_mm_s[Z_AXIS]; // Z feedrate to max
prepare_move_to_destination(); // Lower Z, set_current_to_destination
hop_amount = 0.0; // Clear the hop amount
}
destination[E_CART] += (base_retract + (swapping ? swap_retract_recover_length : retract_recover_length)) * renormalize;
feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s;
prepare_move_to_destination(); // Recover E, set_current_to_destination
}
feedrate_mm_s = old_feedrate_mm_s; // Restore original feedrate
current_position[Z_AXIS] = old_z; // Restore Z and E positions
current_position[E_CART] = old_e;
SYNC_PLAN_POSITION_KINEMATIC(); // As if the move never took place
retracted[active_extruder] = retracting; // Active extruder now retracted / recovered
// If swap retract/recover update the retracted_swap flag too
#if EXTRUDERS > 1
if (swapping) retracted_swap[active_extruder] = retracting;
#endif
/* // debugging
SERIAL_ECHOLNPAIR("retracting ", retracting);
SERIAL_ECHOLNPAIR("swapping ", swapping);
SERIAL_ECHOLNPAIR("active_extruder ", active_extruder);
for (uint8_t i = 0; i < EXTRUDERS; ++i) {
SERIAL_ECHOPAIR("retracted[", i);
SERIAL_ECHOLNPAIR("] ", retracted[i]);
#if EXTRUDERS > 1
SERIAL_ECHOPAIR("retracted_swap[", i);
SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
#endif
}
SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
SERIAL_ECHOLNPAIR("current_position[e] ", current_position[E_CART]);
SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
//*/
}
#endif // FWRETRACT

View File

@@ -1,71 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* fwretract.h - Define firmware-based retraction interface
*/
#ifndef FWRETRACT_H
#define FWRETRACT_H
#include "MarlinConfig.h"
class FWRetract {
public:
static bool autoretract_enabled, // M209 S - Autoretract switch
retracted[EXTRUDERS]; // Which extruders are currently retracted
#if EXTRUDERS > 1
static bool retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted
#endif
static float retract_length, // M207 S - G10 Retract length
retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
retract_zlift, // M207 Z - G10 Retract hop size
retract_recover_length, // M208 S - G11 Recover length
retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
swap_retract_length, // M207 W - G10 Swap Retract length
swap_retract_recover_length, // M208 W - G11 Swap Recover length
swap_retract_recover_feedrate_mm_s, // M208 R - G11 Swap Recover feedrate
hop_amount;
FWRetract() { reset(); }
static void reset();
static void refresh_autoretract() {
for (uint8_t i = 0; i < EXTRUDERS; i++) retracted[i] = false;
}
static void enable_autoretract(const bool enable) {
autoretract_enabled = enable;
refresh_autoretract();
}
static void retract(const bool retracting
#if EXTRUDERS > 1
, bool swapping = false
#endif
);
};
extern FWRetract fwretract;
#endif // FWRETRACT_H

View File

@@ -1,275 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Spanish
*
* LCD Menu Messages
* See also http://marlinfw.org/docs/development/lcd_language.html
*
*/
#ifndef LANGUAGE_ES_UTF_H
#define LANGUAGE_ES_UTF_H
#define MAPPER_C2C3
#define DISPLAY_CHARSET_ISO10646_1
#define CHARSIZE 2
#define WELCOME_MSG MACHINE_NAME _UxGT(" lista.")
#define MSG_BACK _UxGT("Atrás")
#define MSG_SD_INSERTED _UxGT("Tarjeta colocada")
#define MSG_SD_REMOVED _UxGT("Tarjeta retirada")
#define MSG_LCD_ENDSTOPS _UxGT("Endstops") // Max length 8 characters
#define MSG_MAIN _UxGT("Menú principal")
#define MSG_AUTOSTART _UxGT("Inicio automático")
#define MSG_DISABLE_STEPPERS _UxGT("Apagar motores")
#define MSG_DEBUG_MENU _UxGT("Menú depurar")
#define MSG_PROGRESS_BAR_TEST _UxGT("Prueba barra avance")
#define MSG_AUTO_HOME _UxGT("Llevar al origen")
#define MSG_AUTO_HOME_X _UxGT("Origen X")
#define MSG_AUTO_HOME_Y _UxGT("Origen Y")
#define MSG_AUTO_HOME_Z _UxGT("Origen Z")
#define MSG_TMC_Z_CALIBRATION _UxGT("Calibrar Z")
#define MSG_LEVEL_BED_HOMING _UxGT("Origen XYZ")
#define MSG_LEVEL_BED_WAITING _UxGT("Iniciar (Presione)")
#define MSG_LEVEL_BED_NEXT_POINT _UxGT("Siguiente punto")
#define MSG_LEVEL_BED_DONE _UxGT("Nivelación lista!")
#define MSG_SET_HOME_OFFSETS _UxGT("Ajustar desfases")
#define MSG_HOME_OFFSETS_APPLIED _UxGT("Desfase aplicado")
#define MSG_SET_ORIGIN _UxGT("Establecer origen")
#define MSG_PREHEAT_1 _UxGT("Precalentar PLA")
#define MSG_PREHEAT_1_N MSG_PREHEAT_1 _UxGT(" ")
#define MSG_PREHEAT_1_ALL MSG_PREHEAT_1 _UxGT(" Todo")
#define MSG_PREHEAT_1_END MSG_PREHEAT_1 _UxGT(" End")
#define MSG_PREHEAT_1_BEDONLY MSG_PREHEAT_1 _UxGT(" Cama")
#define MSG_PREHEAT_1_SETTINGS MSG_PREHEAT_1 _UxGT(" Config")
#define MSG_PREHEAT_2 _UxGT("Precalentar ABS")
#define MSG_PREHEAT_2_N MSG_PREHEAT_2 _UxGT(" ")
#define MSG_PREHEAT_2_ALL MSG_PREHEAT_2 _UxGT(" Todo")
#define MSG_PREHEAT_2_END MSG_PREHEAT_2 _UxGT(" End")
#define MSG_PREHEAT_2_BEDONLY MSG_PREHEAT_2 _UxGT(" Cama")
#define MSG_PREHEAT_2_SETTINGS MSG_PREHEAT_2 _UxGT(" Config")
#define MSG_COOLDOWN _UxGT("Enfriar")
#define MSG_SWITCH_PS_ON _UxGT("Encender")
#define MSG_SWITCH_PS_OFF _UxGT("Apagar")
#define MSG_EXTRUDE _UxGT("Extruir")
#define MSG_RETRACT _UxGT("Retraer")
#define MSG_MOVE_AXIS _UxGT("Mover ejes")
#define MSG_BED_LEVELING _UxGT("Nivelar cama")
#define MSG_LEVEL_BED _UxGT("Nivelar cama")
#define MSG_MOVING _UxGT("Moviendo...")
#define MSG_FREE_XY _UxGT("Libre XY")
#define MSG_MOVE_X _UxGT("Mover X")
#define MSG_MOVE_Y _UxGT("Mover Y")
#define MSG_MOVE_Z _UxGT("Mover Z")
#define MSG_MOVE_E _UxGT("Extrusor")
#define MSG_MOVE_01MM _UxGT("Mover 0.1mm")
#define MSG_MOVE_1MM _UxGT("Mover 1mm")
#define MSG_MOVE_10MM _UxGT("Mover 10mm")
#define MSG_SPEED _UxGT("Velocidad")
#define MSG_BED_Z _UxGT("Cama Z")
#define MSG_NOZZLE _UxGT("Boquilla")
#define MSG_BED _UxGT("Cama")
#define MSG_FAN_SPEED _UxGT("Ventilador")
#define MSG_FLOW _UxGT("Flujo")
#define MSG_CONTROL _UxGT("Control")
#define MSG_MIN _UxGT(" ") LCD_STR_THERMOMETER _UxGT(" Min")
#define MSG_MAX _UxGT(" ") LCD_STR_THERMOMETER _UxGT(" Max")
#define MSG_FACTOR _UxGT(" ") LCD_STR_THERMOMETER _UxGT(" Fact")
#define MSG_AUTOTEMP _UxGT("Temperatura Auto.")
#define MSG_ON _UxGT("Encender")
#define MSG_OFF _UxGT("Apagar")
#define MSG_PID_P _UxGT("PID-P")
#define MSG_PID_I _UxGT("PID-I")
#define MSG_PID_D _UxGT("PID-D")
#define MSG_PID_C _UxGT("PID-C")
#define MSG_SELECT _UxGT("Seleccionar")
#define MSG_ACC _UxGT("Aceleración")
#define MSG_JERK _UxGT("Jerk")
#define MSG_VX_JERK _UxGT("Vx-jerk")
#define MSG_VY_JERK _UxGT("Vy-jerk")
#define MSG_VZ_JERK _UxGT("Vz-jerk")
#define MSG_VE_JERK _UxGT("Ve-jerk")
#define MSG_VMAX _UxGT("Vmax")
#define MSG_VMIN _UxGT("Vmin")
#define MSG_VTRAV_MIN _UxGT("Vel. viaje min")
#define MSG_ACCELERATION MSG_ACC
#define MSG_AMAX _UxGT("Acel. max")
#define MSG_A_RETRACT _UxGT("Acel. retrac.")
#define MSG_A_TRAVEL _UxGT("Acel. Viaje")
#define MSG_STEPS_PER_MM _UxGT("Pasos/mm")
#if IS_SCARA
#define MSG_ASTEPS _UxGT("A pasos/mm")
#define MSG_BSTEPS _UxGT("B pasos/mm")
#define MSG_CSTEPS _UxGT("Z pasos/mm")
#elif IS_DELTA
#define MSG_ASTEPS _UxGT("A pasos/mm")
#define MSG_BSTEPS _UxGT("B pasos/mm")
#define MSG_CSTEPS _UxGT("C pasos/mm")
#else
#define MSG_ASTEPS _UxGT("X pasos/mm")
#define MSG_BSTEPS _UxGT("Y pasos/mm")
#define MSG_CSTEPS _UxGT("Z pasos/mm")
#endif
#define MSG_ESTEPS _UxGT("E pasos/mm")
#define MSG_E1STEPS _UxGT("E1 pasos/mm")
#define MSG_E2STEPS _UxGT("E2 pasos/mm")
#define MSG_E3STEPS _UxGT("E3 pasos/mm")
#define MSG_E4STEPS _UxGT("E4 pasos/mm")
#define MSG_E5STEPS _UxGT("E5 pasos/mm")
#define MSG_TEMPERATURE _UxGT("Temperatura")
#define MSG_MOTION _UxGT("Movimiento")
#define MSG_FILAMENT _UxGT("Filamento")
#define MSG_VOLUMETRIC_ENABLED _UxGT("E in mm3")
#define MSG_FILAMENT_DIAM _UxGT("Fil. Dia.")
#define MSG_ADVANCE_K _UxGT("Avance K")
#define MSG_CONTRAST _UxGT("Contraste")
#define MSG_STORE_EEPROM _UxGT("Guardar memoria")
#define MSG_LOAD_EEPROM _UxGT("Cargar memoria")
#define MSG_RESTORE_FAILSAFE _UxGT("Restaurar memoria")
#define MSG_REFRESH _UxGT("Volver a cargar")
#define MSG_WATCH _UxGT("Información")
#define MSG_PREPARE _UxGT("Preparar")
#define MSG_TUNE _UxGT("Ajustar")
#define MSG_PAUSE_PRINT _UxGT("Pausar impresión")
#define MSG_RESUME_PRINT _UxGT("Reanudar impresión")
#define MSG_STOP_PRINT _UxGT("Detener impresión")
#define MSG_CARD_MENU _UxGT("Menú de SD")
#define MSG_NO_CARD _UxGT("No hay tarjeta SD")
#define MSG_DWELL _UxGT("Reposo...")
#define MSG_USERWAIT _UxGT("Esperando órdenes")
#define MSG_PRINT_ABORTED _UxGT("Impresión cancelada")
#define MSG_NO_MOVE _UxGT("Sin movimiento")
#define MSG_KILLED _UxGT("Parada de emergencia")
#define MSG_STOPPED _UxGT("Detenida")
#define MSG_CONTROL_RETRACT _UxGT("Retraer mm")
#define MSG_CONTROL_RETRACT_SWAP _UxGT("Interc. Retraer mm")
#define MSG_CONTROL_RETRACTF _UxGT("Retraer V")
#define MSG_CONTROL_RETRACT_ZLIFT _UxGT("Levantar mm")
#define MSG_CONTROL_RETRACT_RECOVER _UxGT("DesRet mm")
#define MSG_CONTROL_RETRACT_RECOVER_SWAP _UxGT("Interc. DesRet mm")
#define MSG_CONTROL_RETRACT_RECOVERF _UxGT("DesRet V")
#define MSG_AUTORETRACT _UxGT("Retracción Auto.")
#define MSG_FILAMENTCHANGE _UxGT("Cambiar filamento")
#define MSG_INIT_SDCARD _UxGT("Iniciando tarjeta")
#define MSG_CNG_SDCARD _UxGT("Cambiar tarjeta")
#define MSG_ZPROBE_OUT _UxGT("Sonda Z fuera")
#define MSG_BLTOUCH_SELFTEST _UxGT("BLTouch Auto-Prueba")
#define MSG_BLTOUCH_RESET _UxGT("Reiniciar BLTouch")
#define MSG_HOME _UxGT("Home") // Used as MSG_HOME " " MSG_X MSG_Y MSG_Z " " MSG_FIRST
#define MSG_FIRST _UxGT("primero")
#define MSG_ZPROBE_ZOFFSET _UxGT("Desfase Z")
#define MSG_BABYSTEP_X _UxGT("Micropaso X")
#define MSG_BABYSTEP_Y _UxGT("Micropaso Y")
#define MSG_BABYSTEP_Z _UxGT("Micropaso Z")
#define MSG_ENDSTOP_ABORT _UxGT("Cancelado - Endstop")
#define MSG_HEATING_FAILED_LCD _UxGT("Error: al calentar")
#define MSG_ERR_REDUNDANT_TEMP _UxGT("Error: temperatura")
#define MSG_THERMAL_RUNAWAY _UxGT("Error: temperatura")
#define MSG_ERR_MAXTEMP _UxGT("Error: Temp Máxima")
#define MSG_ERR_MINTEMP _UxGT("Error: Temp Mínima")
#define MSG_ERR_MAXTEMP_BED _UxGT("Error: Temp Max Cama")
#define MSG_ERR_MINTEMP_BED _UxGT("Error: Temp Min Cama")
#define MSG_ERR_Z_HOMING MSG_HOME _UxGT(" ") MSG_X MSG_Y _UxGT(" ") MSG_FIRST
#define MSG_HALTED _UxGT("IMPRESORA PARADA")
#define MSG_PLEASE_RESET _UxGT("Por favor, reinicie")
#define MSG_SHORT_DAY _UxGT("d") // One character only
#define MSG_SHORT_HOUR _UxGT("h") // One character only
#define MSG_SHORT_MINUTE _UxGT("m") // One character only
#define MSG_HEATING _UxGT("Calentando...")
#define MSG_BED_HEATING _UxGT("Calentando Cama...")
#define MSG_DELTA_CALIBRATE _UxGT("Calibración Delta")
#define MSG_DELTA_CALIBRATE_X _UxGT("Calibrar X")
#define MSG_DELTA_CALIBRATE_Y _UxGT("Calibrar Y")
#define MSG_DELTA_CALIBRATE_Z _UxGT("Calibrar Z")
#define MSG_DELTA_CALIBRATE_CENTER _UxGT("Calibrar Centro")
#define MSG_DELTA_AUTO_CALIBRATE _UxGT("Auto Calibración")
#define MSG_DELTA_HEIGHT_CALIBRATE _UxGT("Est. Altura Delta")
#define MSG_INFO_MENU _UxGT("Inf. Impresora")
#define MSG_INFO_PRINTER_MENU _UxGT("Inf. Impresora")
#define MSG_INFO_STATS_MENU _UxGT("Estadísticas Imp.")
#define MSG_INFO_BOARD_MENU _UxGT("Inf. Controlador")
#define MSG_INFO_THERMISTOR_MENU _UxGT("Termistores")
#define MSG_INFO_EXTRUDERS _UxGT("Extrusores")
#define MSG_INFO_BAUDRATE _UxGT("Baudios")
#define MSG_INFO_PROTOCOL _UxGT("Protocolo")
#define MSG_CASE_LIGHT _UxGT("Luz cabina")
#if LCD_WIDTH > 19
#define MSG_INFO_PRINT_COUNT _UxGT("Conteo de impresión")
#define MSG_INFO_COMPLETED_PRINTS _UxGT("Completadas")
#define MSG_INFO_PRINT_TIME _UxGT("Tiempo total de imp.")
#define MSG_INFO_PRINT_LONGEST _UxGT("Impresión más larga")
#define MSG_INFO_PRINT_FILAMENT _UxGT("Total de Extrusión")
#else
#define MSG_INFO_PRINT_COUNT _UxGT("Impresiones")
#define MSG_INFO_COMPLETED_PRINTS _UxGT("Completadas")
#define MSG_INFO_PRINT_TIME _UxGT("Total")
#define MSG_INFO_PRINT_LONGEST _UxGT("Más larga")
#define MSG_INFO_PRINT_FILAMENT _UxGT("Extrusión")
#endif
#define MSG_INFO_MIN_TEMP _UxGT("Temperatura mínima")
#define MSG_INFO_MAX_TEMP _UxGT("Temperatura máxima")
#define MSG_INFO_PSU _UxGT("Fuente de poder")
#define MSG_DRIVE_STRENGTH _UxGT("Potencia driver")
#define MSG_DAC_PERCENT _UxGT("Driver %")
#define MSG_DAC_EEPROM_WRITE _UxGT("Escribe DAC EEPROM")
#define MSG_FILAMENT_CHANGE_HEADER _UxGT("IMPR. PAUSADA")
#define MSG_FILAMENT_CHANGE_OPTION_HEADER _UxGT("OPC. REINICIO:")
#define MSG_FILAMENT_CHANGE_OPTION_EXTRUDE _UxGT("Extruir más")
#define MSG_FILAMENT_CHANGE_OPTION_RESUME _UxGT("Resumir imp.")
#define MSG_FILAMENT_CHANGE_MINTEMP _UxGT("Temp Mínima es ")
#define MSG_FILAMENT_CHANGE_NOZZLE _UxGT(" Boquilla: ")
#define MSG_FILAMENT_CHANGE_INIT_1 _UxGT("Esperando iniciar")
#define MSG_FILAMENT_CHANGE_INSERT_1 _UxGT("Inserte filamento")
#define MSG_FILAMENT_CHANGE_INSERT_2 _UxGT("y presione el botón")
#if LCD_HEIGHT >= 4
// Up to 3 lines allowed
#define MSG_FILAMENT_CHANGE_INIT_2 _UxGT("del filamento")
#define MSG_FILAMENT_CHANGE_INIT_3 _UxGT("cambiar")
#define MSG_FILAMENT_CHANGE_INSERT_3 _UxGT("para continuar...")
#else // LCD_HEIGHT < 4
// Up to 2 lines allowed
#define MSG_FILAMENT_CHANGE_INIT_2 _UxGT("del fil. cambiar")
#define MSG_FILAMENT_CHANGE_INSERT_1 _UxGT("Inserte filamento")
#endif // LCD_HEIGHT < 4
#define MSG_FILAMENT_CHANGE_UNLOAD_1 _UxGT("Esperado por")
#define MSG_FILAMENT_CHANGE_UNLOAD_2 _UxGT("filamento expulsado")
#define MSG_FILAMENT_CHANGE_LOAD_1 _UxGT("Esperado por")
#define MSG_FILAMENT_CHANGE_LOAD_2 _UxGT("Cargar filamento")
#define MSG_FILAMENT_CHANGE_EXTRUDE_1 _UxGT("Esperado por")
#define MSG_FILAMENT_CHANGE_EXTRUDE_2 _UxGT("Extruir filamento")
#define MSG_FILAMENT_CHANGE_RESUME_1 _UxGT("Esperando imp.")
#define MSG_FILAMENT_CHANGE_RESUME_2 _UxGT("para resumir")
#define MSG_FILAMENT_CHANGE_HEAT_1 _UxGT("Oprima botón para")
#define MSG_FILAMENT_CHANGE_HEAT_2 _UxGT("Calentar la boquilla")
#define MSG_FILAMENT_CHANGE_HEATING_1 _UxGT("Calentando boquilla")
#define MSG_FILAMENT_CHANGE_HEATING_2 _UxGT("Espere por favor")
#endif // LANGUAGE_ES_UTF_H

View File

@@ -1,496 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* malyanlcd.cpp
*
* LCD implementation for Malyan's LCD, a separate ESP8266 MCU running
* on Serial1 for the M200 board. This module outputs a pseudo-gcode
* wrapped in curly braces which the LCD implementation translates into
* actual G-code commands.
*
* Added to Marlin for Mini/Malyan M200
* Unknown commands as of Jan 2018: {H:}
* Not currently implemented:
* {E:} when sent by LCD. Meaning unknown.
*
* Notes for connecting to boards that are not Malyan:
* The LCD is 3.3v, so if powering from a RAMPS 1.4 board or
* other 5v/12v board, use a buck converter to power the LCD and
* the 3.3v side of a logic level shifter. Aux1 on the RAMPS board
* has Serial1 and 12v, making it perfect for this.
* Copyright (c) 2017 Jason Nelson (xC0000005)
*/
#include "MarlinConfig.h"
#if ENABLED(MALYAN_LCD)
#if ENABLED(SDSUPPORT)
#include "cardreader.h"
#include "SdFatConfig.h"
#else
#define LONG_FILENAME_LENGTH 0
#endif
#include "temperature.h"
#include "planner.h"
#include "stepper.h"
#include "duration_t.h"
#include "printcounter.h"
#include "parser.h"
#include "configuration_store.h"
#include "Marlin.h"
#if USE_MARLINSERIAL
// Make an exception to use HardwareSerial too
#undef HardwareSerial_h
#include <HardwareSerial.h>
#define USB_STATUS true
#else
#define USB_STATUS Serial
#endif
// On the Malyan M200, this will be Serial1. On a RAMPS board,
// it might not be.
#define LCD_SERIAL Serial1
// This is based on longest sys command + a filename, plus some buffer
// in case we encounter some data we don't recognize
// There is no evidence a line will ever be this long, but better safe than sorry
#define MAX_CURLY_COMMAND (32 + LONG_FILENAME_LENGTH) * 2
// Track incoming command bytes from the LCD
int inbound_count;
// For sending print completion messages
bool last_printing_status = false;
// Everything written needs the high bit set.
void write_to_lcd_P(const char * const message) {
char encoded_message[MAX_CURLY_COMMAND];
uint8_t message_length = MIN(strlen_P(message), sizeof(encoded_message));
for (uint8_t i = 0; i < message_length; i++)
encoded_message[i] = pgm_read_byte(&message[i]) | 0x80;
LCD_SERIAL.Print::write(encoded_message, message_length);
}
void write_to_lcd(const char * const message) {
char encoded_message[MAX_CURLY_COMMAND];
const uint8_t message_length = MIN(strlen(message), sizeof(encoded_message));
for (uint8_t i = 0; i < message_length; i++)
encoded_message[i] = message[i] | 0x80;
LCD_SERIAL.Print::write(encoded_message, message_length);
}
/**
* Process an LCD 'C' command.
* These are currently all temperature commands
* {C:T0190}
* Set temp for hotend to 190
* {C:P050}
* Set temp for bed to 50
*
* {C:S09} set feedrate to 90 %.
* {C:S12} set feedrate to 120 %.
*
* the command portion begins after the :
*/
void process_lcd_c_command(const char* command) {
switch (command[0]) {
case 'C': {
int raw_feedrate = atoi(command + 1);
feedrate_percentage = raw_feedrate * 10;
feedrate_percentage = constrain(feedrate_percentage, 10, 999);
} break;
case 'T': {
thermalManager.setTargetHotend(atoi(command + 1), 0);
} break;
case 'P': {
thermalManager.setTargetBed(atoi(command + 1));
} break;
default:
SERIAL_ECHOLNPAIR("UNKNOWN C COMMAND", command);
return;
}
}
/**
* Process an LCD 'B' command.
* {B:0} results in: {T0:008/195}{T1:000/000}{TP:000/000}{TQ:000C}{TT:000000}
* T0/T1 are hot end temperatures, TP is bed, TQ is percent, and TT is probably
* time remaining (HH:MM:SS). The UI can't handle displaying a second hotend,
* but the stock firmware always sends it, and it's always zero.
*/
void process_lcd_eb_command(const char* command) {
char elapsed_buffer[10];
duration_t elapsed;
switch (command[0]) {
case '0': {
elapsed = print_job_timer.duration();
sprintf_P(elapsed_buffer, PSTR("%02u%02u%02u"), uint16_t(elapsed.hour()), uint16_t(elapsed.minute()) % 60UL, elapsed.second());
char message_buffer[MAX_CURLY_COMMAND];
sprintf_P(message_buffer,
PSTR("{T0:%03.0f/%03i}{T1:000/000}{TP:%03.0f/%03i}{TQ:%03i}{TT:%s}"),
thermalManager.degHotend(0),
thermalManager.degTargetHotend(0),
#if HAS_HEATED_BED
thermalManager.degBed(),
thermalManager.degTargetBed(),
#else
0, 0,
#endif
#if ENABLED(SDSUPPORT)
card.percentDone(),
#else
0,
#endif
elapsed_buffer);
write_to_lcd(message_buffer);
} break;
default:
SERIAL_ECHOLNPAIR("UNKNOWN E/B COMMAND", command);
return;
}
}
/**
* Process an LCD 'J' command.
* These are currently all movement commands.
* The command portion begins after the :
* Move X Axis
*
* {J:E}{J:X-200}{J:E}
* {J:E}{J:X+200}{J:E}
* X, Y, Z, A (extruder)
*/
void process_lcd_j_command(const char* command) {
static bool steppers_enabled = false;
char axis = command[0];
switch (axis) {
case 'E':
// enable or disable steppers
// switch to relative
enqueue_and_echo_commands_now_P(PSTR("G91"));
enqueue_and_echo_commands_now_P(steppers_enabled ? PSTR("M18") : PSTR("M17"));
steppers_enabled = !steppers_enabled;
break;
case 'A':
axis = 'E';
// fallthru
case 'Y':
case 'Z':
case 'X': {
// G0 <AXIS><distance>
// The M200 class UI seems to send movement in .1mm values.
char cmd[20];
sprintf_P(cmd, PSTR("G1 %c%03.1f"), axis, atof(command + 1) / 10.0);
enqueue_and_echo_command_now(cmd);
} break;
default:
SERIAL_ECHOLNPAIR("UNKNOWN J COMMAND", command);
return;
}
}
/**
* Process an LCD 'P' command, related to homing and printing.
* Cancel:
* {P:X}
*
* Home all axes:
* {P:H}
*
* Print a file:
* {P:000}
* The File number is specified as a three digit value.
* Printer responds with:
* {PRINTFILE:Mini_SNES_Bottom.gcode}
* {SYS:BUILD}echo:Now fresh file: Mini_SNES_Bottom.gcode
* File opened: Mini_SNES_Bottom.gcode Size: 5805813
* File selected
* {SYS:BUILD}
* T:-2526.8 E:0
* T:-2533.0 E:0
* T:-2537.4 E:0
* Note only the curly brace stuff matters.
*/
void process_lcd_p_command(const char* command) {
switch (command[0]) {
case 'X':
#if ENABLED(SDSUPPORT)
// cancel print
write_to_lcd_P(PSTR("{SYS:CANCELING}"));
last_printing_status = false;
card.stopSDPrint(
#if SD_RESORT
true
#endif
);
clear_command_queue();
quickstop_stepper();
print_job_timer.stop();
thermalManager.disable_all_heaters();
#if FAN_COUNT > 0
for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
#endif
wait_for_heatup = false;
write_to_lcd_P(PSTR("{SYS:STARTED}"));
#endif
break;
case 'H':
// Home all axis
enqueue_and_echo_commands_now_P(PSTR("G28"));
break;
default: {
#if ENABLED(SDSUPPORT)
// Print file 000 - a three digit number indicating which
// file to print in the SD card. If it's a directory,
// then switch to the directory.
// Find the name of the file to print.
// It's needed to echo the PRINTFILE option.
// The {S:L} command should've ensured the SD card was mounted.
card.getfilename(atoi(command));
// There may be a difference in how V1 and V2 LCDs handle subdirectory
// prints. Investigate more. This matches the V1 motion controller actions
// but the V2 LCD switches to "print" mode on {SYS:DIR} response.
if (card.filenameIsDir) {
card.chdir(card.filename);
write_to_lcd_P(PSTR("{SYS:DIR}"));
}
else {
char message_buffer[MAX_CURLY_COMMAND];
sprintf_P(message_buffer, PSTR("{PRINTFILE:%s}"), card.longest_filename());
write_to_lcd(message_buffer);
write_to_lcd_P(PSTR("{SYS:BUILD}"));
card.openAndPrintFile(card.filename);
}
#endif
} break; // default
} // switch
}
/**
* Handle an lcd 'S' command
* {S:I} - Temperature request
* {T0:999/000}{T1:000/000}{TP:004/000}
*
* {S:L} - File Listing request
* Printer Response:
* {FILE:buttons.gcode}
* {FILE:update.bin}
* {FILE:nupdate.bin}
* {FILE:fcupdate.flg}
* {SYS:OK}
*/
void process_lcd_s_command(const char* command) {
switch (command[0]) {
case 'I': {
// temperature information
char message_buffer[MAX_CURLY_COMMAND];
sprintf_P(message_buffer, PSTR("{T0:%03.0f/%03i}{T1:000/000}{TP:%03.0f/%03i}"),
thermalManager.degHotend(0), thermalManager.degTargetHotend(0),
#if HAS_HEATED_BED
thermalManager.degBed(), thermalManager.degTargetBed()
#else
0, 0
#endif
);
write_to_lcd(message_buffer);
} break;
case 'H':
// Home all axis
enqueue_and_echo_command("G28");
break;
case 'L': {
#if ENABLED(SDSUPPORT)
if (!card.cardOK) card.initsd();
// A more efficient way to do this would be to
// implement a callback in the ls_SerialPrint code, but
// that requires changes to the core cardreader class that
// would not benefit the majority of users. Since one can't
// select a file for printing during a print, there's
// little reason not to do it this way.
char message_buffer[MAX_CURLY_COMMAND];
uint16_t file_count = card.get_num_Files();
for (uint16_t i = 0; i < file_count; i++) {
card.getfilename(i);
sprintf_P(message_buffer, card.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.longest_filename());
write_to_lcd(message_buffer);
}
write_to_lcd_P(PSTR("{SYS:OK}"));
#endif
} break;
default:
SERIAL_ECHOLNPAIR("UNKNOWN S COMMAND", command);
return;
}
}
/**
* Receive a curly brace command and translate to G-code.
* Currently {E:0} is not handled. Its function is unknown,
* but it occurs during the temp window after a sys build.
*/
void process_lcd_command(const char* command) {
const char *current = command;
current++; // skip the leading {. The trailing one is already gone.
byte command_code = *current++;
if (*current != ':') {
SERIAL_ECHOLNPAIR("UNKNOWN COMMAND FORMAT", command);
return;
}
current++; // skip the :
switch (command_code) {
case 'S':
process_lcd_s_command(current);
break;
case 'J':
process_lcd_j_command(current);
break;
case 'P':
process_lcd_p_command(current);
break;
case 'C':
process_lcd_c_command(current);
break;
case 'B':
case 'E':
process_lcd_eb_command(current);
break;
default:
SERIAL_ECHOLNPAIR("UNKNOWN COMMAND", command);
return;
}
}
/**
* UC means connected.
* UD means disconnected
* The stock firmware considers USB initialized as "connected."
*/
void update_usb_status(const bool forceUpdate) {
static bool last_usb_connected_status = false;
// This is mildly different than stock, which
// appears to use the usb discovery status.
// This is more logical.
if (last_usb_connected_status != USB_STATUS || forceUpdate) {
last_usb_connected_status = USB_STATUS;
write_to_lcd_P(last_usb_connected_status ? PSTR("{R:UC}\r\n") : PSTR("{R:UD}\r\n"));
}
}
/**
* - from printer on startup:
* {SYS:STARTED}{VER:29}{SYS:STARTED}{R:UD}
* The optimize attribute fixes a register Compile
* error for amtel.
*/
void _O2 lcd_update() {
static char inbound_buffer[MAX_CURLY_COMMAND];
// First report USB status.
update_usb_status(false);
// now drain commands...
while (LCD_SERIAL.available()) {
const byte b = (byte)LCD_SERIAL.read() & 0x7F;
inbound_buffer[inbound_count++] = b;
if (b == '}' || inbound_count == sizeof(inbound_buffer) - 1) {
inbound_buffer[inbound_count - 1] = '\0';
process_lcd_command(inbound_buffer);
inbound_count = 0;
inbound_buffer[0] = 0;
}
}
#if ENABLED(SDSUPPORT)
// The way last printing status works is simple:
// The UI needs to see at least one TQ which is not 100%
// and then when the print is complete, one which is.
static uint8_t last_percent_done = 100;
// If there was a print in progress, we need to emit the final
// print status as {TQ:100}. Reset last percent done so a new print will
// issue a percent of 0.
const uint8_t percent_done = card.sdprinting ? card.percentDone() : last_printing_status ? 100 : 0;
if (percent_done != last_percent_done) {
char message_buffer[10];
sprintf_P(message_buffer, PSTR("{TQ:%03i}"), percent_done);
write_to_lcd(message_buffer);
last_percent_done = percent_done;
last_printing_status = card.sdprinting;
}
#endif
}
/**
* The Malyan LCD actually runs as a separate MCU on Serial 1.
* This code's job is to siphon the weird curly-brace commands from
* it and translate into gcode, which then gets injected into
* the command queue where possible.
*/
void lcd_init() {
inbound_count = 0;
LCD_SERIAL.begin(500000);
// Signal init
write_to_lcd_P(PSTR("{SYS:STARTED}\r\n"));
// send a version that says "unsupported"
write_to_lcd_P(PSTR("{VER:99}\r\n"));
// No idea why it does this twice.
write_to_lcd_P(PSTR("{SYS:STARTED}\r\n"));
update_usb_status(true);
}
/**
* Set an alert.
*/
void lcd_setalertstatusPGM(const char* message) {
char message_buffer[MAX_CURLY_COMMAND];
sprintf_P(message_buffer, PSTR("{E:%s}"), message);
write_to_lcd(message_buffer);
}
#endif // MALYAN_LCD

View File

@@ -1,302 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* parser.cpp - Parser for a GCode line, providing a parameter interface.
*/
#include "parser.h"
#include "Marlin.h"
#include "language.h"
// Must be declared for allocation and to satisfy the linker
// Zero values need no initialization.
bool GCodeParser::volumetric_enabled;
#if ENABLED(INCH_MODE_SUPPORT)
float GCodeParser::linear_unit_factor, GCodeParser::volumetric_unit_factor;
#endif
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
TempUnit GCodeParser::input_temp_units;
#endif
char *GCodeParser::command_ptr,
*GCodeParser::string_arg,
*GCodeParser::value_ptr;
char GCodeParser::command_letter;
int GCodeParser::codenum;
#if USE_GCODE_SUBCODES
uint8_t GCodeParser::subcode;
#endif
#if ENABLED(FASTER_GCODE_PARSER)
// Optimized Parameters
uint32_t GCodeParser::codebits; // found bits
uint8_t GCodeParser::param[26]; // parameter offsets from command_ptr
#else
char *GCodeParser::command_args; // start of parameters
#endif
// Create a global instance of the GCode parser singleton
GCodeParser parser;
/**
* Clear all code-seen (and value pointers)
*
* Since each param is set/cleared on seen codes,
* this may be optimized by commenting out ZERO(param)
*/
void GCodeParser::reset() {
string_arg = NULL; // No whole line argument
command_letter = '?'; // No command letter
codenum = 0; // No command code
#if USE_GCODE_SUBCODES
subcode = 0; // No command sub-code
#endif
#if ENABLED(FASTER_GCODE_PARSER)
codebits = 0; // No codes yet
//ZERO(param); // No parameters (should be safe to comment out this line)
#endif
}
// Populate all fields by parsing a single line of GCode
// 58 bytes of SRAM are used to speed up seen/value
void GCodeParser::parse(char *p) {
reset(); // No codes to report
// Skip spaces
while (*p == ' ') ++p;
// Skip N[-0-9] if included in the command line
if (*p == 'N' && NUMERIC_SIGNED(p[1])) {
#if ENABLED(FASTER_GCODE_PARSER)
//set('N', p + 1); // (optional) Set the 'N' parameter value
#endif
p += 2; // skip N[-0-9]
while (NUMERIC(*p)) ++p; // skip [0-9]*
while (*p == ' ') ++p; // skip [ ]*
}
// *p now points to the current command, which should be G, M, or T
command_ptr = p;
// Get the command letter, which must be G, M, or T
const char letter = *p++;
// Nullify asterisk and trailing whitespace
char *starpos = strchr(p, '*');
if (starpos) {
--starpos; // *
while (*starpos == ' ') --starpos; // spaces...
starpos[1] = '\0';
}
// Bail if the letter is not G, M, or T
switch (letter) { case 'G': case 'M': case 'T': break; default: return; }
// Skip spaces to get the numeric part
while (*p == ' ') p++;
// Bail if there's no command code number
if (!NUMERIC(*p)) return;
// Save the command letter at this point
// A '?' signifies an unknown command
command_letter = letter;
// Get the code number - integer digits only
codenum = 0;
do {
codenum *= 10, codenum += *p++ - '0';
} while (NUMERIC(*p));
// Allow for decimal point in command
#if USE_GCODE_SUBCODES
if (*p == '.') {
p++;
while (NUMERIC(*p))
subcode *= 10, subcode += *p++ - '0';
}
#endif
// Skip all spaces to get to the first argument, or nul
while (*p == ' ') p++;
// The command parameters (if any) start here, for sure!
#if DISABLED(FASTER_GCODE_PARSER)
command_args = p; // Scan for parameters in seen()
#endif
// Only use string_arg for these M codes
if (letter == 'M') switch (codenum) { case 23: case 28: case 30: case 117: case 118: case 928: string_arg = p; return; default: break; }
#if ENABLED(DEBUG_GCODE_PARSER)
const bool debug = codenum == 800;
#endif
/**
* Find all parameters, set flags and pointers for fast parsing
*
* Most codes ignore 'string_arg', but those that want a string will get the right pointer.
* The following loop assigns the first "parameter" having no numeric value to 'string_arg'.
* This allows M0/M1 with expire time to work: "M0 S5 You Win!"
* For 'M118' you must use 'E1' and 'A1' rather than just 'E' or 'A'
*/
string_arg = NULL;
while (const char code = *p++) { // Get the next parameter. A NUL ends the loop
// Special handling for M32 [P] !/path/to/file.g#
// The path must be the last parameter
if (code == '!' && letter == 'M' && codenum == 32) {
string_arg = p; // Name starts after '!'
char * const lb = strchr(p, '#'); // Already seen '#' as SD char (to pause buffering)
if (lb) *lb = '\0'; // Safe to mark the end of the filename
return;
}
// Arguments MUST be uppercase for fast GCode parsing
#if ENABLED(FASTER_GCODE_PARSER)
#define PARAM_TEST WITHIN(code, 'A', 'Z')
#else
#define PARAM_TEST true
#endif
if (PARAM_TEST) {
while (*p == ' ') p++; // Skip spaces between parameters & values
const bool has_num = valid_float(p);
#if ENABLED(DEBUG_GCODE_PARSER)
if (debug) {
SERIAL_ECHOPAIR("Got letter ", code);
SERIAL_ECHOPAIR(" at index ", (int)(p - command_ptr - 1));
if (has_num) SERIAL_ECHOPGM(" (has_num)");
}
#endif
if (!has_num && !string_arg) { // No value? First time, keep as string_arg
string_arg = p - 1;
#if ENABLED(DEBUG_GCODE_PARSER)
if (debug) SERIAL_ECHOPAIR(" string_arg: ", hex_address((void*)string_arg)); // DEBUG
#endif
}
#if ENABLED(DEBUG_GCODE_PARSER)
if (debug) SERIAL_EOL();
#endif
#if ENABLED(FASTER_GCODE_PARSER)
set(code, has_num ? p : NULL); // Set parameter exists and pointer (NULL for no number)
#endif
}
else if (!string_arg) { // Not A-Z? First time, keep as the string_arg
string_arg = p - 1;
#if ENABLED(DEBUG_GCODE_PARSER)
if (debug) SERIAL_ECHOPAIR(" string_arg: ", hex_address((void*)string_arg)); // DEBUG
#endif
}
if (!WITHIN(*p, 'A', 'Z')) { // Another parameter right away?
while (*p && DECIMAL_SIGNED(*p)) p++; // Skip over the value section of a parameter
while (*p == ' ') p++; // Skip over all spaces
}
}
}
#if ENABLED(CNC_COORDINATE_SYSTEMS)
// Parse the next parameter as a new command
bool GCodeParser::chain() {
#if ENABLED(FASTER_GCODE_PARSER)
char *next_command = command_ptr;
if (next_command) {
while (*next_command && *next_command != ' ') ++next_command;
while (*next_command == ' ') ++next_command;
if (!*next_command) next_command = NULL;
}
#else
const char *next_command = command_args;
#endif
if (next_command) parse(next_command);
return !!next_command;
}
#endif // CNC_COORDINATE_SYSTEMS
void GCodeParser::unknown_command_error() {
SERIAL_ECHO_START();
SERIAL_ECHOPAIR(MSG_UNKNOWN_COMMAND, command_ptr);
SERIAL_CHAR('"');
SERIAL_EOL();
}
#if ENABLED(DEBUG_GCODE_PARSER)
void GCodeParser::debug() {
SERIAL_ECHOPAIR("Command: ", command_ptr);
SERIAL_ECHOPAIR(" (", command_letter);
SERIAL_ECHO(codenum);
SERIAL_ECHOLNPGM(")");
#if ENABLED(FASTER_GCODE_PARSER)
SERIAL_ECHOPGM(" args: \"");
for (char c = 'A'; c <= 'Z'; ++c)
if (seen(c)) { SERIAL_CHAR(c); SERIAL_CHAR(' '); }
#else
SERIAL_ECHOPAIR(" args: \"", command_args);
#endif
SERIAL_CHAR('"');
if (string_arg) {
SERIAL_ECHOPGM(" string: \"");
SERIAL_ECHO(string_arg);
SERIAL_CHAR('"');
}
SERIAL_ECHOPGM("\n\n");
for (char c = 'A'; c <= 'Z'; ++c) {
if (seen(c)) {
SERIAL_ECHOPAIR("Code '", c); SERIAL_ECHOPGM("':");
if (has_value()) {
SERIAL_ECHOPAIR("\n float: ", value_float());
SERIAL_ECHOPAIR("\n long: ", value_long());
SERIAL_ECHOPAIR("\n ulong: ", value_ulong());
SERIAL_ECHOPAIR("\n millis: ", value_millis());
SERIAL_ECHOPAIR("\n sec-ms: ", value_millis_from_seconds());
SERIAL_ECHOPAIR("\n int: ", value_int());
SERIAL_ECHOPAIR("\n ushort: ", value_ushort());
SERIAL_ECHOPAIR("\n byte: ", (int)value_byte());
SERIAL_ECHOPAIR("\n bool: ", (int)value_bool());
SERIAL_ECHOPAIR("\n linear: ", value_linear_units());
SERIAL_ECHOPAIR("\n celsius: ", value_celsius());
}
else
SERIAL_ECHOPGM(" (no value)");
SERIAL_ECHOPGM("\n\n");
}
}
}
#endif // DEBUG_GCODE_PARSER

View File

@@ -1,341 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* parser.h - Parser for a GCode line, providing a parameter interface.
* Codes like M149 control the way the GCode parser behaves,
* so settings for these codes are located in this class.
*/
#ifndef _PARSER_H_
#define _PARSER_H_
#include "enum.h"
#include "types.h"
#include "MarlinConfig.h"
//#define DEBUG_GCODE_PARSER
#if ENABLED(DEBUG_GCODE_PARSER)
#include "hex_print_routines.h"
#include "serial.h"
#endif
#define strtof strtod
/**
* GCode parser
*
* - Parse a single gcode line for its letter, code, subcode, and parameters
* - FASTER_GCODE_PARSER:
* - Flags existing params (1 bit each)
* - Stores value offsets (1 byte each)
* - Provide accessors for parameters:
* - Parameter exists
* - Parameter has value
* - Parameter value in different units and types
*/
class GCodeParser {
private:
static char *value_ptr; // Set by seen, used to fetch the value
#if ENABLED(FASTER_GCODE_PARSER)
static uint32_t codebits; // Parameters pre-scanned
static uint8_t param[26]; // For A-Z, offsets into command args
#else
static char *command_args; // Args start here, for slow scan
#endif
public:
// Global states for GCode-level units features
static bool volumetric_enabled;
#if ENABLED(INCH_MODE_SUPPORT)
static float linear_unit_factor, volumetric_unit_factor;
#endif
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
static TempUnit input_temp_units;
#endif
// Command line state
static char *command_ptr, // The command, so it can be echoed
*string_arg; // string of command line
static char command_letter; // G, M, or T
static int codenum; // 123
#if USE_GCODE_SUBCODES
static uint8_t subcode; // .1
#endif
#if ENABLED(DEBUG_GCODE_PARSER)
static void debug();
#endif
GCodeParser() {
#if ENABLED(INCH_MODE_SUPPORT)
set_input_linear_units(LINEARUNIT_MM);
#endif
}
// Reset is done before parsing
static void reset();
#define LETTER_BIT(N) ((N) - 'A')
FORCE_INLINE static bool valid_signless(const char * const p) {
return NUMERIC(p[0]) || (p[0] == '.' && NUMERIC(p[1])); // .?[0-9]
}
FORCE_INLINE static bool valid_float(const char * const p) {
return valid_signless(p) || ((p[0] == '-' || p[0] == '+') && valid_signless(&p[1])); // [-+]?.?[0-9]
}
#if ENABLED(FASTER_GCODE_PARSER)
FORCE_INLINE static bool valid_int(const char * const p) {
return NUMERIC(p[0]) || ((p[0] == '-' || p[0] == '+') && NUMERIC(p[1])); // [-+]?[0-9]
}
// Set the flag and pointer for a parameter
static void set(const char c, char * const ptr) {
const uint8_t ind = LETTER_BIT(c);
if (ind >= COUNT(param)) return; // Only A-Z
SBI32(codebits, ind); // parameter exists
param[ind] = ptr ? ptr - command_ptr : 0; // parameter offset or 0
#if ENABLED(DEBUG_GCODE_PARSER)
if (codenum == 800) {
SERIAL_ECHOPAIR("Set bit ", (int)ind);
SERIAL_ECHOPAIR(" of codebits (", hex_address((void*)(codebits >> 16)));
print_hex_word((uint16_t)(codebits & 0xFFFF));
SERIAL_ECHOLNPAIR(") | param = ", (int)param[ind]);
}
#endif
}
// Code seen bit was set. If not found, value_ptr is unchanged.
// This allows "if (seen('A')||seen('B'))" to use the last-found value.
static bool seen(const char c) {
const uint8_t ind = LETTER_BIT(c);
if (ind >= COUNT(param)) return false; // Only A-Z
const bool b = TEST32(codebits, ind);
if (b) {
#if ENABLED(DEBUG_GCODE_PARSER)
if (codenum == 800) {
SERIAL_CHAR('\''); SERIAL_CHAR(c); SERIAL_ECHOLNPGM("' is seen");
}
#endif
char * const ptr = command_ptr + param[ind];
value_ptr = param[ind] && valid_float(ptr) ? ptr : (char*)NULL;
}
return b;
}
static bool seen_any() { return !!codebits; }
#define SEEN_TEST(L) TEST32(codebits, LETTER_BIT(L))
#else // !FASTER_GCODE_PARSER
// Code is found in the string. If not found, value_ptr is unchanged.
// This allows "if (seen('A')||seen('B'))" to use the last-found value.
static bool seen(const char c) {
char *p = strchr(command_args, c);
const bool b = !!p;
if (b) value_ptr = valid_float(&p[1]) ? &p[1] : (char*)NULL;
return b;
}
static bool seen_any() { return *command_args == '\0'; }
#define SEEN_TEST(L) !!strchr(command_args, L)
#endif // !FASTER_GCODE_PARSER
// Seen any axis parameter
static bool seen_axis() {
return SEEN_TEST('X') || SEEN_TEST('Y') || SEEN_TEST('Z') || SEEN_TEST('E');
}
// Populate all fields by parsing a single line of GCode
// This uses 54 bytes of SRAM to speed up seen/value
static void parse(char * p);
#if ENABLED(CNC_COORDINATE_SYSTEMS)
// Parse the next parameter as a new command
static bool chain();
#endif
// The code value pointer was set
FORCE_INLINE static bool has_value() { return value_ptr != NULL; }
// Seen a parameter with a value
inline static bool seenval(const char c) { return seen(c) && has_value(); }
// Float removes 'E' to prevent scientific notation interpretation
inline static float value_float() {
if (value_ptr) {
char *e = value_ptr;
for (;;) {
const char c = *e;
if (c == '\0' || c == ' ') break;
if (c == 'E' || c == 'e') {
*e = '\0';
const float ret = strtof(value_ptr, NULL);
*e = c;
return ret;
}
++e;
}
return strtof(value_ptr, NULL);
}
return 0;
}
// Code value as a long or ulong
inline static int32_t value_long() { return value_ptr ? strtol(value_ptr, NULL, 10) : 0L; }
inline static uint32_t value_ulong() { return value_ptr ? strtoul(value_ptr, NULL, 10) : 0UL; }
// Code value for use as time
FORCE_INLINE static millis_t value_millis() { return value_ulong(); }
FORCE_INLINE static millis_t value_millis_from_seconds() { return value_float() * 1000UL; }
// Reduce to fewer bits
FORCE_INLINE static int16_t value_int() { return (int16_t)value_long(); }
FORCE_INLINE static uint16_t value_ushort() { return (uint16_t)value_long(); }
inline static uint8_t value_byte() { return (uint8_t)constrain(value_long(), 0, 255); }
// Bool is true with no value or non-zero
inline static bool value_bool() { return !has_value() || !!value_byte(); }
// Units modes: Inches, Fahrenheit, Kelvin
#if ENABLED(INCH_MODE_SUPPORT)
inline static void set_input_linear_units(const LinearUnit units) {
switch (units) {
case LINEARUNIT_INCH:
linear_unit_factor = 25.4;
break;
case LINEARUNIT_MM:
default:
linear_unit_factor = 1.0;
break;
}
volumetric_unit_factor = POW(linear_unit_factor, 3.0);
}
inline static float axis_unit_factor(const AxisEnum axis) {
return (axis >= E_AXIS && volumetric_enabled ? volumetric_unit_factor : linear_unit_factor);
}
inline static float value_linear_units() { return value_float() * linear_unit_factor; }
inline static float value_axis_units(const AxisEnum axis) { return value_float() * axis_unit_factor(axis); }
inline static float value_per_axis_unit(const AxisEnum axis) { return value_float() / axis_unit_factor(axis); }
#else
FORCE_INLINE static float value_linear_units() { return value_float(); }
FORCE_INLINE static float value_axis_units(const AxisEnum a) { UNUSED(a); return value_float(); }
FORCE_INLINE static float value_per_axis_unit(const AxisEnum a) { UNUSED(a); return value_float(); }
#endif
#if ENABLED(TEMPERATURE_UNITS_SUPPORT)
inline static void set_input_temp_units(TempUnit units) { input_temp_units = units; }
#if ENABLED(ULTIPANEL) && DISABLED(DISABLE_M503)
FORCE_INLINE static char temp_units_code() {
return input_temp_units == TEMPUNIT_K ? 'K' : input_temp_units == TEMPUNIT_F ? 'F' : 'C';
}
FORCE_INLINE static const char* temp_units_name() {
return input_temp_units == TEMPUNIT_K ? PSTR("Kelvin") : input_temp_units == TEMPUNIT_F ? PSTR("Fahrenheit") : PSTR("Celsius");
}
inline static float to_temp_units(const float &f) {
switch (input_temp_units) {
case TEMPUNIT_F:
return f * 0.5555555556 + 32.0;
case TEMPUNIT_K:
return f + 273.15;
case TEMPUNIT_C:
default:
return f;
}
}
#endif // ULTIPANEL && !DISABLE_M503
inline static float value_celsius() {
const float f = value_float();
switch (input_temp_units) {
case TEMPUNIT_F:
return (f - 32.0) * 0.5555555556;
case TEMPUNIT_K:
return f - 273.15;
case TEMPUNIT_C:
default:
return f;
}
}
inline static float value_celsius_diff() {
switch (input_temp_units) {
case TEMPUNIT_F:
return value_float() * 0.5555555556;
case TEMPUNIT_C:
case TEMPUNIT_K:
default:
return value_float();
}
}
#else // !TEMPERATURE_UNITS_SUPPORT
FORCE_INLINE static float value_celsius() { return value_float(); }
FORCE_INLINE static float value_celsius_diff() { return value_float(); }
#endif // !TEMPERATURE_UNITS_SUPPORT
FORCE_INLINE static float value_feedrate() { return value_linear_units(); }
void unknown_command_error();
// Provide simple value accessors with default option
FORCE_INLINE static float floatval(const char c, const float dval=0.0) { return seenval(c) ? value_float() : dval; }
FORCE_INLINE static bool boolval(const char c, const bool dval=false) { return seenval(c) ? value_bool() : (seen(c) ? true : dval); }
FORCE_INLINE static uint8_t byteval(const char c, const uint8_t dval=0) { return seenval(c) ? value_byte() : dval; }
FORCE_INLINE static int16_t intval(const char c, const int16_t dval=0) { return seenval(c) ? value_int() : dval; }
FORCE_INLINE static uint16_t ushortval(const char c, const uint16_t dval=0) { return seenval(c) ? value_ushort() : dval; }
FORCE_INLINE static int32_t longval(const char c, const int32_t dval=0) { return seenval(c) ? value_long() : dval; }
FORCE_INLINE static uint32_t ulongval(const char c, const uint32_t dval=0) { return seenval(c) ? value_ulong() : dval; }
FORCE_INLINE static float linearval(const char c, const float dval=0.0) { return seenval(c) ? value_linear_units() : dval; }
FORCE_INLINE static float celsiusval(const char c, const float dval=0.0) { return seenval(c) ? value_celsius() : dval; }
};
extern GCodeParser parser;
#endif // _PARSER_H_

View File

@@ -1,179 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Einsy-Rambo pin assignments
*/
#ifndef __AVR_ATmega2560__
#error "Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu."
#endif
#define BOARD_NAME "Einsy Rambo"
//
// TMC2130 Configuration_adv defaults for EinsyRambo
//
#if !AXIS_DRIVER_TYPE(X, TMC2130) || !AXIS_DRIVER_TYPE(Y, TMC2130) || !AXIS_DRIVER_TYPE(Z, TMC2130) || !AXIS_DRIVER_TYPE(E0, TMC2130)
#error "You must set ([XYZ]|E0)_DRIVER_TYPE to TMC2130 in Configuration.h for EinsyRambo."
#endif
// TMC2130 Diag Pins (currently just for reference)
#define X_DIAG_PIN 64
#define Y_DIAG_PIN 69
#define Z_DIAG_PIN 68
#define E0_DIAG_PIN 65
//
// Limit Switches
//
// Only use Diag Pins when SENSORLESS_HOMING is enabled for the TMC2130 drivers.
// Otherwise use a physical endstop based configuration.
//
// SERVO0_PIN and Z_MIN_PIN configuration for BLTOUCH sensor when combined with SENSORLESS_HOMING.
//
#if DISABLED(SENSORLESS_HOMING)
#define X_STOP_PIN 12
#define Y_STOP_PIN 11
#define Z_STOP_PIN 10
#else
#define X_STOP_PIN X_DIAG_PIN
#define Y_STOP_PIN Y_DIAG_PIN
#if ENABLED(BLTOUCH)
#define Z_STOP_PIN 11 // Y-MIN
#define SERVO0_PIN 10 // Z-MIN
#else
#define Z_STOP_PIN 10
#endif
#endif
//
// Z Probe (when not Z_MIN_PIN)
//
#ifndef Z_MIN_PROBE_PIN
#define Z_MIN_PROBE_PIN 10
#endif
//
// Steppers
//
#define X_STEP_PIN 37
#define X_DIR_PIN 49
#define X_ENABLE_PIN 29
#define X_CS_PIN 41
#define Y_STEP_PIN 36
#define Y_DIR_PIN 48
#define Y_ENABLE_PIN 28
#define Y_CS_PIN 39
#define Z_STEP_PIN 35
#define Z_DIR_PIN 47
#define Z_ENABLE_PIN 27
#define Z_CS_PIN 67
#define E0_STEP_PIN 34
#define E0_DIR_PIN 43
#define E0_ENABLE_PIN 26
#define E0_CS_PIN 66
//
// Temperature Sensors
//
#define TEMP_0_PIN 0 // Analog Input
#define TEMP_1_PIN 1 // Analog Input
#define TEMP_BED_PIN 2 // Analog Input
//
// Heaters / Fans
//
#define HEATER_0_PIN 3
#define HEATER_BED_PIN 4
#ifndef FAN_PIN
#define FAN_PIN 8
#endif
#ifndef FAN1_PIN
#define FAN1_PIN 6
#endif
//
// Misc. Functions
//
#define SDSS 77
#define LED_PIN 13
#define CASE_LIGHT_PIN 9
//
// M3/M4/M5 - Spindle/Laser Control
//
// use P1 connector for spindle pins
#define SPINDLE_LASER_PWM_PIN 9 // MUST BE HARDWARE PWM
#define SPINDLE_LASER_ENABLE_PIN 18 // Pin should have a pullup!
#define SPINDLE_DIR_PIN 19
//
// Průša i3 MK2 Multiplexer Support
//
#define E_MUX0_PIN 17
#define E_MUX1_PIN 16
#define E_MUX2_PIN 78 // 84 in MK2 Firmware, with BEEPER as 78
//
// LCD / Controller
//
#if ENABLED(ULTRA_LCD)
#define KILL_PIN 32
#if ENABLED(NEWPANEL)
#if ENABLED(CR10_STOCKDISPLAY)
#define LCD_PINS_RS 85
#define LCD_PINS_ENABLE 71
#define LCD_PINS_D4 70
#define BTN_EN1 61
#define BTN_EN2 59
#else
#define LCD_PINS_RS 82
#define LCD_PINS_ENABLE 61
#define LCD_PINS_D4 59
#define LCD_PINS_D5 70
#define LCD_PINS_D6 85
#define LCD_PINS_D7 71
#define BTN_EN1 14
#define BTN_EN2 72
#endif
#define BTN_ENC 9 // AUX-2
#define BEEPER_PIN 84 // AUX-4
#define SD_DETECT_PIN 15
#endif // NEWPANEL
#endif // ULTRA_LCD

View File

@@ -1,193 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Einsy-Retro pin assignments
*/
#ifndef __AVR_ATmega2560__
#error "Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu."
#endif
#define BOARD_NAME "Einsy Retro"
//
// TMC2130 Configuration_adv defaults for EinsyRetro
//
#if !AXIS_DRIVER_TYPE(X, TMC2130) || !AXIS_DRIVER_TYPE(Y, TMC2130) || !AXIS_DRIVER_TYPE(Z, TMC2130) || !AXIS_DRIVER_TYPE(E0, TMC2130)
#error "You must set ([XYZ]|E0)_DRIVER_TYPE to TMC2130 in Configuration.h for EinsyRetro."
#endif
// TMC2130 Diag Pins (currently just for reference)
#define X_DIAG_PIN 64
#define Y_DIAG_PIN 69
#define Z_DIAG_PIN 68
#define E0_DIAG_PIN 65
//
// Limit Switches
//
// Only use Diag Pins when SENSORLESS_HOMING is enabled for the TMC2130 drivers.
// Otherwise use a physical endstop based configuration.
//
// SERVO0_PIN and Z_MIN_PIN configuration for BLTOUCH sensor when combined with SENSORLESS_HOMING.
//
#if DISABLED(SENSORLESS_HOMING)
#define X_MIN_PIN 12
#define Y_MIN_PIN 11
#define Z_MIN_PIN 10
#define X_MAX_PIN 81
#define Y_MAX_PIN 57
#else
#if X_HOME_DIR == -1
#define X_MIN_PIN X_DIAG_PIN
#define X_MAX_PIN 81
#else
#define X_MIN_PIN 12
#define X_MAX_PIN X_DIAG_PIN
#endif
#if Y_HOME_DIR == -1
#define Y_MIN_PIN Y_DIAG_PIN
#define Y_MAX_PIN 57
#else
#define Y_MIN_PIN 11
#define Y_MAX_PIN Y_DIAG_PIN
#endif
#if ENABLED(BLTOUCH)
#define Z_MIN_PIN 11 // Y-MIN
#define SERVO0_PIN 10 // Z-MIN
#else
#define Z_MIN_PIN 10
#endif
#endif
#define Z_MAX_PIN 7
//
// Z Probe (when not Z_MIN_PIN)
//
#ifndef Z_MIN_PROBE_PIN
#define Z_MIN_PROBE_PIN 10
#endif
//
// Steppers
//
#define X_STEP_PIN 37
#define X_DIR_PIN 49
#define X_ENABLE_PIN 29
#define X_CS_PIN 41
#define Y_STEP_PIN 36
#define Y_DIR_PIN 48
#define Y_ENABLE_PIN 28
#define Y_CS_PIN 39
#define Z_STEP_PIN 35
#define Z_DIR_PIN 47
#define Z_ENABLE_PIN 27
#define Z_CS_PIN 67
#define E0_STEP_PIN 34
#define E0_DIR_PIN 43
#define E0_ENABLE_PIN 26
#define E0_CS_PIN 66
//
// Temperature Sensors
//
#define TEMP_0_PIN 0 // Analog Input
#define TEMP_1_PIN 1 // Analog Input
#define TEMP_BED_PIN 2 // Analog Input
//
// Heaters / Fans
//
#define HEATER_0_PIN 3
#define HEATER_BED_PIN 4
#ifndef FAN_PIN
#define FAN_PIN 8
#endif
#define FAN1_PIN 6
//
// Misc. Functions
//
#define SDSS 53
#define LED_PIN 13
#define CASE_LIGHT_PIN 9
//
// M3/M4/M5 - Spindle/Laser Control
//
// use P1 connector for spindle pins
#define SPINDLE_LASER_PWM_PIN 9 // MUST BE HARDWARE PWM
#define SPINDLE_LASER_ENABLE_PIN 18 // Pin should have a pullup!
#define SPINDLE_DIR_PIN 19
//
// Průša i3 MK2 Multiplexer Support
//
#define E_MUX0_PIN 17
#define E_MUX1_PIN 16
#define E_MUX2_PIN 78 // 84 in MK2 Firmware, with BEEPER as 78
//
// LCD / Controller
//
#if ENABLED(ULTRA_LCD)
#define KILL_PIN 32
#if ENABLED(NEWPANEL)
#if ENABLED(CR10_STOCKDISPLAY)
#define LCD_PINS_RS 85
#define LCD_PINS_ENABLE 71
#define LCD_PINS_D4 70
#define BTN_EN1 18
#define BTN_EN2 19
#else
#define LCD_PINS_RS 82
#define LCD_PINS_ENABLE 18
#define LCD_PINS_D4 19
#define LCD_PINS_D5 70
#define LCD_PINS_D6 85
#define LCD_PINS_D7 71
#define BTN_EN1 14
#define BTN_EN2 72
#endif
#define BTN_ENC 9 // AUX-2
#define BEEPER_PIN 84 // AUX-4
#define SD_DETECT_PIN 15
#endif // NEWPANEL
#endif // ULTRA_LCD

View File

@@ -1,54 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Melzi (Malyan M150) pin assignments
*/
#define BOARD_NAME "Melzi (Malyan)"
#include "pins_MELZI.h"
#undef LCD_SDSS
#undef LCD_PINS_RS
#undef LCD_PINS_ENABLE
#undef LCD_PINS_D4
#undef BTN_EN1
#undef BTN_EN2
#undef BTN_ENC
#define LCD_PINS_RS 17 // ST9720 CS
#define LCD_PINS_ENABLE 16 // ST9720 DAT
#define LCD_PINS_D4 11 // ST9720 CLK
#define BTN_EN1 30
#define BTN_EN2 29
#define BTN_ENC 28
// Alter timing for graphical display
#ifndef ST7920_DELAY_1
#define ST7920_DELAY_1 DELAY_NS(125)
#endif
#ifndef ST7920_DELAY_2
#define ST7920_DELAY_2 DELAY_NS(125)
#endif
#ifndef ST7920_DELAY_3
#define ST7920_DELAY_3 DELAY_NS(125)
#endif

View File

@@ -1,61 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Melzi pin assignments
*/
#define BOARD_NAME "Melzi (Tronxy)"
#include "pins_MELZI.h"
#undef Z_ENABLE_PIN
#undef LCD_PINS_RS
#undef LCD_PINS_ENABLE
#undef LCD_PINS_D4
#undef LCD_PINS_D5
#undef LCD_PINS_D6
#undef LCD_PINS_D7
#undef BTN_EN1
#undef BTN_EN2
#undef BTN_ENC
#undef LCD_SDSS
#define Z_ENABLE_PIN 14
#define LCD_PINS_RS 30
#define LCD_PINS_ENABLE 28
#define LCD_PINS_D4 16
#define LCD_PINS_D5 17
#define LCD_PINS_D6 27
#define LCD_PINS_D7 29
#define BTN_EN1 10
#define BTN_EN2 11
#define BTN_ENC 26
#ifndef ST7920_DELAY_1
#define ST7920_DELAY_1 DELAY_NS(0)
#endif
#ifndef ST7920_DELAY_2
#define ST7920_DELAY_2 DELAY_NS(125)
#endif
#ifndef ST7920_DELAY_3
#define ST7920_DELAY_3 DELAY_NS(0)
#endif

View File

@@ -1,41 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* MKS BASE v1.5 with A4982 stepper drivers and digital micro-stepping
*/
#include "pins_MKS_BASE.h"
/**
* Microstepping pins
*/
#define X_MS1_PIN 5 // Digital 3 / Pin 5 / PE3 / SERVO2_PIN
#define X_MS2_PIN 6 // Digital 6 / Pin 14 / PH3 / SERVO1_PIN
#define Y_MS1_PIN 59 // Analog 5 / Pin 92 / PF5
#define Y_MS2_PIN 58 // Analog 4 / Pin 93 / PF4
#define Z_MS1_PIN 22 // Digital 22 / Pin 78 / PA0
#define Z_MS2_PIN 39 // Digital 39 / Pin 70 / PG2
#define E0_MS1_PIN 63 // Analog 9 / Pin 86 / PK1
#define E0_MS2_PIN 64 // Analog 10 / Pin 87 / PK2
#define E1_MS1_PIN 57 // Analog 3 / Pin 93 / PF3
#define E1_MS2_PIN 4 // Digital 4 / Pin 1 / PG5 / SERVO3_PIN

View File

@@ -1,35 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* MKS BASE with Heroic HR4982 stepper drivers
*/
#include "pins_MKS_BASE_15.h"
/**
* Some new boards use HR4982 (Heroic) instead of the A4982 (Allegro) stepper drivers.
* Most the functionality is similar, the HR variant obviously doesn't work with diode
* smoothers (no fast decay). And the Heroic has a 128 µStepping mode where the A4982
* is doing quarter steps (MS1=0, MS2=1).
*/
#define HEROIC_STEPPER_DRIVERS

View File

@@ -1,144 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino Mega with RAMPS v1.4 adjusted pin assignments
*
* MKS GEN v1.3 (Extruder, Fan, Bed)
* MKS GEN v1.3 (Extruder, Extruder, Fan, Bed)
* MKS GEN v1.4 (Extruder, Fan, Bed)
* MKS GEN v1.4 (Extruder, Extruder, Fan, Bed)
*/
#if HOTENDS > 2 || E_STEPPERS > 2
#error "MKS GEN 1.3/1.4 supports up to 2 hotends / E-steppers. Comment out this line to continue."
#endif
#define BOARD_NAME "MKS GEN >= v1.3"
//
// Heaters / Fans
//
// Power outputs EFBF or EFBE
#define MOSFET_D_PIN 7
//
// PSU / SERVO
//
// If POWER_SUPPLY is specified, always hijack Servo 3
//
#if POWER_SUPPLY > 0
#define SERVO3_PIN -1
#define PS_ON_PIN 4
#endif
#include "pins_RAMPS.h"
//
// LCD / Controller
//
#if ENABLED(VIKI2) || ENABLED(miniVIKI)
/**
* VIKI2 Has two groups of wires with...
*
* +Vin + Input supply, requires 120ma for LCD and mSD card
* GND Ground Pin
* MOSI Data input for LCD and SD
* MISO Data output for SD
* SCK Clock for LCD and SD
* AO Reg. Sel for LCD
* LCS Chip Select for LCD
* SDCS Chip Select for SD
* SDCD Card Detect pin for SD
* ENCA Encoder output A
* ENCB Encoder output B
* ENCBTN Encoder button switch
*
* BTN Panel mounted button switch
* BUZZER Piezo buzzer
* BLUE-LED Blue LED ring pin (3 to 5v, mosfet buffered)
* RED-LED Red LED ring pin (3 to 5v, mosfet buffered)
*
* This configuration uses the following arrangement:
*
* EXP1 D37 = EN2 D35 = EN1 EXP2 D50 = MISO D52 = SCK
* D17 = BLUE D16 = RED D31 = ENC D53 = SDCS
* D23 = KILL D25 = BUZZ D33 = --- D51 = MOSI
* D27 = A0 D29 = LCS D49 = SDCD RST = ---
* GND = GND 5V = 5V GND = --- D41 = ---
*/
#undef BTN_EN1
#undef BTN_EN2
#undef BTN_ENC
#undef DOGLCD_A0
#undef DOGLCD_CS
#undef SD_DETECT_PIN
#undef BEEPER_PIN
#undef KILL_PIN
//
// VIKI2 12-wire lead
//
// orange/white SDCD
#define SD_DETECT_PIN 49
// white ENCA
#define BTN_EN1 35
// green ENCB
#define BTN_EN2 37
// purple ENCBTN
#define BTN_ENC 31
// brown A0
#define DOGLCD_A0 27
// green/white LCS
#define DOGLCD_CS 29
// 50 gray MISO
// 51 yellow MOSI
// 52 orange SCK
// blue SDCS
//#define SDSS 53
//
// VIKI2 4-wire lead
//
// blue BTN
#define KILL_PIN 23
// green BUZZER
#define BEEPER_PIN 25
// yellow RED-LED
#define STAT_LED_RED_PIN 16
// white BLUE-LED
#define STAT_LED_BLUE_PIN 17
#endif

View File

@@ -1,29 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#if HOTENDS > 1 || E_STEPPERS > 1
#error "Ender-4 supports only 1 hotend / E-stepper. Comment out this line to continue."
#endif
#define BOARD_NAME "Ender-4"
#include "pins_RAMPS.h"

View File

@@ -1,41 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino Mega with RAMPS v1.3 for Anycubic
*/
#ifndef BOARD_NAME
#define BOARD_NAME "Anycubic RAMPS 1.3"
#endif
#define IS_RAMPS_EFB
#define RAMPS_D9_PIN 44
#define FAN2_PIN 9
#define ORIG_E0_AUTO_FAN_PIN 9
#include "pins_RAMPS_13.h"
#undef E1_STEP_PIN
#undef E1_DIR_PIN
#undef E1_ENABLE_PIN
#undef E1_CS_PIN

View File

@@ -1,232 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino Mega with RAMPS v1.4 for Anycubic
*/
#ifndef BOARD_NAME
#define BOARD_NAME "Anycubic RAMPS 1.4"
#endif
#define LARGE_FLASH true
// Misc PINs
#define BUZZER 31
#define SDPOWER -1
#define SDSS 53
#define LED_PIN 13
#define Z_MIN_PROBE_PIN 2
#define FIL_RUNOUT_PIN 19
#ifdef OutageTest
#define OUTAGETEST_PIN 79
#define OUTAGECON_PIN 58
#endif
// Steppers
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define Y_STEP_PIN 60
#define Y_DIR_PIN 61
#define Y_ENABLE_PIN 56
#define Y2_STEP_PIN 36
#define Y2_DIR_PIN 34
#define Y2_ENABLE_PIN 30
#define Z_STEP_PIN 46
#define Z_DIR_PIN 48
#define Z_ENABLE_PIN 62
#define Z2_STEP_PIN 36
#define Z2_DIR_PIN 34
#define Z2_ENABLE_PIN 30
#define E0_STEP_PIN 26
#define E0_DIR_PIN 28
#define E0_ENABLE_PIN 24
// EndStops
#define X_MIN_PIN 3
#define Y_MIN_PIN 42
#define Z_MIN_PIN 18
#define X_MAX_PIN 43
#define Y_MAX_PIN -1
#define Z_MAX_PIN -1
// Fans
#define FAN_PIN 9
#define FAN2_PIN 44
#define ORIG_E0_AUTO_FAN_PIN 44
#define CONTROLLER_FAN_PIN 7
// Heaters
#define HEATER_0_PIN 10
#define HEATER_1_PIN 45
#define HEATER_BED_PIN 8
// Temperatursensoren
#define TEMP_0_PIN 13
#define TEMP_1_PIN 15
#define TEMP_2_PIN 12
#define TEMP_BED_PIN 14
// Servos
#ifdef NUM_SERVOS
#define SERVO0_PIN 11
#if NUM_SERVOS > 1
#define SERVO1_PIN 6
#endif
#if NUM_SERVOS > 2
#define SERVO2_PIN 5
#endif
#if NUM_SERVOS > 3
#define SERVO3_PIN 4
#endif
#endif
#if defined(ANYCUBIC_TFT_MODEL)
#define BEEPER_PIN 31
#define SD_DETECT_PIN 49
#endif
// LCD
#if defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL) || defined(ANYCUBIC_TFT_MODEL)
#define KILL_PIN 41
#else
#define KILL_PIN -1
#endif
#ifdef ULTRA_LCD
#ifdef NEWPANEL
#define LCD_PINS_RS 16
#define LCD_PINS_ENABLE 17
#define LCD_PINS_D4 23
#define LCD_PINS_D5 25
#define LCD_PINS_D6 27
#define LCD_PINS_D7 29
#ifdef REPRAP_DISCOUNT_SMART_CONTROLLER
#define BEEPER_PIN 37
#define BTN_EN1 31
#define BTN_EN2 33
#define BTN_ENC 35
#define SD_DETECT_PIN 49
#elif defined(LCD_I2C_PANELOLU2)
#define BTN_EN1 47 //reverse if the encoder turns the wrong way.
#define BTN_EN2 43
#define BTN_ENC 32
#define SDSS 53
#define SD_DETECT_PIN -1
#define KILL_PIN 41
#elif defined(LCD_I2C_VIKI)
#define BTN_EN1 22 //reverse if the encoder turns the wrong way.
#define BTN_EN2 7
#define BTN_ENC -1
#define SDSS 53
#define SD_DETECT_PIN 49
#elif defined(FULL_GRAPHIC_SMALL_PANEL)
#define BEEPER_PIN 37
// Pins for DOGM SPI LCD Support
#define DOGLCD_A0 23
#define DOGLCD_CS 27
#define LCD_PIN_BL 25 // backlight LED on PA3
#define KILL_PIN 41
// GLCD features
//#define LCD_CONTRAST 190
// Uncomment screen orientation
// #define LCD_SCREEN_ROT_90
// #define LCD_SCREEN_ROT_180
// #define LCD_SCREEN_ROT_270
//The encoder and click button
#define BTN_EN1 33
#define BTN_EN2 -1
#define BTN_ENC 35 //the click switch
//not connected to a pin
#define SD_DETECT_PIN 49
#elif defined(MULTIPANEL)
// #define BEEPER_PIN 37
// Pins for DOGM SPI LCD Support
#define DOGLCD_A0 17
#define DOGLCD_CS 16
#define LCD_PIN_BL 23 // backlight LED on A11/D65
#define SDSS 53
#define KILL_PIN 64
// GLCD features
//#define LCD_CONTRAST 190
// Uncomment screen orientation
// #define LCD_SCREEN_ROT_90
// #define LCD_SCREEN_ROT_180
// #define LCD_SCREEN_ROT_270
//The encoder and click button
#define BTN_EN1 -1
#define BTN_EN2 33
#define BTN_ENC 35 //the click switch
//not connected to a pin
#define SD_DETECT_PIN 49
#else
//arduino pin which triggers an piezzo beeper
#define BEEPER_PIN 31 // Beeper on AUX-4
//buttons are directly attached using AUX-2
#ifdef REPRAPWORLD_KEYPAD
#define BTN_EN1 64 // encoder
#define BTN_EN2 59 // encoder
#define BTN_ENC 63 // enter button
#define SHIFT_OUT 40 // shift register
#define SHIFT_CLK 44 // shift register
#define SHIFT_LD 42 // shift register
#else
#define BTN_EN1 37
#define BTN_EN2 35
#define BTN_ENC -1 //the click
#endif
#ifdef G3D_PANEL
#define SD_DETECT_PIN 49
#else
#define SD_DETECT_PIN -1 // Ramps does not use this port
#endif
#endif
#define LCD_PINS_RS 16
#define LCD_PINS_ENABLE 17
#define LCD_PINS_D4 23
#define LCD_PINS_D5 25
#define LCD_PINS_D6 27
#define LCD_PINS_D7 29
#endif
#endif

View File

@@ -1,117 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* power.cpp - power control
*/
#include "MarlinConfig.h"
#if ENABLED(AUTO_POWER_CONTROL)
#include "power.h"
#include "temperature.h"
#include "stepper_indirection.h"
Power powerManager;
millis_t Power::lastPowerOn;
bool Power::is_power_needed() {
#if ENABLED(AUTO_POWER_FANS)
for (uint8_t i = 0; i < FAN_COUNT; i++) if (fanSpeeds[i] > 0) return true;
#endif
#if ENABLED(AUTO_POWER_E_FANS)
HOTEND_LOOP() if (thermalManager.autofan_speed[e] > 0) return true;
#endif
#if ENABLED(AUTO_POWER_CONTROLLERFAN) && HAS_CONTROLLER_FAN && ENABLED(USE_CONTROLLER_FAN)
if (controllerFanSpeed > 0) return true;
#endif
// If any of the drivers or the bed are enabled...
if (X_ENABLE_READ == X_ENABLE_ON || Y_ENABLE_READ == Y_ENABLE_ON || Z_ENABLE_READ == Z_ENABLE_ON
#if HAS_HEATED_BED
|| thermalManager.soft_pwm_amount_bed > 0
#endif
#if HAS_X2_ENABLE
|| X2_ENABLE_READ == X_ENABLE_ON
#endif
#if HAS_Y2_ENABLE
|| Y2_ENABLE_READ == Y_ENABLE_ON
#endif
#if HAS_Z2_ENABLE
|| Z2_ENABLE_READ == Z_ENABLE_ON
#endif
|| E0_ENABLE_READ == E_ENABLE_ON
#if E_STEPPERS > 1
|| E1_ENABLE_READ == E_ENABLE_ON
#if E_STEPPERS > 2
|| E2_ENABLE_READ == E_ENABLE_ON
#if E_STEPPERS > 3
|| E3_ENABLE_READ == E_ENABLE_ON
#if E_STEPPERS > 4
|| E4_ENABLE_READ == E_ENABLE_ON
#endif
#endif
#endif
#endif
) return true;
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0) return true;
#if HAS_HEATED_BED
if (thermalManager.degTargetBed() > 0) return true;
#endif
return false;
}
void Power::check() {
static millis_t nextPowerCheck = 0;
millis_t ms = millis();
if (ELAPSED(ms, nextPowerCheck)) {
nextPowerCheck = ms + 2500UL;
if (is_power_needed())
power_on();
else if (!lastPowerOn || ELAPSED(ms, lastPowerOn + (POWER_TIMEOUT) * 1000UL))
power_off();
}
}
void Power::power_on() {
lastPowerOn = millis();
if (!powersupply_on) {
PSU_PIN_ON();
#if HAS_TRINAMIC
delay(100); // Wait for power to settle
restore_stepper_drivers();
#endif
}
}
void Power::power_off() {
if (powersupply_on) PSU_PIN_OFF();
}
#endif // AUTO_POWER_CONTROL

View File

@@ -1,44 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* power.h - power control
*/
#ifndef POWER_H
#define POWER_H
#include "types.h"
class Power {
public:
static void check();
static void power_on();
static void power_off();
private:
static millis_t lastPowerOn;
static bool is_power_needed();
};
extern Power powerManager;
#endif // POWER_H

View File

@@ -1,284 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* power_loss_recovery.cpp - Resume an SD print after power-loss
*/
#include "MarlinConfig.h"
#if ENABLED(POWER_LOSS_RECOVERY)
#include "power_loss_recovery.h"
#include "cardreader.h"
#include "planner.h"
#include "printcounter.h"
#include "serial.h"
#include "temperature.h"
#include "ultralcd.h"
// Recovery data
job_recovery_info_t job_recovery_info;
JobRecoveryPhase job_recovery_phase = JOB_RECOVERY_IDLE;
uint8_t job_recovery_commands_count; //=0
char job_recovery_commands[BUFSIZE + APPEND_CMD_COUNT][MAX_CMD_SIZE];
// Extern
extern uint8_t active_extruder, commands_in_queue, cmd_queue_index_r;
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
void debug_print_job_recovery(const bool recovery) {
SERIAL_PROTOCOLLNPGM("---- Job Recovery Info ----");
SERIAL_PROTOCOLPAIR("valid_head:", int(job_recovery_info.valid_head));
SERIAL_PROTOCOLLNPAIR(" valid_foot:", int(job_recovery_info.valid_foot));
if (job_recovery_info.valid_head) {
if (job_recovery_info.valid_head == job_recovery_info.valid_foot) {
SERIAL_PROTOCOLPGM("current_position: ");
LOOP_XYZE(i) {
SERIAL_PROTOCOL(job_recovery_info.current_position[i]);
if (i < E_AXIS) SERIAL_CHAR(',');
}
SERIAL_EOL();
SERIAL_PROTOCOLLNPAIR("feedrate: ", job_recovery_info.feedrate);
#if HOTENDS > 1
SERIAL_PROTOCOLLNPAIR("active_hotend: ", int(job_recovery_info.active_hotend));
#endif
SERIAL_PROTOCOLPGM("target_temperature: ");
HOTEND_LOOP() {
SERIAL_PROTOCOL(job_recovery_info.target_temperature[e]);
if (e < HOTENDS - 1) SERIAL_CHAR(',');
}
SERIAL_EOL();
#if HAS_HEATED_BED
SERIAL_PROTOCOLLNPAIR("target_temperature_bed: ", job_recovery_info.target_temperature_bed);
#endif
#if FAN_COUNT
SERIAL_PROTOCOLPGM("fanSpeeds: ");
for (int8_t i = 0; i < FAN_COUNT; i++) {
SERIAL_PROTOCOL(job_recovery_info.fanSpeeds[i]);
if (i < FAN_COUNT - 1) SERIAL_CHAR(',');
}
SERIAL_EOL();
#endif
#if HAS_LEVELING
SERIAL_PROTOCOLPAIR("leveling: ", int(job_recovery_info.leveling));
SERIAL_PROTOCOLLNPAIR(" fade: ", int(job_recovery_info.fade));
#endif
SERIAL_PROTOCOLLNPAIR("cmd_queue_index_r: ", int(job_recovery_info.cmd_queue_index_r));
SERIAL_PROTOCOLLNPAIR("commands_in_queue: ", int(job_recovery_info.commands_in_queue));
if (recovery)
for (uint8_t i = 0; i < job_recovery_commands_count; i++) SERIAL_PROTOCOLLNPAIR("> ", job_recovery_commands[i]);
else
for (uint8_t i = 0; i < job_recovery_info.commands_in_queue; i++) SERIAL_PROTOCOLLNPAIR("> ", job_recovery_info.command_queue[i]);
SERIAL_PROTOCOLLNPAIR("sd_filename: ", job_recovery_info.sd_filename);
SERIAL_PROTOCOLLNPAIR("sdpos: ", job_recovery_info.sdpos);
SERIAL_PROTOCOLLNPAIR("print_job_elapsed: ", job_recovery_info.print_job_elapsed);
}
else
SERIAL_PROTOCOLLNPGM("INVALID DATA");
}
SERIAL_PROTOCOLLNPGM("---------------------------");
}
#endif // DEBUG_POWER_LOSS_RECOVERY
/**
* Check for Print Job Recovery during setup()
*
* If a saved state exists, populate job_recovery_commands with
* commands to restore the machine state and continue the file.
*/
void check_print_job_recovery() {
memset(&job_recovery_info, 0, sizeof(job_recovery_info));
ZERO(job_recovery_commands);
if (!card.cardOK) card.initsd();
if (card.cardOK) {
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
SERIAL_PROTOCOLLNPAIR("Init job recovery info. Size: ", int(sizeof(job_recovery_info)));
#endif
if (card.jobRecoverFileExists()) {
card.openJobRecoveryFile(true);
card.loadJobRecoveryInfo();
card.closeJobRecoveryFile();
//card.removeJobRecoveryFile();
if (job_recovery_info.valid_head && job_recovery_info.valid_head == job_recovery_info.valid_foot) {
uint8_t ind = 0;
#if HAS_LEVELING
strcpy_P(job_recovery_commands[ind++], PSTR("M420 S0 Z0")); // Leveling off before G92 or G28
#endif
strcpy_P(job_recovery_commands[ind++], PSTR("G92.0 Z0")); // Ensure Z is equal to 0
strcpy_P(job_recovery_commands[ind++], PSTR("G1 Z2")); // Raise Z by 2mm (we hope!)
strcpy_P(job_recovery_commands[ind++], PSTR("G28 R0"
#if ENABLED(MARLIN_DEV_MODE)
" S"
#elif !IS_KINEMATIC
" X Y" // Home X and Y for Cartesian
#endif
));
char str_1[16], str_2[16];
#if HAS_LEVELING
if (job_recovery_info.fade || job_recovery_info.leveling) {
// Restore leveling state before G92 sets Z
// This ensures the steppers correspond to the native Z
dtostrf(job_recovery_info.fade, 1, 1, str_1);
sprintf_P(job_recovery_commands[ind++], PSTR("M420 S%i Z%s"), int(job_recovery_info.leveling), str_1);
}
#endif
dtostrf(job_recovery_info.current_position[Z_AXIS] + 2, 1, 3, str_1);
dtostrf(job_recovery_info.current_position[E_CART]
#if ENABLED(SAVE_EACH_CMD_MODE)
- 5
#endif
, 1, 3, str_2
);
sprintf_P(job_recovery_commands[ind++], PSTR("G92.0 Z%s E%s"), str_1, str_2); // Current Z + 2 and E
uint8_t r = job_recovery_info.cmd_queue_index_r, c = job_recovery_info.commands_in_queue;
while (c--) {
strcpy(job_recovery_commands[ind++], job_recovery_info.command_queue[r]);
r = (r + 1) % BUFSIZE;
}
if (job_recovery_info.sd_filename[0] == '/') job_recovery_info.sd_filename[0] = ' ';
sprintf_P(job_recovery_commands[ind++], PSTR("M23 %s"), job_recovery_info.sd_filename);
sprintf_P(job_recovery_commands[ind++], PSTR("M24 S%ld T%ld"), job_recovery_info.sdpos, job_recovery_info.print_job_elapsed);
job_recovery_commands_count = ind;
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
debug_print_job_recovery(true);
#endif
}
else {
if (job_recovery_info.valid_head != job_recovery_info.valid_foot)
LCD_ALERTMESSAGEPGM("INVALID DATA");
memset(&job_recovery_info, 0, sizeof(job_recovery_info));
}
}
}
}
/**
* Save the current machine state to the power-loss recovery file
*/
void save_job_recovery_info() {
#if SAVE_INFO_INTERVAL_MS > 0
static millis_t next_save_ms; // = 0; // Init on reset
millis_t ms = millis();
#endif
if (
// Save on every command
#if ENABLED(SAVE_EACH_CMD_MODE)
true
#else
// Save if power loss pin is triggered
#if PIN_EXISTS(POWER_LOSS)
READ(POWER_LOSS_PIN) == POWER_LOSS_STATE ||
#endif
// Save if interval is elapsed
#if SAVE_INFO_INTERVAL_MS > 0
ELAPSED(ms, next_save_ms) ||
#endif
// Save on every new Z height
(current_position[Z_AXIS] > 0 && current_position[Z_AXIS] > job_recovery_info.current_position[Z_AXIS])
#endif
) {
#if SAVE_INFO_INTERVAL_MS > 0
next_save_ms = ms + SAVE_INFO_INTERVAL_MS;
#endif
// Head and foot will match if valid data was saved
if (!++job_recovery_info.valid_head) ++job_recovery_info.valid_head; // non-zero in sequence
job_recovery_info.valid_foot = job_recovery_info.valid_head;
// Machine state
COPY(job_recovery_info.current_position, current_position);
job_recovery_info.feedrate = feedrate_mm_s;
#if HOTENDS > 1
job_recovery_info.active_hotend = active_extruder;
#endif
COPY(job_recovery_info.target_temperature, thermalManager.target_temperature);
#if HAS_HEATED_BED
job_recovery_info.target_temperature_bed = thermalManager.target_temperature_bed;
#endif
#if FAN_COUNT
COPY(job_recovery_info.fanSpeeds, fanSpeeds);
#endif
#if HAS_LEVELING
job_recovery_info.leveling = planner.leveling_active;
job_recovery_info.fade = (
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
planner.z_fade_height
#else
0
#endif
);
#endif
// Commands in the queue
job_recovery_info.cmd_queue_index_r = cmd_queue_index_r;
job_recovery_info.commands_in_queue = commands_in_queue;
COPY(job_recovery_info.command_queue, command_queue);
// Elapsed print job time
job_recovery_info.print_job_elapsed = print_job_timer.duration();
// SD file position
card.getAbsFilename(job_recovery_info.sd_filename);
job_recovery_info.sdpos = card.getIndex();
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
SERIAL_PROTOCOLLNPGM("Saving...");
debug_print_job_recovery(false);
#endif
card.openJobRecoveryFile(false);
(void)card.saveJobRecoveryInfo();
// If power-loss pin was triggered, write just once then kill
#if PIN_EXISTS(POWER_LOSS)
if (READ(POWER_LOSS_PIN) == POWER_LOSS_STATE) kill(MSG_POWER_LOSS_RECOVERY);
#endif
}
}
#endif // POWER_LOSS_RECOVERY

View File

@@ -1,99 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* power_loss_recovery.h - Resume an SD print after power-loss
*/
#ifndef _POWER_LOSS_RECOVERY_H_
#define _POWER_LOSS_RECOVERY_H_
#include "cardreader.h"
#include "types.h"
#include "MarlinConfig.h"
#define SAVE_INFO_INTERVAL_MS 0
//#define SAVE_EACH_CMD_MODE
//#define DEBUG_POWER_LOSS_RECOVERY
typedef struct {
uint8_t valid_head;
// Machine state
float current_position[NUM_AXIS], feedrate;
#if HOTENDS > 1
uint8_t active_hotend;
#endif
int16_t target_temperature[HOTENDS];
#if HAS_HEATED_BED
int16_t target_temperature_bed;
#endif
#if FAN_COUNT
int16_t fanSpeeds[FAN_COUNT];
#endif
#if HAS_LEVELING
bool leveling;
float fade;
#endif
// Command queue
uint8_t cmd_queue_index_r, commands_in_queue;
char command_queue[BUFSIZE][MAX_CMD_SIZE];
// SD Filename and position
char sd_filename[MAXPATHNAMELENGTH];
uint32_t sdpos;
// Job elapsed time
millis_t print_job_elapsed;
uint8_t valid_foot;
} job_recovery_info_t;
extern job_recovery_info_t job_recovery_info;
enum JobRecoveryPhase : unsigned char {
JOB_RECOVERY_IDLE,
JOB_RECOVERY_MAYBE,
JOB_RECOVERY_YES,
JOB_RECOVERY_DONE
};
extern JobRecoveryPhase job_recovery_phase;
#if HAS_LEVELING
#define APPEND_CMD_COUNT 9
#else
#define APPEND_CMD_COUNT 7
#endif
extern char job_recovery_commands[BUFSIZE + APPEND_CMD_COUNT][MAX_CMD_SIZE];
extern uint8_t job_recovery_commands_count;
void check_print_job_recovery();
void save_job_recovery_info();
#endif // _POWER_LOSS_RECOVERY_H_

View File

@@ -1,61 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* runout.cpp - Runout sensor support
*/
#include "MarlinConfig.h"
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#include "runout.h"
FilamentRunoutSensor runout;
bool FilamentRunoutSensor::filament_ran_out; // = false
uint8_t FilamentRunoutSensor::runout_count; // = 0
void FilamentRunoutSensor::setup() {
#if ENABLED(FIL_RUNOUT_PULLUP)
#define INIT_RUNOUT_PIN(P) SET_INPUT_PULLUP(P)
#else
#define INIT_RUNOUT_PIN(P) SET_INPUT(P)
#endif
INIT_RUNOUT_PIN(FIL_RUNOUT_PIN);
#if NUM_RUNOUT_SENSORS > 1
INIT_RUNOUT_PIN(FIL_RUNOUT2_PIN);
#if NUM_RUNOUT_SENSORS > 2
INIT_RUNOUT_PIN(FIL_RUNOUT3_PIN);
#if NUM_RUNOUT_SENSORS > 3
INIT_RUNOUT_PIN(FIL_RUNOUT4_PIN);
#if NUM_RUNOUT_SENSORS > 4
INIT_RUNOUT_PIN(FIL_RUNOUT5_PIN);
#endif
#endif
#endif
#endif
}
#endif // FILAMENT_RUNOUT_SENSOR

View File

@@ -1,85 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* runout.h - Runout sensor support
*/
#ifndef _RUNOUT_H_
#define _RUNOUT_H_
#include "cardreader.h"
#include "printcounter.h"
#include "stepper.h"
#include "Marlin.h"
#include "MarlinConfig.h"
#define FIL_RUNOUT_THRESHOLD 5
class FilamentRunoutSensor {
public:
FilamentRunoutSensor() {}
static void setup();
FORCE_INLINE static void reset() { runout_count = 0; filament_ran_out = false; }
FORCE_INLINE static void run() {
if ((IS_SD_PRINTING() || print_job_timer.isRunning()) && check() && !filament_ran_out) {
filament_ran_out = true;
enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
planner.synchronize();
}
}
private:
static bool filament_ran_out;
static uint8_t runout_count;
FORCE_INLINE static bool check() {
#if NUM_RUNOUT_SENSORS < 2
// A single sensor applying to all extruders
const bool is_out = READ(FIL_RUNOUT_PIN) == FIL_RUNOUT_INVERTING;
#else
// Read the sensor for the active extruder
bool is_out;
switch (active_extruder) {
case 0: is_out = READ(FIL_RUNOUT_PIN) == FIL_RUNOUT_INVERTING; break;
case 1: is_out = READ(FIL_RUNOUT2_PIN) == FIL_RUNOUT_INVERTING; break;
#if NUM_RUNOUT_SENSORS > 2
case 2: is_out = READ(FIL_RUNOUT3_PIN) == FIL_RUNOUT_INVERTING; break;
#if NUM_RUNOUT_SENSORS > 3
case 3: is_out = READ(FIL_RUNOUT4_PIN) == FIL_RUNOUT_INVERTING; break;
#if NUM_RUNOUT_SENSORS > 4
case 4: is_out = READ(FIL_RUNOUT5_PIN) == FIL_RUNOUT_INVERTING; break;
#endif
#endif
#endif
}
#endif
return (is_out ? ++runout_count : (runout_count = 0)) > FIL_RUNOUT_THRESHOLD;
}
};
extern FilamentRunoutSensor runout;
#endif // _RUNOUT_H_

View File

@@ -1,493 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* status_screen_DOGM.h
*
* Standard Status Screen for Graphical Display
*/
#ifndef _STATUS_SCREEN_DOGM_H_
#define _STATUS_SCREEN_DOGM_H_
FORCE_INLINE void _draw_centered_temp(const int16_t temp, const uint8_t x, const uint8_t y) {
const char * const str = itostr3(temp);
u8g.setPrintPos(x - (str[0] != ' ' ? 0 : str[1] != ' ' ? 1 : 2) * DOG_CHAR_WIDTH / 2, y);
lcd_print(str);
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
}
#ifndef HEAT_INDICATOR_X
#define HEAT_INDICATOR_X 8
#endif
FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, const bool blink) {
#if !HEATER_IDLE_HANDLER
UNUSED(blink);
#endif
#if HAS_HEATED_BED
const bool isBed = heater < 0;
#else
constexpr bool isBed = false;
#endif
if (PAGE_UNDER(7)) {
#if HEATER_IDLE_HANDLER
const bool is_idle = (
#if HAS_HEATED_BED
isBed ? thermalManager.is_bed_idle() :
#endif
thermalManager.is_heater_idle(heater)
);
if (blink || !is_idle)
#endif
_draw_centered_temp(0.5f + (
#if HAS_HEATED_BED
isBed ? thermalManager.degTargetBed() :
#endif
thermalManager.degTargetHotend(heater)
), x, 7
);
}
if (PAGE_CONTAINS(21, 28)) {
_draw_centered_temp(0.5f + (
#if HAS_HEATED_BED
isBed ? thermalManager.degBed() :
#endif
thermalManager.degHotend(heater)
), x, 28
);
if (PAGE_CONTAINS(17, 20)) {
const uint8_t h = isBed ? 7 : HEAT_INDICATOR_X,
y = isBed ? 18 : 17;
if (
#if HAS_HEATED_BED
isBed ? thermalManager.isHeatingBed() :
#endif
thermalManager.isHeatingHotend(heater)
) {
u8g.setColorIndex(0); // white on black
u8g.drawBox(x + h, y, 2, 2);
u8g.setColorIndex(1); // black on white
}
else
u8g.drawBox(x + h, y, 2, 2);
}
}
}
//
// Before homing, blink '123' <-> '???'.
// Homed but unknown... '123' <-> ' '.
// Homed and known, display constantly.
//
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) {
if (blink)
lcd_print(value);
else {
if (!TEST(axis_homed, axis))
while (const char c = *value++) lcd_print(c <= '.' ? c : '?');
else {
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
if (!TEST(axis_known_position, axis))
lcd_printPGM(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
else
#endif
lcd_print(value);
}
}
}
inline void lcd_implementation_status_message(const bool blink) {
#if ENABLED(STATUS_MESSAGE_SCROLLING)
static bool last_blink = false;
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
// If the string fits into the LCD, just print it and do not scroll it
if (slen <= LCD_WIDTH) {
// The string isn't scrolling and may not fill the screen
lcd_print_utf(lcd_status_message);
// Fill the rest with spaces
while (slen < LCD_WIDTH) {
u8g.print(' ');
++slen;
}
}
else {
// String is larger than the available space in screen.
// Get a pointer to the next valid UTF8 character
const char *stat = lcd_status_message + status_scroll_offset;
// Get the string remaining length
const uint8_t rlen = utf8_strlen(stat);
// If we have enough characters to display
if (rlen >= LCD_WIDTH) {
// The remaining string fills the screen - Print it
lcd_print_utf(stat, LCD_WIDTH);
}
else {
// The remaining string does not completely fill the screen
lcd_print_utf(stat, LCD_WIDTH); // The string leaves space
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
u8g.print('.'); // Always at 1+ spaces left, draw a dot
if (--chars) { // Draw a second dot if there's space
u8g.print('.');
if (--chars) // Print a second copy of the message
lcd_print_utf(lcd_status_message, LCD_WIDTH - (rlen + 2));
}
}
if (last_blink != blink) {
last_blink = blink;
// Adjust by complete UTF8 characters
if (status_scroll_offset < slen) {
status_scroll_offset++;
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
status_scroll_offset++;
}
else
status_scroll_offset = 0;
}
}
#else
UNUSED(blink);
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(lcd_status_message);
// Just print the string to the LCD
lcd_print_utf(lcd_status_message, LCD_WIDTH);
// Fill the rest with spaces if there are missing spaces
while (slen < LCD_WIDTH) {
u8g.print(' ');
++slen;
}
#endif
}
static void lcd_implementation_status_screen() {
const bool blink = lcd_blink();
#if FAN_ANIM_FRAMES > 2
static bool old_blink;
static uint8_t fan_frame;
if (old_blink != blink) {
old_blink = blink;
if (!fanSpeeds[0] || ++fan_frame >= FAN_ANIM_FRAMES) fan_frame = 0;
}
#endif
// Status Menu Font
lcd_setFont(FONT_STATUSMENU);
//
// Fan Animation
//
// Draws the whole heading image as a B/W bitmap rather than
// drawing the elements separately.
// This was done as an optimization, as it was slower to draw
// multiple parts compared to a single bitmap.
//
// The bitmap:
// - May be offset in X
// - Includes all nozzle(s), bed(s), and the fan.
//
// TODO:
//
// - Only draw the whole header on the first
// entry to the status screen. Nozzle, bed, and
// fan outline bits don't change.
//
if (PAGE_UNDER(STATUS_SCREENHEIGHT + 1)) {
u8g.drawBitmapP(
STATUS_SCREEN_X, STATUS_SCREEN_Y,
(STATUS_SCREENWIDTH + 7) / 8, STATUS_SCREENHEIGHT,
#if HAS_FAN0
#if FAN_ANIM_FRAMES > 2
fan_frame == 1 ? status_screen1_bmp :
fan_frame == 2 ? status_screen2_bmp :
#if FAN_ANIM_FRAMES > 3
fan_frame == 3 ? status_screen3_bmp :
#endif
#else
blink && fanSpeeds[0] ? status_screen1_bmp :
#endif
#endif
status_screen0_bmp
);
}
//
// Temperature Graphics and Info
//
if (PAGE_UNDER(28)) {
// Extruders
HOTEND_LOOP() _draw_heater_status(STATUS_SCREEN_HOTEND_TEXT_X(e), e, blink);
// Heated bed
#if HOTENDS < 4 && HAS_HEATED_BED
_draw_heater_status(STATUS_SCREEN_BED_TEXT_X, -1, blink);
#endif
#if HAS_FAN0
if (PAGE_CONTAINS(STATUS_SCREEN_FAN_TEXT_Y - 7, STATUS_SCREEN_FAN_TEXT_Y)) {
// Fan
const int16_t per = ((fanSpeeds[0] + 1) * 100) / 256;
if (per) {
u8g.setPrintPos(STATUS_SCREEN_FAN_TEXT_X, STATUS_SCREEN_FAN_TEXT_Y);
lcd_print(itostr3(per));
u8g.print('%');
}
}
#endif
}
#if ENABLED(SDSUPPORT)
//
// SD Card Symbol
//
if (card.isFileOpen() && PAGE_CONTAINS(42 - (TALL_FONT_CORRECTION), 51 - (TALL_FONT_CORRECTION))) {
// Upper box
u8g.drawBox(42, 42 - (TALL_FONT_CORRECTION), 8, 7); // 42-48 (or 41-47)
// Right edge
u8g.drawBox(50, 44 - (TALL_FONT_CORRECTION), 2, 5); // 44-48 (or 43-47)
// Bottom hollow box
u8g.drawFrame(42, 49 - (TALL_FONT_CORRECTION), 10, 4); // 49-52 (or 48-51)
// Corner pixel
u8g.drawPixel(50, 43 - (TALL_FONT_CORRECTION)); // 43 (or 42)
}
#endif // SDSUPPORT
#if ENABLED(SDSUPPORT) || ENABLED(LCD_SET_PROGRESS_MANUALLY)
//
// Progress bar frame
//
#define PROGRESS_BAR_X 54
#define PROGRESS_BAR_WIDTH (LCD_PIXEL_WIDTH - PROGRESS_BAR_X)
if (PAGE_CONTAINS(49, 52 - (TALL_FONT_CORRECTION))) // 49-52 (or 49-51)
u8g.drawFrame(
PROGRESS_BAR_X, 49,
PROGRESS_BAR_WIDTH, 4 - (TALL_FONT_CORRECTION)
);
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
const uint8_t progress_bar_percent = card.percentDone();
#endif
if (progress_bar_percent > 1) {
//
// Progress bar solid part
//
if (PAGE_CONTAINS(50, 51 - (TALL_FONT_CORRECTION))) // 50-51 (or just 50)
u8g.drawBox(
PROGRESS_BAR_X + 1, 50,
(uint16_t)((PROGRESS_BAR_WIDTH - 2) * progress_bar_percent * 0.01), 2 - (TALL_FONT_CORRECTION)
);
//
// SD Percent Complete
//
#if ENABLED(DOGM_SD_PERCENT)
if (PAGE_CONTAINS(41, 48)) {
// Percent complete
u8g.setPrintPos(55, 48);
u8g.print(itostr3(progress_bar_percent));
u8g.print('%');
}
#endif
}
//
// Elapsed Time
//
#if DISABLED(DOGM_SD_PERCENT)
#define SD_DURATION_X (PROGRESS_BAR_X + (PROGRESS_BAR_WIDTH / 2) - len * (DOG_CHAR_WIDTH / 2))
#else
#define SD_DURATION_X (LCD_PIXEL_WIDTH - len * DOG_CHAR_WIDTH)
#endif
if (PAGE_CONTAINS(41, 48)) {
char buffer[10];
duration_t elapsed = print_job_timer.duration();
bool has_days = (elapsed.value >= 60*60*24L);
uint8_t len = elapsed.toDigital(buffer, has_days);
u8g.setPrintPos(SD_DURATION_X, 48);
lcd_print(buffer);
}
#endif // SDSUPPORT || LCD_SET_PROGRESS_MANUALLY
//
// XYZ Coordinates
//
#define XYZ_BASELINE (30 + INFO_FONT_HEIGHT)
#define X_LABEL_POS 3
#define X_VALUE_POS 11
#define XYZ_SPACING 40
#if ENABLED(XYZ_HOLLOW_FRAME)
#define XYZ_FRAME_TOP 29
#define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 3
#else
#define XYZ_FRAME_TOP 30
#define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 1
#endif
static char xstring[5], ystring[5], zstring[7];
#if ENABLED(FILAMENT_LCD_DISPLAY)
static char wstring[5], mstring[4];
#endif
// At the first page, regenerate the XYZ strings
if (page.page == 0) {
strcpy(xstring, ftostr4sign(LOGICAL_X_POSITION(current_position[X_AXIS])));
strcpy(ystring, ftostr4sign(LOGICAL_Y_POSITION(current_position[Y_AXIS])));
strcpy(zstring, ftostr52sp(LOGICAL_Z_POSITION(current_position[Z_AXIS])));
#if ENABLED(FILAMENT_LCD_DISPLAY)
strcpy(wstring, ftostr12ns(filament_width_meas));
strcpy(mstring, itostr3(100.0 * (
parser.volumetric_enabled
? planner.volumetric_area_nominal / planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
: planner.volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]
)
));
#endif
}
if (PAGE_CONTAINS(XYZ_FRAME_TOP, XYZ_FRAME_TOP + XYZ_FRAME_HEIGHT - 1)) {
#if ENABLED(XYZ_HOLLOW_FRAME)
u8g.drawFrame(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 29-40 7: 29-39
#else
u8g.drawBox(0, XYZ_FRAME_TOP, LCD_PIXEL_WIDTH, XYZ_FRAME_HEIGHT); // 8: 30-39 7: 30-37
#endif
if (PAGE_CONTAINS(XYZ_BASELINE - (INFO_FONT_HEIGHT - 1), XYZ_BASELINE)) {
#if DISABLED(XYZ_HOLLOW_FRAME)
u8g.setColorIndex(0); // white on black
#endif
u8g.setPrintPos(0 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
lcd_printPGM(PSTR(MSG_X));
u8g.setPrintPos(0 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
_draw_axis_value(X_AXIS, xstring, blink);
u8g.setPrintPos(1 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
lcd_printPGM(PSTR(MSG_Y));
u8g.setPrintPos(1 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
_draw_axis_value(Y_AXIS, ystring, blink);
u8g.setPrintPos(2 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
lcd_printPGM(PSTR(MSG_Z));
u8g.setPrintPos(2 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
_draw_axis_value(Z_AXIS, zstring, blink);
#if DISABLED(XYZ_HOLLOW_FRAME)
u8g.setColorIndex(1); // black on white
#endif
}
}
//
// Feedrate
//
if (PAGE_CONTAINS(51 - INFO_FONT_HEIGHT, 49)) {
lcd_setFont(FONT_MENU);
u8g.setPrintPos(3, 50);
lcd_print(LCD_STR_FEEDRATE[0]);
lcd_setFont(FONT_STATUSMENU);
u8g.setPrintPos(12, 50);
lcd_print(itostr3(feedrate_percentage));
u8g.print('%');
//
// Filament sensor display if SD is disabled
//
#if ENABLED(FILAMENT_LCD_DISPLAY) && DISABLED(SDSUPPORT)
u8g.setPrintPos(56, 50);
lcd_print(wstring);
u8g.setPrintPos(102, 50);
lcd_print(mstring);
u8g.print('%');
lcd_setFont(FONT_MENU);
u8g.setPrintPos(47, 50);
lcd_print(LCD_STR_FILAM_DIA);
u8g.setPrintPos(93, 50);
lcd_print(LCD_STR_FILAM_MUL);
#endif
}
//
// Status line
//
#define STATUS_BASELINE (55 + INFO_FONT_HEIGHT)
if (PAGE_CONTAINS(STATUS_BASELINE - (INFO_FONT_HEIGHT - 1), STATUS_BASELINE)) {
u8g.setPrintPos(0, STATUS_BASELINE);
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
if (PENDING(millis(), previous_lcd_status_ms + 5000UL)) { //Display both Status message line and Filament display on the last line
lcd_implementation_status_message(blink);
}
else {
lcd_printPGM(PSTR(LCD_STR_FILAM_DIA));
u8g.print(':');
lcd_print(wstring);
lcd_printPGM(PSTR(" " LCD_STR_FILAM_MUL));
u8g.print(':');
lcd_print(mstring);
u8g.print('%');
}
#else
lcd_implementation_status_message(blink);
#endif
}
}
#endif // _STATUS_SCREEN_DOGM_H_

View File

@@ -1,972 +0,0 @@
/**
* Lightweight Status Screen for the RepRapDiscount Full
* Graphics Smart Controller (ST7920-based 128x64 LCD)
*
* (c) 2017 Aleph Objects, Inc.
*
* The code in this page is free software: you can
* redistribute it and/or modify it under the terms of the GNU
* General Public License (GNU GPL) as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version. The code is distributed WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
*
*/
/**
* Implementation of a Status Screen for the RepRapDiscount
* Full Graphics Smart Controller using native ST7920 commands
* instead of U8Glib.
*
* This alternative Status Screen makes use of the built-in character
* generation capabilities of the ST7920 to update the Status Screen
* with less SPI traffic and CPU use. In particular:
*
* - The fan and bed animations are handled using custom characters
* that are stored in CGRAM. This allows for the animation to be
* updated by writing a single character to the text-buffer (DDRAM).
*
* - All the information in the Status Screen is text that is written
* to DDRAM, so the work of generating the bitmaps is offloaded to
* the ST7920 rather than being render by U8Glib on the MCU.
*
* - The graphics buffer (GDRAM) is only used for static graphics
* elements (nozzle and feedrate bitmaps) and for the progress
* bar, so updates are sporadic.
*/
#include "status_screen_lite_ST7920_class.h"
#include "duration_t.h"
#define BUFFER_WIDTH 256
#define BUFFER_HEIGHT 32
#define DDRAM_LINE_1 0x00
#define DDRAM_LINE_2 0x10
#define DDRAM_LINE_3 0x08
#define DDRAM_LINE_4 0x18
ST7920_Lite_Status_Screen::st7920_state_t ST7920_Lite_Status_Screen::current_bits;
void ST7920_Lite_Status_Screen::cmd(const uint8_t cmd) {
if (!current_bits.synced || !current_bits.cmd) {
current_bits.synced = true;
current_bits.cmd = true;
sync_cmd();
}
write_byte(cmd);
}
void ST7920_Lite_Status_Screen::begin_data() {
if (!current_bits.synced || current_bits.cmd) {
current_bits.synced = true;
current_bits.cmd = false;
sync_dat();
}
}
void ST7920_Lite_Status_Screen::write_str(const char *str) {
while (*str) write_byte(*str++);
}
void ST7920_Lite_Status_Screen::write_str(const char *str, uint8_t len) {
while (*str && len--) write_byte(*str++);
}
void ST7920_Lite_Status_Screen::write_str_P(const char * const str) {
const char *p_str = (const char *)str;
while (char c = pgm_read_byte_near(p_str++)) write_byte(c);
}
void ST7920_Lite_Status_Screen::write_str(progmem_str str) {
write_str_P((const char*)str);
}
void ST7920_Lite_Status_Screen::write_number(const int16_t value, const uint8_t digits/*=3*/) {
char str[7];
const char *fmt;
switch (digits) {
case 6: fmt = PSTR("%6d"); break;
case 5: fmt = PSTR("%5d"); break;
case 4: fmt = PSTR("%4d"); break;
case 3: fmt = PSTR("%3d"); break;
case 2: fmt = PSTR("%2d"); break;
case 1: fmt = PSTR("%1d"); break;
}
sprintf_P(str, fmt, value);
write_str(str);
}
void ST7920_Lite_Status_Screen::display_status(const bool display_on, const bool cursor_on, const bool blink_on) {
extended_function_set(false);
cmd(0b00001000 |
(display_on ? 0b0100 : 0) |
(cursor_on ? 0b0010 : 0) |
(blink_on ? 0b0001 : 0)
);
}
// Sets the extended and graphics bits simultaneously, regardless of
// the current state. This is a helper function for extended_function_set()
// and graphics()
void ST7920_Lite_Status_Screen::_extended_function_set(const bool extended, const bool graphics) {
cmd( 0b00100000 |
(extended ? 0b00000100 : 0) |
(graphics ? 0b00000010 : 0)
);
current_bits.extended = extended;
current_bits.graphics = graphics;
}
void ST7920_Lite_Status_Screen::extended_function_set(const bool extended) {
if (extended != current_bits.extended)
_extended_function_set(extended, current_bits.graphics);
}
void ST7920_Lite_Status_Screen::graphics(const bool graphics) {
if (graphics != current_bits.graphics)
_extended_function_set(current_bits.extended, graphics);
}
void ST7920_Lite_Status_Screen::entry_mode_select(const bool ac_increase, const bool shift) {
extended_function_set(false);
cmd(0b00000100 |
(ac_increase ? 0b00000010 : 0) |
(shift ? 0b00000001 : 0)
);
}
// Sets the sa bit regardless of the current state. This is a helper
// function for scroll_or_addr_select()
void ST7920_Lite_Status_Screen::_scroll_or_addr_select(const bool sa) {
extended_function_set(true);
cmd(0b00100010 |
(sa ? 0b000001 : 0)
);
current_bits.sa = sa;
}
void ST7920_Lite_Status_Screen::scroll_or_addr_select(const bool sa) {
if (sa != current_bits.sa)
_scroll_or_addr_select(sa);
}
void ST7920_Lite_Status_Screen::set_ddram_address(const uint8_t addr) {
extended_function_set(false);
cmd(0b10000000 | (addr & 0b00111111));
}
void ST7920_Lite_Status_Screen::set_cgram_address(const uint8_t addr) {
extended_function_set(false);
cmd(0b01000000 | (addr & 0b00111111));
}
void ST7920_Lite_Status_Screen::set_gdram_address(const uint8_t x, const uint8_t y) {
extended_function_set(true);
cmd(0b10000000 | (y & 0b01111111));
cmd(0b10000000 | (x & 0b00001111));
}
void ST7920_Lite_Status_Screen::clear() {
extended_function_set(false);
cmd(0x00000001);
delay(15); //delay for CGRAM clear
}
void ST7920_Lite_Status_Screen::home() {
extended_function_set(false);
cmd(0x00000010);
}
/* This fills the entire text buffer with spaces */
void ST7920_Lite_Status_Screen::clear_ddram() {
set_ddram_address(DDRAM_LINE_1);
begin_data();
for (uint8_t i = 64; i--;) write_byte(' ');
}
/* This fills the entire graphics buffer with zeros */
void ST7920_Lite_Status_Screen::clear_gdram() {
for (uint8_t y = 0; y < BUFFER_HEIGHT; y++) {
set_gdram_address(0, y);
begin_data();
for (uint8_t i = (BUFFER_WIDTH) / 16; i--;) write_word(0);
}
}
void ST7920_Lite_Status_Screen::load_cgram_icon(const uint16_t addr, const void *data) {
const uint16_t *p_word = (const uint16_t *)data;
set_cgram_address(addr);
begin_data();
for (uint8_t i = 16; i--;)
write_word(pgm_read_word_near(p_word++));
}
/**
* Draw an icon in GDRAM. Position specified in DDRAM
* coordinates. i.e., X from 1 to 8, Y from 1 to 4.
*/
void ST7920_Lite_Status_Screen::draw_gdram_icon(uint8_t x, uint8_t y, const void *data) {
const uint16_t *p_word = (const uint16_t *)data;
if (y > 2) { // Handle display folding
y -= 2;
x += 8;
}
--x;
--y;
for (int i = 0; i < 16; i++) {
set_gdram_address(x, i + y * 16);
begin_data();
write_word(pgm_read_word_near(p_word++));
}
}
/************************** ICON DEFINITIONS *************************************/
#define CGRAM_ICON_1_ADDR 0x00
#define CGRAM_ICON_2_ADDR 0x10
#define CGRAM_ICON_3_ADDR 0x20
#define CGRAM_ICON_4_ADDR 0x30
#define CGRAM_ICON_1_WORD 0x00
#define CGRAM_ICON_2_WORD 0x02
#define CGRAM_ICON_3_WORD 0x04
#define CGRAM_ICON_4_WORD 0x06
const uint8_t degree_symbol_y_top = 1;
PROGMEM const uint8_t degree_symbol[] = {
0b00110000,
0b01001000,
0b01001000,
0b00110000,
};
const uint16_t nozzle_icon[] PROGMEM = {
0b0000000000000000,
0b0000000000000000,
0b0000111111110000,
0b0001111111111000,
0b0001111111111000,
0b0001111111111000,
0b0000111111110000,
0b0000111111110000,
0b0001111111111000,
0b0001111111111000,
0b0001111111111000,
0b0000011111100000,
0b0000001111000000,
0b0000000110000000,
0b0000000000000000,
0b0000000000000000
};
const uint16_t bed_icon[] PROGMEM = {
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0111111111111110,
0b0111111111111110,
0b0110000000000110,
0b0000000000000000,
0b0000000000000000
};
const uint16_t heat1_icon[] PROGMEM = {
0b0000000000000000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0010001000100000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
};
const uint16_t heat2_icon[] PROGMEM = {
0b0000000000000000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0010001000100000,
0b0010001000100000,
0b0001000100010000,
0b0000100010001000,
0b0000100010001000,
0b0001000100010000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000,
0b0000000000000000
};
const uint16_t fan1_icon[] PROGMEM = {
0b0000000000000000,
0b0111111111111110,
0b0111000000001110,
0b0110001111000110,
0b0100001111000010,
0b0100000110000010,
0b0101100000011010,
0b0101110110111010,
0b0101100000011010,
0b0100000110000010,
0b0100001111000010,
0b0110001111000110,
0b0111000000001110,
0b0111111111111110,
0b0000000000000000,
0b0000000000000000
};
const uint16_t fan2_icon[] PROGMEM = {
0b0000000000000000,
0b0111111111111110,
0b0111000000001110,
0b0110010000100110,
0b0100111001110010,
0b0101111001111010,
0b0100110000110010,
0b0100000110000010,
0b0100110000110010,
0b0101111001111010,
0b0100111001110010,
0b0110010000100110,
0b0111000000001110,
0b0111111111111110,
0b0000000000000000,
0b0000000000000000
};
const uint16_t feedrate_icon[] PROGMEM = {
0b0000000000000000,
0b0111111000000000,
0b0110000000000000,
0b0110000000000000,
0b0110000000000000,
0b0111111011111000,
0b0110000011001100,
0b0110000011001100,
0b0110000011001100,
0b0110000011111000,
0b0000000011001100,
0b0000000011001100,
0b0000000011001100,
0b0000000011001100,
0b0000000000000000,
0b0000000000000000
};
/************************** MAIN SCREEN *************************************/
// The ST7920 does not have a degree character, but we
// can fake it by writing it to GDRAM.
// This function takes as an argument character positions
// i.e x is [1-16], while the y position is [1-4]
void ST7920_Lite_Status_Screen::draw_degree_symbol(uint8_t x, uint8_t y, bool draw) {
const uint8_t *p_bytes = degree_symbol;
if (y > 2) {
// Handle display folding
y -= 2;
x += 16;
}
x -= 1;
y -= 1;
const bool oddChar = x & 1;
const uint8_t x_word = x >> 1;
const uint8_t y_top = degree_symbol_y_top;
const uint8_t y_bot = y_top + sizeof(degree_symbol)/sizeof(degree_symbol[0]);
for (uint8_t i = y_top; i < y_bot; i++) {
uint8_t byte = pgm_read_byte_near(p_bytes++);
set_gdram_address(x_word,i+y*16);
begin_data();
if (draw) {
write_byte(oddChar ? 0x00 : byte);
write_byte(oddChar ? byte : 0x00);
}
else
write_word(0x0000);
}
}
void ST7920_Lite_Status_Screen::draw_static_elements() {
scroll_or_addr_select(0);
// Load the animated bed and fan icons
load_cgram_icon(CGRAM_ICON_1_ADDR, heat1_icon);
load_cgram_icon(CGRAM_ICON_2_ADDR, heat2_icon);
load_cgram_icon(CGRAM_ICON_3_ADDR, fan1_icon);
load_cgram_icon(CGRAM_ICON_4_ADDR, fan2_icon);
// Draw the static icons in GDRAM
draw_gdram_icon(1, 1, nozzle_icon);
#if HOTENDS > 1
draw_gdram_icon(1,2,nozzle_icon);
draw_gdram_icon(1,3,bed_icon);
#else
draw_gdram_icon(1,2,bed_icon);
#endif
draw_gdram_icon(6,2,feedrate_icon);
// Draw the initial fan icon
draw_fan_icon(false);
}
/**
* Although this is undocumented, the ST7920 allows the character
* data buffer (DDRAM) to be used in conjunction with the graphics
* bitmap buffer (CGRAM). The contents of the graphics buffer is
* XORed with the data from the character generator. This allows
* us to make the progess bar out of graphical data (the bar) and
* text data (the percentage).
*/
void ST7920_Lite_Status_Screen::draw_progress_bar(const uint8_t value) {
#if HOTENDS == 1
// If we have only one extruder, draw a long progress bar on the third line
const uint8_t top = 1, // Top in pixels
bottom = 13, // Bottom in pixels
left = 12, // Left edge, in 16-bit words
width = 4; // Width of progress bar, in 16-bit words
#else
const uint8_t top = 16 + 1,
bottom = 16 + 13,
left = 5,
width = 3;
#endif
const uint8_t char_pcnt = 100 / width; // How many percent does each 16-bit word represent?
// Draw the progress bar as a bitmap in CGRAM
for (uint8_t y = top; y <= bottom; y++) {
set_gdram_address(left, y);
begin_data();
for (uint8_t x = 0; x < width; x++) {
uint16_t gfx_word = 0x0000;
if ((x + 1) * char_pcnt <= value)
gfx_word = 0xFFFF; // Draw completely filled bytes
else if ((x * char_pcnt) < value)
gfx_word = int(0x8000) >> (value % char_pcnt) * 16 / char_pcnt; // Draw partially filled bytes
// Draw the frame around the progress bar
if (y == top || y == bottom)
gfx_word = 0xFFFF; // Draw top/bottom border
else if (x == width - 1)
gfx_word |= 0x0001; // Draw right border
else if (x == 0)
gfx_word |= 0x8000; // Draw left border
write_word(gfx_word);
}
}
// Draw the percentage as text in DDRAM
#if HOTENDS == 1
set_ddram_address(DDRAM_LINE_3 + 4);
begin_data();
write_byte(' ');
#else
set_ddram_address(DDRAM_LINE_2 + left);
begin_data();
#endif
// Draw centered
if (value > 9) {
write_number(value, 4);
write_str(F("% "));
}
else {
write_number(value, 3);
write_str(F("% "));
}
}
void ST7920_Lite_Status_Screen::draw_fan_icon(const bool whichIcon) {
set_ddram_address(DDRAM_LINE_1 + 5);
begin_data();
write_word(whichIcon ? CGRAM_ICON_3_WORD : CGRAM_ICON_4_WORD);
}
void ST7920_Lite_Status_Screen::draw_heat_icon(const bool whichIcon, const bool heating) {
set_ddram_address(
#if HOTENDS == 1
DDRAM_LINE_2
#else
DDRAM_LINE_3
#endif
);
begin_data();
if (heating)
write_word(whichIcon ? CGRAM_ICON_1_WORD : CGRAM_ICON_2_WORD);
else {
write_byte(' ');
write_byte(' ');
}
}
#define FAR(a,b) (((a > b) ? (a-b) : (b-a)) > 2)
static struct {
bool E1_show_target : 1;
bool E2_show_target : 1;
#if HAS_HEATED_BED
bool bed_show_target : 1;
#endif
} display_state = {
true, true
#if HAS_HEATED_BED
, true
#endif
};
void ST7920_Lite_Status_Screen::draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange) {
switch (line) {
case 1: set_ddram_address(DDRAM_LINE_1 + 1); break;
case 2: set_ddram_address(DDRAM_LINE_2 + 1); break;
case 3: set_ddram_address(DDRAM_LINE_3 + 1); break;
case 4: set_ddram_address(DDRAM_LINE_3 + 1); break;
}
begin_data();
write_number(temp);
if (showTarget) {
write_str(F("\x1A"));
write_number(target);
};
if (targetStateChange) {
if (!showTarget) write_str(F(" "));
draw_degree_symbol(6, line, !showTarget);
draw_degree_symbol(10, line, showTarget);
}
}
void ST7920_Lite_Status_Screen::draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(1, temp, target, show_target, display_state.E1_show_target != show_target || forceUpdate);
display_state.E1_show_target = show_target;
}
void ST7920_Lite_Status_Screen::draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(2, temp, target, show_target, display_state.E2_show_target != show_target || forceUpdate);
display_state.E2_show_target = show_target;
}
#if HAS_HEATED_BED
void ST7920_Lite_Status_Screen::draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate) {
const bool show_target = target && FAR(temp, target);
draw_temps(2
#if HOTENDS > 1
+ 1
#endif
, temp, target, show_target, display_state.bed_show_target != show_target || forceUpdate
);
display_state.bed_show_target = show_target;
}
#endif
void ST7920_Lite_Status_Screen::draw_fan_speed(const uint8_t value) {
set_ddram_address(DDRAM_LINE_1 + 6);
begin_data();
write_number(value, 3);
write_byte('%');
}
void ST7920_Lite_Status_Screen::draw_print_time(const duration_t &elapsed) {
#if HOTENDS == 1
set_ddram_address(DDRAM_LINE_3);
#else
set_ddram_address(DDRAM_LINE_3 + 5);
#endif
char str[7];
str[elapsed.toDigital(str)] = ' ';
begin_data();
write_str(str, 6);
}
void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint8_t percentage) {
// We only have enough room for the feedrate when
// we have one extruder
#if HOTENDS == 1
set_ddram_address(DDRAM_LINE_2 + 6);
begin_data();
write_number(percentage, 3);
write_byte('%');
#endif
}
void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
set_ddram_address(DDRAM_LINE_4);
begin_data();
const uint8_t lcd_len = 16;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
uint8_t slen = utf8_strlen(str);
// If the string fits into the LCD, just print it and do not scroll it
if (slen <= lcd_len) {
// The string isn't scrolling and may not fill the screen
write_str(str);
// Fill the rest with spaces
while (slen < lcd_len) {
write_byte(' ');
++slen;
}
}
else {
// String is larger than the available space in screen.
// Get a pointer to the next valid UTF8 character
const char *stat = str + status_scroll_offset;
// Get the string remaining length
const uint8_t rlen = utf8_strlen(stat);
// If we have enough characters to display
if (rlen >= lcd_len) {
// The remaining string fills the screen - Print it
write_str(stat, lcd_len);
}
else {
// The remaining string does not completely fill the screen
write_str(stat); // The string leaves space
uint8_t chars = lcd_len - rlen; // Amount of space left in characters
write_byte('.'); // Always at 1+ spaces left, draw a dot
if (--chars) { // Draw a second dot if there's space
write_byte('.');
if (--chars)
write_str(str, chars); // Print a second copy of the message
}
}
// Adjust by complete UTF8 characters
if (status_scroll_offset < slen) {
status_scroll_offset++;
while (!START_OF_UTF8_CHAR(str[status_scroll_offset]))
status_scroll_offset++;
}
else
status_scroll_offset = 0;
}
#else
// Get the UTF8 character count of the string
uint8_t slen = utf8_strlen(str);
// Just print the string to the LCD
write_str(str, lcd_len);
// Fill the rest with spaces if there are missing spaces
while (slen < lcd_len) {
write_byte(' ');
++slen;
}
#endif
}
void ST7920_Lite_Status_Screen::draw_position(const float x, const float y, const float z, bool position_known) {
char str[7];
set_ddram_address(DDRAM_LINE_4);
begin_data();
// If position is unknown, flash the labels.
const unsigned char alt_label = position_known ? 0 : (lcd_blink() ? ' ' : 0);
dtostrf(x, -4, 0, str);
write_byte(alt_label ? alt_label : 'X');
write_str(str, 4);
dtostrf(y, -4, 0, str);
write_byte(alt_label ? alt_label : 'Y');
write_str(str, 4);
dtostrf(z, -5, 1, str);
write_byte(alt_label ? alt_label : 'Z');
write_str(str, 5);
}
bool ST7920_Lite_Status_Screen::indicators_changed() {
// We only add the target temperatures to the checksum
// because the actual temps fluctuate so by updating
// them only during blinks we gain a bit of stability.
const bool blink = lcd_blink();
const uint8_t feedrate_perc = feedrate_percentage;
const uint8_t fan_speed = ((fanSpeeds[0] + 1) * 100) / 256;
const int16_t extruder_1_target = thermalManager.degTargetHotend(0);
#if HOTENDS > 1
const int16_t extruder_2_target = thermalManager.degTargetHotend(1);
#endif
#if HAS_HEATED_BED
const int16_t bed_target = thermalManager.degTargetBed();
#endif
static uint16_t last_checksum = 0;
const uint16_t checksum = blink ^ feedrate_perc ^ fan_speed ^ extruder_1_target
#if HOTENDS > 1
^ extruder_2_target
#endif
#if HAS_HEATED_BED
^ bed_target
#endif
;
if (last_checksum == checksum) return false;
last_checksum = checksum;
return true;
}
void ST7920_Lite_Status_Screen::update_indicators(const bool forceUpdate) {
if (forceUpdate || indicators_changed()) {
const bool blink = lcd_blink();
const duration_t elapsed = print_job_timer.duration();
const uint8_t feedrate_perc = feedrate_percentage;
const uint8_t fan_speed = ((fanSpeeds[0] + 1) * 100) / 256;
const int16_t extruder_1_temp = thermalManager.degHotend(0),
extruder_1_target = thermalManager.degTargetHotend(0);
#if HOTENDS > 1
const int16_t extruder_2_temp = thermalManager.degHotend(1),
extruder_2_target = thermalManager.degTargetHotend(1);
#endif
#if HAS_HEATED_BED
const int16_t bed_temp = thermalManager.degBed(),
bed_target = thermalManager.degTargetBed();
#endif
draw_extruder_1_temp(extruder_1_temp, extruder_1_target, forceUpdate);
#if HOTENDS > 1
draw_extruder_2_temp(extruder_2_temp, extruder_2_target, forceUpdate);
#endif
#if HAS_HEATED_BED
draw_bed_temp(bed_temp, bed_target, forceUpdate);
#endif
draw_fan_speed(fan_speed);
draw_print_time(elapsed);
draw_feedrate_percentage(feedrate_perc);
// Update the fan and bed animations
if (fan_speed > 0) draw_fan_icon(blink);
#if HAS_HEATED_BED
if (bed_target > 0)
draw_heat_icon(blink, true);
else
draw_heat_icon(false, false);
#endif
}
}
bool ST7920_Lite_Status_Screen::position_changed() {
const float x_pos = current_position[X_AXIS],
y_pos = current_position[Y_AXIS],
z_pos = current_position[Z_AXIS];
const uint8_t checksum = uint8_t(x_pos) ^ uint8_t(y_pos) ^ uint8_t(z_pos);
static uint8_t last_checksum = 0;
if (last_checksum == checksum) return false;
last_checksum = checksum;
return true;
}
bool ST7920_Lite_Status_Screen::status_changed() {
uint8_t checksum = 0;
for (const char *p = lcd_status_message; *p; p++) checksum ^= *p;
static uint8_t last_checksum = 0;
if (last_checksum == checksum) return false;
last_checksum = checksum;
return true;
}
bool ST7920_Lite_Status_Screen::blink_changed() {
static uint8_t last_blink = 0;
const bool blink = lcd_blink();
if (last_blink == blink) return false;
last_blink = blink;
return true;
}
#ifndef STATUS_EXPIRE_SECONDS
#define STATUS_EXPIRE_SECONDS 20
#endif
void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
#if STATUS_EXPIRE_SECONDS
static uint8_t countdown = 0;
#endif
/**
* There is only enough room in the display for either the
* status message or the position, not both, so we choose
* one or another. Whenever the status message changes,
* we show it for a number of consecutive seconds, but
* then go back to showing the position as soon as the
* head moves, i.e:
*
* countdown > 1 -- Show status
* countdown = 1 -- Show status, until movement
* countdown = 0 -- Show position
*
* If STATUS_EXPIRE_SECONDS is zero, the position display
* will be disabled and only the status will be shown.
*/
if (forceUpdate || status_changed()) {
#if ENABLED(STATUS_MESSAGE_SCROLLING)
status_scroll_offset = 0;
#endif
#if STATUS_EXPIRE_SECONDS
countdown = lcd_status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
#endif
draw_status_message(lcd_status_message);
blink_changed(); // Clear changed flag
}
#if !STATUS_EXPIRE_SECONDS
#if ENABLED(STATUS_MESSAGE_SCROLLING)
else
draw_status_message(lcd_status_message);
#endif
#else
else if (countdown > 1 && blink_changed()) {
countdown--;
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message(lcd_status_message);
#endif
}
else if (countdown > 0 && blink_changed()) {
if (position_changed()) {
countdown--;
forceUpdate = true;
}
#if ENABLED(STATUS_MESSAGE_SCROLLING)
draw_status_message(lcd_status_message);
#endif
}
if (countdown == 0 && (forceUpdate || position_changed() ||
#if DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
blink_changed()
#endif
)) {
draw_position(
current_position[X_AXIS],
current_position[Y_AXIS],
current_position[Z_AXIS],
#if ENABLED(DISABLE_REDUCED_ACCURACY_WARNING)
true
#else
all_axes_known()
#endif
);
}
#endif
}
void ST7920_Lite_Status_Screen::update_progress(const bool forceUpdate) {
#if ENABLED(LCD_SET_PROGRESS_MANUALLY) || ENABLED(SDSUPPORT)
#if DISABLED(LCD_SET_PROGRESS_MANUALLY)
uint8_t progress_bar_percent = 0;
#endif
#if ENABLED(SDSUPPORT)
// Progress bar % comes from SD when actively printing
if (IS_SD_PRINTING()) progress_bar_percent = card.percentDone();
#endif
// Since the progress bar involves writing
// quite a few bytes to GDRAM, only do this
// when an update is actually necessary.
static uint8_t last_progress = 0;
if (!forceUpdate && last_progress == progress_bar_percent) return;
last_progress = progress_bar_percent;
draw_progress_bar(progress_bar_percent);
#else
UNUSED(forceUpdate);
#endif // LCD_SET_PROGRESS_MANUALLY || SDSUPPORT
}
void ST7920_Lite_Status_Screen::update(const bool forceUpdate) {
cs();
update_indicators(forceUpdate);
update_status_or_position(forceUpdate);
update_progress(forceUpdate);
ncs();
}
void ST7920_Lite_Status_Screen::reset_state_from_unknown() {
_extended_function_set(true, true); // Do it twice as only one bit
_extended_function_set(true, true); // get set at a time.
_scroll_or_addr_select(false);
}
void ST7920_Lite_Status_Screen::on_entry() {
cs();
reset_state_from_unknown();
clear();
clear_gdram();
draw_static_elements();
update(true);
ncs();
}
void ST7920_Lite_Status_Screen::on_exit() {
cs();
clear();
_extended_function_set(true, true); // Restore state to what u8g expects.
ncs();
}
// This is called prior to the KILL screen to
// clear the screen so we don't end up with a
// garbled display.
void ST7920_Lite_Status_Screen::clear_text_buffer() {
cs();
reset_state_from_unknown();
clear();
_extended_function_set(true, true); // Restore state to what u8g expects.
ncs();
}
static void lcd_implementation_status_screen() {
ST7920_Lite_Status_Screen::update(false);
}
/**
* In order to properly update the lite Status Screen,
* we must know when we have entered and left the
* Status Screen. Since the ultralcd code is not
* set up for doing this, we call this function before
* each update indicating whether the current screen
* is the Status Screen.
*
* This function keeps track of whether we have left or
* entered the Status Screen and calls the on_entry()
* and on_exit() methods for cleanup.
*/
static void lcd_in_status(const bool inStatus) {
static bool lastInStatus = false;
if (lastInStatus == inStatus) return;
if ((lastInStatus = inStatus))
ST7920_Lite_Status_Screen::on_entry();
else
ST7920_Lite_Status_Screen::on_exit();
}

View File

@@ -1,111 +0,0 @@
/**
* Lightweight Status Screen for the RepRapDiscount Full
* Graphics Smart Controller (ST7920-based 128x64 LCD)
*
* (c) 2017 Aleph Objects, Inc.
*
* The code in this page is free software: you can
* redistribute it and/or modify it under the terms of the GNU
* General Public License (GNU GPL) as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version. The code is distributed WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
*
*/
#ifndef STATUS_SCREEN_LITE_ST7920_CLASS_H
#define STATUS_SCREEN_LITE_ST7920_CLASS_H
#include "macros.h"
#include "duration_t.h"
typedef const __FlashStringHelper *progmem_str;
class ST7920_Lite_Status_Screen {
private:
static struct st7920_state_t {
uint8_t synced : 1; // Whether a sync has been sent
uint8_t cmd : 1; // Whether the sync was cmd or data
uint8_t extended : 1;
uint8_t graphics : 1;
uint8_t sa : 1;
} current_bits;
static void cs();
static void ncs();
static void sync_cmd();
static void sync_dat();
static void write_byte(const uint8_t w);
FORCE_INLINE static void write_word(const uint16_t w) {
write_byte((w >> 8) & 0xFF);
write_byte((w >> 0) & 0xFF);
}
static void cmd(const uint8_t cmd);
static void begin_data();
static void write_str(const char *str);
static void write_str(const char *str, const uint8_t len);
static void write_str_P(const char * const str);
static void write_str(progmem_str str);
static void write_number(const int16_t value, const uint8_t digits=3);
static void _extended_function_set(const bool extended, const bool graphics);
static void _scroll_or_addr_select(const bool sa);
static void reset_state_from_unknown();
static void home();
static void display_status(const bool display_on, const bool cursor_on, const bool blink_on);
static void extended_function_set(const bool extended);
static void graphics(const bool graphics);
static void entry_mode_select(const bool ac_increase, const bool shift);
static void scroll_or_addr_select(const bool sa);
static void set_ddram_address(const uint8_t addr);
static void set_cgram_address(const uint8_t addr);
static void set_gdram_address(const uint8_t x, const uint8_t y);
static void clear();
static void clear_ddram();
static void clear_gdram();
static void load_cgram_icon(const uint16_t addr, const void *data);
static void draw_gdram_icon(uint8_t x, uint8_t y, const void *data);
static uint8_t string_checksum(const char *str);
protected:
static void draw_degree_symbol(uint8_t x, uint8_t y, bool draw);
static void draw_static_elements();
static void draw_progress_bar(const uint8_t value);
static void draw_fan_icon(const bool whichIcon);
static void draw_heat_icon(const bool whichIcon, const bool heating);
static void draw_temps(uint8_t line, const int16_t temp, const int16_t target, bool showTarget, bool targetStateChange);
static void draw_extruder_1_temp(const int16_t temp, const int16_t target, bool forceUpdate = false);
static void draw_extruder_2_temp(const int16_t temp, const int16_t target, bool forceUpdate = false);
static void draw_bed_temp(const int16_t temp, const int16_t target, bool forceUpdate = false);
static void draw_fan_speed(const uint8_t value);
static void draw_print_time(const duration_t &elapsed);
static void draw_feedrate_percentage(const uint8_t percentage);
static void draw_status_message(const char *str);
static void draw_position(const float x, const float y, const float z, bool position_known = true);
static bool indicators_changed();
static bool position_changed();
static bool blink_changed();
static bool status_changed();
static void update_indicators(const bool forceUpdate);
static void update_position(const bool forceUpdate, bool resetChecksum);
static void update_status_or_position(bool forceUpdate);
static void update_progress(const bool forceUpdate);
public:
static void update(const bool forceUpdate);
static void on_entry();
static void on_exit();
static void clear_text_buffer();
};
#endif // STATUS_SCREEN_LITE_ST7920_CLASS_H

View File

@@ -1,39 +0,0 @@
/**
* Lightweight Status Screen for the RepRapDiscount Full
* Graphics Smart Controller (ST7920-based 128x64 LCD)
*
* (c) 2017 Aleph Objects, Inc.
*
* The code in this page is free software: you can
* redistribute it and/or modify it under the terms of the GNU
* General Public License (GNU GPL) as published by the Free Software
* Foundation, either version 3 of the License, or (at your option)
* any later version. The code is distributed WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
*
*/
#include "status_screen_lite_ST7920_class.h"
void ST7920_Lite_Status_Screen::cs() {
ST7920_CS();
current_bits.synced = false;
}
void ST7920_Lite_Status_Screen::ncs() {
ST7920_NCS();
current_bits.synced = false;
}
void ST7920_Lite_Status_Screen::sync_cmd() {
ST7920_SET_CMD();
}
void ST7920_Lite_Status_Screen::sync_dat() {
ST7920_SET_DAT();
}
void ST7920_Lite_Status_Screen::write_byte(const uint8_t data) {
ST7920_WRITE_BYTE(data);
}

View File

@@ -1,64 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// 100k bed thermistor in JGAurora A5. Calibrated by Sam Pinches 21st Jan 2018 using cheap k-type thermocouple inserted into heater block, using TM-902C meter.
const short temptable_15[][2] PROGMEM = {
{ OV( 31), 275 },
{ OV( 33), 270 },
{ OV( 35), 260 },
{ OV( 38), 253 },
{ OV( 41), 248 },
{ OV( 48), 239 },
{ OV( 56), 232 },
{ OV( 66), 222 },
{ OV( 78), 212 },
{ OV( 93), 206 },
{ OV( 106), 199 },
{ OV( 118), 191 },
{ OV( 130), 186 },
{ OV( 158), 176 },
{ OV( 187), 167 },
{ OV( 224), 158 },
{ OV( 270), 148 },
{ OV( 321), 137 },
{ OV( 379), 127 },
{ OV( 446), 117 },
{ OV( 518), 106 },
{ OV( 593), 96 },
{ OV( 668), 86 },
{ OV( 739), 76 },
{ OV( 767), 72 },
{ OV( 830), 62 },
{ OV( 902), 48 },
{ OV( 926), 45 },
{ OV( 955), 35 },
{ OV( 966), 30 },
{ OV( 977), 25 },
{ OV( 985), 20 },
{ OV( 993), 15 },
{ OV( 999), 10 },
{ OV(1004), 5 },
{ OV(1008), 0 },
{ OV(1012), -5 },
{ OV(1016), -10 },
{ OV(1020), -15 }
};

View File

@@ -1,57 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// 100k Zonestar thermistor. Adjusted By Hally
const short temptable_501[][2] PROGMEM = {
{OV( 1), 713},
{OV( 14), 300}, // Top rating 300C
{OV( 16), 290},
{OV( 19), 280},
{OV( 23), 270},
{OV( 27), 260},
{OV( 31), 250},
{OV( 37), 240},
{OV( 47), 230},
{OV( 57), 220},
{OV( 68), 210},
{OV( 84), 200},
{OV( 100), 190},
{OV( 128), 180},
{OV( 155), 170},
{OV( 189), 160},
{OV( 230), 150},
{OV( 278), 140},
{OV( 336), 130},
{OV( 402), 120},
{OV( 476), 110},
{OV( 554), 100},
{OV( 635), 90},
{OV( 713), 80},
{OV( 784), 70},
{OV( 846), 60},
{OV( 897), 50},
{OV( 937), 40},
{OV( 966), 30},
{OV( 986), 20},
{OV(1000), 10},
{OV(1010), 0}
};

View File

@@ -1,631 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "MarlinConfig.h"
#if HAS_TRINAMIC
#include "tmc_util.h"
#include "Marlin.h"
#include "printcounter.h"
#include "duration_t.h"
#include "stepper_indirection.h"
#if ENABLED(TMC_DEBUG)
#include "planner.h"
#endif
bool report_tmc_status = false;
/**
* Check for over temperature or short to ground error flags.
* Report and log warning of overtemperature condition.
* Reduce driver current in a persistent otpw condition.
* Keep track of otpw counter so we don't reduce current on a single instance,
* and so we don't repeatedly report warning before the condition is cleared.
*/
#if ENABLED(MONITOR_DRIVER_STATUS)
struct TMC_driver_data {
uint32_t drv_status;
bool is_otpw;
bool is_ot;
bool is_error;
};
#if HAS_DRIVER(TMC2130)
static uint32_t get_pwm_scale(TMC2130Stepper &st) { return st.PWM_SCALE(); }
static uint8_t get_status_response(TMC2130Stepper &st) { return st.status_response & 0xF; }
static TMC_driver_data get_driver_data(TMC2130Stepper &st) {
constexpr uint32_t OTPW_bm = 0x4000000UL;
constexpr uint8_t OTPW_bp = 26;
constexpr uint32_t OT_bm = 0x2000000UL;
constexpr uint8_t OT_bp = 25;
constexpr uint8_t DRIVER_ERROR_bm = 0x2UL;
constexpr uint8_t DRIVER_ERROR_bp = 1;
TMC_driver_data data;
data.drv_status = st.DRV_STATUS();
data.is_otpw = (data.drv_status & OTPW_bm) >> OTPW_bp;
data.is_ot = (data.drv_status & OT_bm) >> OT_bp;
data.is_error = (st.status_response & DRIVER_ERROR_bm) >> DRIVER_ERROR_bp;
return data;
}
#endif
#if HAS_DRIVER(TMC2208)
static uint32_t get_pwm_scale(TMC2208Stepper &st) { return st.pwm_scale_sum(); }
static uint8_t get_status_response(TMC2208Stepper &st) {
uint32_t drv_status = st.DRV_STATUS();
uint8_t gstat = st.GSTAT();
uint8_t response = 0;
response |= (drv_status >> (31-3)) & 0b1000;
response |= gstat & 0b11;
return response;
}
static TMC_driver_data get_driver_data(TMC2208Stepper &st) {
constexpr uint32_t OTPW_bm = 0b1ul;
constexpr uint8_t OTPW_bp = 0;
constexpr uint32_t OT_bm = 0b10ul;
constexpr uint8_t OT_bp = 1;
TMC_driver_data data;
data.drv_status = st.DRV_STATUS();
data.is_otpw = (data.drv_status & OTPW_bm) >> OTPW_bp;
data.is_ot = (data.drv_status & OT_bm) >> OT_bp;
data.is_error = st.drv_err();
return data;
}
#endif
template<typename TMC>
void monitor_tmc_driver(TMC &st, const TMC_AxisEnum axis, uint8_t &otpw_cnt) {
TMC_driver_data data = get_driver_data(st);
#if ENABLED(STOP_ON_ERROR)
if (data.is_error) {
SERIAL_EOL();
_tmc_say_axis(axis);
SERIAL_ECHOLNPGM(" driver error detected:");
if (data.is_ot) SERIAL_ECHOLNPGM("overtemperature");
if (st.s2ga()) SERIAL_ECHOLNPGM("short to ground (coil A)");
if (st.s2gb()) SERIAL_ECHOLNPGM("short to ground (coil B)");
#if ENABLED(TMC_DEBUG)
tmc_report_all();
#endif
kill(PSTR("Driver error"));
}
#endif
// Report if a warning was triggered
if (data.is_otpw && otpw_cnt == 0) {
char timestamp[10];
duration_t elapsed = print_job_timer.duration();
const bool has_days = (elapsed.value > 60*60*24L);
(void)elapsed.toDigital(timestamp, has_days);
SERIAL_EOL();
SERIAL_ECHO(timestamp);
SERIAL_ECHOPGM(": ");
_tmc_say_axis(axis);
SERIAL_ECHOPGM(" driver overtemperature warning! (");
SERIAL_ECHO(st.getCurrent());
SERIAL_ECHOLNPGM("mA)");
}
#if CURRENT_STEP_DOWN > 0
// Decrease current if is_otpw is true and driver is enabled and there's been more than 4 warnings
if (data.is_otpw && st.isEnabled() && otpw_cnt > 4) {
st.setCurrent(st.getCurrent() - CURRENT_STEP_DOWN, R_SENSE, HOLD_MULTIPLIER);
#if ENABLED(REPORT_CURRENT_CHANGE)
_tmc_say_axis(axis);
SERIAL_ECHOLNPAIR(" current decreased to ", st.getCurrent());
#endif
}
#endif
if (data.is_otpw) {
otpw_cnt++;
st.flag_otpw = true;
}
else if (otpw_cnt > 0) otpw_cnt = 0;
if (report_tmc_status) {
const uint32_t pwm_scale = get_pwm_scale(st);
_tmc_say_axis(axis);
SERIAL_ECHOPAIR(":", pwm_scale);
SERIAL_ECHOPGM(" |0b"); SERIAL_PRINT(get_status_response(st), BIN);
SERIAL_ECHOPGM("| ");
if (data.is_error) SERIAL_CHAR('E');
else if (data.is_ot) SERIAL_CHAR('O');
else if (data.is_otpw) SERIAL_CHAR('W');
else if (otpw_cnt > 0) SERIAL_PRINT(otpw_cnt, DEC);
else if (st.flag_otpw) SERIAL_CHAR('F');
SERIAL_CHAR('\t');
}
}
#define HAS_HW_COMMS(ST) AXIS_DRIVER_TYPE(ST, TMC2130) || (AXIS_DRIVER_TYPE(ST, TMC2208) && defined(ST##_HARDWARE_SERIAL))
void monitor_tmc_driver() {
static millis_t next_cOT = 0;
if (ELAPSED(millis(), next_cOT)) {
next_cOT = millis() + 500;
#if HAS_HW_COMMS(X)
static uint8_t x_otpw_cnt = 0;
monitor_tmc_driver(stepperX, TMC_X, x_otpw_cnt);
#endif
#if HAS_HW_COMMS(Y)
static uint8_t y_otpw_cnt = 0;
monitor_tmc_driver(stepperY, TMC_Y, y_otpw_cnt);
#endif
#if HAS_HW_COMMS(Z)
static uint8_t z_otpw_cnt = 0;
monitor_tmc_driver(stepperZ, TMC_Z, z_otpw_cnt);
#endif
#if HAS_HW_COMMS(X2)
static uint8_t x2_otpw_cnt = 0;
monitor_tmc_driver(stepperX2, TMC_X, x2_otpw_cnt);
#endif
#if HAS_HW_COMMS(Y2)
static uint8_t y2_otpw_cnt = 0;
monitor_tmc_driver(stepperY2, TMC_Y, y2_otpw_cnt);
#endif
#if HAS_HW_COMMS(Z2)
static uint8_t z2_otpw_cnt = 0;
monitor_tmc_driver(stepperZ2, TMC_Z, z2_otpw_cnt);
#endif
#if HAS_HW_COMMS(E0)
static uint8_t e0_otpw_cnt = 0;
monitor_tmc_driver(stepperE0, TMC_E0, e0_otpw_cnt);
#endif
#if HAS_HW_COMMS(E1)
static uint8_t e1_otpw_cnt = 0;
monitor_tmc_driver(stepperE1, TMC_E1, e1_otpw_cnt);
#endif
#if HAS_HW_COMMS(E2)
static uint8_t e2_otpw_cnt = 0;
monitor_tmc_driver(stepperE2, TMC_E2, e2_otpw_cnt);
#endif
#if HAS_HW_COMMS(E3)
static uint8_t e3_otpw_cnt = 0;
monitor_tmc_driver(stepperE3, TMC_E3, e3_otpw_cnt);
#endif
#if HAS_HW_COMMS(E4)
static uint8_t e4_otpw_cnt = 0;
monitor_tmc_driver(stepperE4, TMC_E4, e4_otpw_cnt);
#endif
if (report_tmc_status) SERIAL_EOL();
}
}
#endif // MONITOR_DRIVER_STATUS
void _tmc_say_axis(const TMC_AxisEnum axis) {
static const char ext_X[] PROGMEM = "X", ext_Y[] PROGMEM = "Y", ext_Z[] PROGMEM = "Z",
ext_X2[] PROGMEM = "X2", ext_Y2[] PROGMEM = "Y2", ext_Z2[] PROGMEM = "Z2",
ext_E0[] PROGMEM = "E0", ext_E1[] PROGMEM = "E1",
ext_E2[] PROGMEM = "E2", ext_E3[] PROGMEM = "E3",
ext_E4[] PROGMEM = "E4";
static const char* const tmc_axes[] PROGMEM = { ext_X, ext_Y, ext_Z, ext_X2, ext_Y2, ext_Z2, ext_E0, ext_E1, ext_E2, ext_E3, ext_E4 };
serialprintPGM((char*)pgm_read_ptr(&tmc_axes[axis]));
}
void _tmc_say_current(const TMC_AxisEnum axis, const uint16_t curr) {
_tmc_say_axis(axis);
SERIAL_ECHOLNPAIR(" driver current: ", curr);
}
void _tmc_say_otpw(const TMC_AxisEnum axis, const bool otpw) {
_tmc_say_axis(axis);
SERIAL_ECHOPGM(" temperature prewarn triggered: ");
serialprintPGM(otpw ? PSTR("true") : PSTR("false"));
SERIAL_EOL();
}
void _tmc_say_otpw_cleared(const TMC_AxisEnum axis) {
_tmc_say_axis(axis);
SERIAL_ECHOLNPGM(" prewarn flag cleared");
}
void _tmc_say_pwmthrs(const TMC_AxisEnum axis, const uint32_t thrs) {
_tmc_say_axis(axis);
SERIAL_ECHOLNPAIR(" stealthChop max speed: ", thrs);
}
void _tmc_say_sgt(const TMC_AxisEnum axis, const int8_t sgt) {
_tmc_say_axis(axis);
SERIAL_ECHOPGM(" homing sensitivity: ");
SERIAL_PRINTLN(sgt, DEC);
}
#if ENABLED(TMC_DEBUG)
enum TMC_debug_enum : char {
TMC_CODES,
TMC_ENABLED,
TMC_CURRENT,
TMC_RMS_CURRENT,
TMC_MAX_CURRENT,
TMC_IRUN,
TMC_IHOLD,
TMC_CS_ACTUAL,
TMC_PWM_SCALE,
TMC_VSENSE,
TMC_STEALTHCHOP,
TMC_MICROSTEPS,
TMC_TSTEP,
TMC_TPWMTHRS,
TMC_TPWMTHRS_MMS,
TMC_OTPW,
TMC_OTPW_TRIGGERED,
TMC_TOFF,
TMC_TBL,
TMC_HEND,
TMC_HSTRT,
TMC_SGT
};
enum TMC_drv_status_enum : char {
TMC_DRV_CODES,
TMC_STST,
TMC_OLB,
TMC_OLA,
TMC_S2GB,
TMC_S2GA,
TMC_DRV_OTPW,
TMC_OT,
TMC_STALLGUARD,
TMC_DRV_CS_ACTUAL,
TMC_FSACTIVE,
TMC_SG_RESULT,
TMC_DRV_STATUS_HEX,
TMC_T157,
TMC_T150,
TMC_T143,
TMC_T120,
TMC_STEALTH,
TMC_S2VSB,
TMC_S2VSA
};
static void drv_status_print_hex(const TMC_AxisEnum axis, const uint32_t drv_status) {
_tmc_say_axis(axis);
SERIAL_ECHOPGM(" = 0x");
for (int B = 24; B >= 8; B -= 8){
SERIAL_PRINT((drv_status >> (B + 4)) & 0xF, HEX);
SERIAL_PRINT((drv_status >> B) & 0xF, HEX);
SERIAL_CHAR(':');
}
SERIAL_PRINT((drv_status >> 4) & 0xF, HEX);
SERIAL_PRINT((drv_status) & 0xF, HEX);
SERIAL_EOL();
}
#if HAS_DRIVER(TMC2130)
static void tmc_status(TMC2130Stepper &st, const TMC_debug_enum i) {
switch (i) {
case TMC_PWM_SCALE: SERIAL_PRINT(st.PWM_SCALE(), DEC); break;
case TMC_TSTEP: SERIAL_ECHO(st.TSTEP()); break;
case TMC_SGT: SERIAL_PRINT(st.sgt(), DEC); break;
case TMC_STEALTHCHOP: serialprintPGM(st.stealthChop() ? PSTR("true") : PSTR("false")); break;
default: break;
}
}
static void tmc_parse_drv_status(TMC2130Stepper &st, const TMC_drv_status_enum i) {
switch (i) {
case TMC_STALLGUARD: if (st.stallguard()) SERIAL_CHAR('X'); break;
case TMC_SG_RESULT: SERIAL_PRINT(st.sg_result(), DEC); break;
case TMC_FSACTIVE: if (st.fsactive()) SERIAL_CHAR('X'); break;
default: break;
}
}
#endif
#if HAS_DRIVER(TMC2208)
static void tmc_status(TMC2208Stepper &st, const TMC_debug_enum i) {
switch (i) {
case TMC_TSTEP: { uint32_t data = 0; st.TSTEP(&data); SERIAL_PROTOCOL(data); break; }
case TMC_PWM_SCALE: SERIAL_PRINT(st.pwm_scale_sum(), DEC); break;
case TMC_STEALTHCHOP: serialprintPGM(st.stealth() ? PSTR("true") : PSTR("false")); break;
case TMC_S2VSA: if (st.s2vsa()) SERIAL_CHAR('X'); break;
case TMC_S2VSB: if (st.s2vsb()) SERIAL_CHAR('X'); break;
default: break;
}
}
static void tmc_parse_drv_status(TMC2208Stepper &st, const TMC_drv_status_enum i) {
switch (i) {
case TMC_T157: if (st.t157()) SERIAL_CHAR('X'); break;
case TMC_T150: if (st.t150()) SERIAL_CHAR('X'); break;
case TMC_T143: if (st.t143()) SERIAL_CHAR('X'); break;
case TMC_T120: if (st.t120()) SERIAL_CHAR('X'); break;
default: break;
}
}
#endif
template <typename TMC>
static void tmc_status(TMC &st, const TMC_AxisEnum axis, const TMC_debug_enum i, const float spmm) {
SERIAL_ECHO('\t');
switch (i) {
case TMC_CODES: _tmc_say_axis(axis); break;
case TMC_ENABLED: serialprintPGM(st.isEnabled() ? PSTR("true") : PSTR("false")); break;
case TMC_CURRENT: SERIAL_ECHO(st.getCurrent()); break;
case TMC_RMS_CURRENT: SERIAL_PROTOCOL(st.rms_current()); break;
case TMC_MAX_CURRENT: SERIAL_PRINT((float)st.rms_current() * 1.41, 0); break;
case TMC_IRUN:
SERIAL_PRINT(st.irun(), DEC);
SERIAL_ECHOPGM("/31");
break;
case TMC_IHOLD:
SERIAL_PRINT(st.ihold(), DEC);
SERIAL_ECHOPGM("/31");
break;
case TMC_CS_ACTUAL:
SERIAL_PRINT(st.cs_actual(), DEC);
SERIAL_ECHOPGM("/31");
break;
case TMC_VSENSE: serialprintPGM(st.vsense() ? PSTR("1=.18") : PSTR("0=.325")); break;
case TMC_MICROSTEPS: SERIAL_ECHO(st.microsteps()); break;
case TMC_TPWMTHRS: {
uint32_t tpwmthrs_val = st.TPWMTHRS();
SERIAL_ECHO(tpwmthrs_val);
}
break;
case TMC_TPWMTHRS_MMS: {
uint32_t tpwmthrs_val = st.TPWMTHRS();
if (tpwmthrs_val)
SERIAL_ECHO(12650000UL * st.microsteps() / (256 * tpwmthrs_val * spmm));
else
SERIAL_CHAR('-');
}
break;
case TMC_OTPW: serialprintPGM(st.otpw() ? PSTR("true") : PSTR("false")); break;
case TMC_OTPW_TRIGGERED: serialprintPGM(st.getOTPW() ? PSTR("true") : PSTR("false")); break;
case TMC_TOFF: SERIAL_PRINT(st.toff(), DEC); break;
case TMC_TBL: SERIAL_PRINT(st.blank_time(), DEC); break;
case TMC_HEND: SERIAL_PRINT(st.hysteresis_end(), DEC); break;
case TMC_HSTRT: SERIAL_PRINT(st.hysteresis_start(), DEC); break;
default: tmc_status(st, i); break;
}
}
template <typename TMC>
static void tmc_parse_drv_status(TMC &st, const TMC_AxisEnum axis, const TMC_drv_status_enum i) {
SERIAL_CHAR('\t');
switch (i) {
case TMC_DRV_CODES: _tmc_say_axis(axis); break;
case TMC_STST: if (st.stst()) SERIAL_CHAR('X'); break;
case TMC_OLB: if (st.olb()) SERIAL_CHAR('X'); break;
case TMC_OLA: if (st.ola()) SERIAL_CHAR('X'); break;
case TMC_S2GB: if (st.s2gb()) SERIAL_CHAR('X'); break;
case TMC_S2GA: if (st.s2ga()) SERIAL_CHAR('X'); break;
case TMC_DRV_OTPW: if (st.otpw()) SERIAL_CHAR('X'); break;
case TMC_OT: if (st.ot()) SERIAL_CHAR('X'); break;
case TMC_DRV_CS_ACTUAL: SERIAL_PRINT(st.cs_actual(), DEC); break;
case TMC_DRV_STATUS_HEX:drv_status_print_hex(axis, st.DRV_STATUS()); break;
default: tmc_parse_drv_status(st, i); break;
}
}
static void tmc_debug_loop(const TMC_debug_enum i) {
#if AXIS_IS_TMC(X)
tmc_status(stepperX, TMC_X, i, planner.axis_steps_per_mm[X_AXIS]);
#endif
#if AXIS_IS_TMC(X2)
tmc_status(stepperX2, TMC_X2, i, planner.axis_steps_per_mm[X_AXIS]);
#endif
#if AXIS_IS_TMC(Y)
tmc_status(stepperY, TMC_Y, i, planner.axis_steps_per_mm[Y_AXIS]);
#endif
#if AXIS_IS_TMC(Y2)
tmc_status(stepperY2, TMC_Y2, i, planner.axis_steps_per_mm[Y_AXIS]);
#endif
#if AXIS_IS_TMC(Z)
tmc_status(stepperZ, TMC_Z, i, planner.axis_steps_per_mm[Z_AXIS]);
#endif
#if AXIS_IS_TMC(Z2)
tmc_status(stepperZ2, TMC_Z2, i, planner.axis_steps_per_mm[Z_AXIS]);
#endif
#if AXIS_IS_TMC(E0)
tmc_status(stepperE0, TMC_E0, i, planner.axis_steps_per_mm[E_AXIS]);
#endif
#if AXIS_IS_TMC(E1)
tmc_status(stepperE1, TMC_E1, i, planner.axis_steps_per_mm[E_AXIS
#if ENABLED(DISTINCT_E_FACTORS)
+ 1
#endif
]);
#endif
#if AXIS_IS_TMC(E2)
tmc_status(stepperE2, TMC_E2, i, planner.axis_steps_per_mm[E_AXIS
#if ENABLED(DISTINCT_E_FACTORS)
+ 2
#endif
]);
#endif
#if AXIS_IS_TMC(E3)
tmc_status(stepperE3, TMC_E3, i, planner.axis_steps_per_mm[E_AXIS
#if ENABLED(DISTINCT_E_FACTORS)
+ 3
#endif
]);
#endif
#if AXIS_IS_TMC(E4)
tmc_status(stepperE4, TMC_E4, i, planner.axis_steps_per_mm[E_AXIS
#if ENABLED(DISTINCT_E_FACTORS)
+ 4
#endif
]);
#endif
SERIAL_EOL();
}
static void drv_status_loop(const TMC_drv_status_enum i) {
#if AXIS_IS_TMC(X)
tmc_parse_drv_status(stepperX, TMC_X, i);
#endif
#if AXIS_IS_TMC(X2)
tmc_parse_drv_status(stepperX2, TMC_X2, i);
#endif
#if AXIS_IS_TMC(Y)
tmc_parse_drv_status(stepperY, TMC_Y, i);
#endif
#if AXIS_IS_TMC(Y2)
tmc_parse_drv_status(stepperY2, TMC_Y2, i);
#endif
#if AXIS_IS_TMC(Z)
tmc_parse_drv_status(stepperZ, TMC_Z, i);
#endif
#if AXIS_IS_TMC(Z2)
tmc_parse_drv_status(stepperZ2, TMC_Z2, i);
#endif
#if AXIS_IS_TMC(E0)
tmc_parse_drv_status(stepperE0, TMC_E0, i);
#endif
#if AXIS_IS_TMC(E1)
tmc_parse_drv_status(stepperE1, TMC_E1, i);
#endif
#if AXIS_IS_TMC(E2)
tmc_parse_drv_status(stepperE2, TMC_E2, i);
#endif
#if AXIS_IS_TMC(E3)
tmc_parse_drv_status(stepperE3, TMC_E3, i);
#endif
#if AXIS_IS_TMC(E4)
tmc_parse_drv_status(stepperE4, TMC_E4, i);
#endif
SERIAL_EOL();
}
/**
* M122 report functions
*/
void tmc_set_report_status(const bool status) {
if ((report_tmc_status = status))
SERIAL_ECHOLNPGM("axis:pwm_scale |status_response|");
}
void tmc_report_all() {
#define TMC_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); tmc_debug_loop(ITEM); }while(0)
#define DRV_REPORT(LABEL, ITEM) do{ SERIAL_ECHOPGM(LABEL); drv_status_loop(ITEM); }while(0)
TMC_REPORT("\t", TMC_CODES);
TMC_REPORT("Enabled\t", TMC_ENABLED);
TMC_REPORT("Set current", TMC_CURRENT);
TMC_REPORT("RMS current", TMC_RMS_CURRENT);
TMC_REPORT("MAX current", TMC_MAX_CURRENT);
TMC_REPORT("Run current", TMC_IRUN);
TMC_REPORT("Hold current", TMC_IHOLD);
TMC_REPORT("CS actual\t", TMC_CS_ACTUAL);
TMC_REPORT("PWM scale\t", TMC_PWM_SCALE);
TMC_REPORT("vsense\t", TMC_VSENSE);
TMC_REPORT("stealthChop", TMC_STEALTHCHOP);
TMC_REPORT("msteps\t", TMC_MICROSTEPS);
TMC_REPORT("tstep\t", TMC_TSTEP);
TMC_REPORT("pwm\nthreshold\t", TMC_TPWMTHRS);
TMC_REPORT("[mm/s]\t", TMC_TPWMTHRS_MMS);
TMC_REPORT("OT prewarn", TMC_OTPW);
TMC_REPORT("OT prewarn has\n"
"been triggered", TMC_OTPW_TRIGGERED);
TMC_REPORT("off time\t", TMC_TOFF);
TMC_REPORT("blank time", TMC_TBL);
TMC_REPORT("hysteresis\n-end\t", TMC_HEND);
TMC_REPORT("-start\t", TMC_HSTRT);
TMC_REPORT("Stallguard thrs", TMC_SGT);
DRV_REPORT("DRVSTATUS", TMC_DRV_CODES);
#if HAS_DRIVER(TMC2130)
DRV_REPORT("stallguard\t", TMC_STALLGUARD);
DRV_REPORT("sg_result\t", TMC_SG_RESULT);
DRV_REPORT("fsactive\t", TMC_FSACTIVE);
#endif
DRV_REPORT("stst\t", TMC_STST);
DRV_REPORT("olb\t", TMC_OLB);
DRV_REPORT("ola\t", TMC_OLA);
DRV_REPORT("s2gb\t", TMC_S2GB);
DRV_REPORT("s2ga\t", TMC_S2GA);
DRV_REPORT("otpw\t", TMC_DRV_OTPW);
DRV_REPORT("ot\t", TMC_OT);
#if HAS_DRIVER(TMC2208)
DRV_REPORT("157C\t", TMC_T157);
DRV_REPORT("150C\t", TMC_T150);
DRV_REPORT("143C\t", TMC_T143);
DRV_REPORT("120C\t", TMC_T120);
DRV_REPORT("s2vsa\t", TMC_S2VSA);
DRV_REPORT("s2vsb\t", TMC_S2VSB);
#endif
DRV_REPORT("Driver registers:", TMC_DRV_STATUS_HEX);
SERIAL_EOL();
}
#endif // TMC_DEBUG
#if ENABLED(SENSORLESS_HOMING)
void tmc_sensorless_homing(TMC2130Stepper &st, const bool enable/*=true*/) {
st.coolstep_min_speed(enable ? 1024UL * 1024UL - 1UL : 0);
#if ENABLED(STEALTHCHOP)
st.stealthChop(!enable);
#endif
st.diag1_stall(enable ? 1 : 0);
}
#endif // SENSORLESS_HOMING
#if HAS_DRIVER(TMC2130)
#define SET_CS_PIN(st) OUT_WRITE(st##_CS_PIN, HIGH)
void tmc_init_cs_pins() {
#if AXIS_DRIVER_TYPE(X, TMC2130)
SET_CS_PIN(X);
#endif
#if AXIS_DRIVER_TYPE(Y, TMC2130)
SET_CS_PIN(Y);
#endif
#if AXIS_DRIVER_TYPE(Z, TMC2130)
SET_CS_PIN(Z);
#endif
#if AXIS_DRIVER_TYPE(X2, TMC2130)
SET_CS_PIN(X2);
#endif
#if AXIS_DRIVER_TYPE(Y2, TMC2130)
SET_CS_PIN(Y2);
#endif
#if AXIS_DRIVER_TYPE(Z2, TMC2130)
SET_CS_PIN(Z2);
#endif
#if AXIS_DRIVER_TYPE(E0, TMC2130)
SET_CS_PIN(E0);
#endif
#if AXIS_DRIVER_TYPE(E1, TMC2130)
SET_CS_PIN(E1);
#endif
#if AXIS_DRIVER_TYPE(E2, TMC2130)
SET_CS_PIN(E2);
#endif
#if AXIS_DRIVER_TYPE(E3, TMC2130)
SET_CS_PIN(E3);
#endif
#if AXIS_DRIVER_TYPE(E4, TMC2130)
SET_CS_PIN(E4);
#endif
}
#endif // TMC2130
#endif // HAS_TRINAMIC

View File

@@ -1,107 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _TMC_UTIL_H_
#define _TMC_UTIL_H_
#include "MarlinConfig.h"
#if HAS_DRIVER(TMC2130)
#include <TMC2130Stepper.h>
#endif
#if HAS_DRIVER(TMC2208)
#include <TMC2208Stepper.h>
#endif
extern bool report_tmc_status;
enum TMC_AxisEnum : char { TMC_X, TMC_Y, TMC_Z, TMC_X2, TMC_Y2, TMC_Z2, TMC_E0, TMC_E1, TMC_E2, TMC_E3, TMC_E4 };
constexpr uint32_t _tmc_thrs(const uint16_t msteps, const int32_t thrs, const uint32_t spmm) {
return 12650000UL * msteps / (256 * thrs * spmm);
}
void _tmc_say_axis(const TMC_AxisEnum axis);
void _tmc_say_current(const TMC_AxisEnum axis, const uint16_t curr);
void _tmc_say_otpw(const TMC_AxisEnum axis, const bool otpw);
void _tmc_say_otpw_cleared(const TMC_AxisEnum axis);
void _tmc_say_pwmthrs(const TMC_AxisEnum axis, const uint32_t thrs);
void _tmc_say_sgt(const TMC_AxisEnum axis, const int8_t sgt);
template<typename TMC>
void tmc_get_current(TMC &st, const TMC_AxisEnum axis) {
_tmc_say_current(axis, st.getCurrent());
}
template<typename TMC>
void tmc_set_current(TMC &st, const int mA) {
st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER);
}
template<typename TMC>
void tmc_report_otpw(TMC &st, const TMC_AxisEnum axis) {
_tmc_say_otpw(axis, st.getOTPW());
}
template<typename TMC>
void tmc_clear_otpw(TMC &st, const TMC_AxisEnum axis) {
st.clear_otpw();
_tmc_say_otpw_cleared(axis);
}
template<typename TMC>
void tmc_get_pwmthrs(TMC &st, const TMC_AxisEnum axis, const uint16_t spmm) {
_tmc_say_pwmthrs(axis, _tmc_thrs(st.microsteps(), st.TPWMTHRS(), spmm));
}
template<typename TMC>
void tmc_set_pwmthrs(TMC &st, const int32_t thrs, const uint32_t spmm) {
st.TPWMTHRS(_tmc_thrs(st.microsteps(), thrs, spmm));
}
template<typename TMC>
void tmc_get_sgt(TMC &st, const TMC_AxisEnum axis) {
_tmc_say_sgt(axis, st.sgt());
}
template<typename TMC>
void tmc_set_sgt(TMC &st, const int8_t sgt_val) {
st.sgt(sgt_val);
}
void monitor_tmc_driver();
#if ENABLED(TMC_DEBUG)
void tmc_set_report_status(const bool status);
void tmc_report_all();
#endif
/**
* TMC2130 specific sensorless homing using stallGuard2.
* stallGuard2 only works when in spreadCycle mode.
* spreadCycle and stealthChop are mutually exclusive.
*
* Defined here because of limitations with templates and headers.
*/
#if ENABLED(SENSORLESS_HOMING)
void tmc_sensorless_homing(TMC2130Stepper &st, const bool enable=true);
#endif
#if HAS_DRIVER(TMC2130)
void tmc_init_cs_pins();
#endif
#endif // _TMC_UTIL_H_