├── .gitignore ├── README.md ├── src ├── spi.c ├── optiboot_xflash.h ├── BlinkM.h ├── Configuration.cpp ├── swspi.h ├── asm.h ├── first_lay_cal.h ├── boards.h ├── AutoDeplete.h ├── rbuf.h ├── tone04.h ├── xflash_dump.h ├── BlinkM.cpp ├── system_timer.h ├── uart2.h ├── pat9125.h ├── backlight.h ├── conv2str.h ├── xyzcal.h ├── timer02.h ├── static_assert.h ├── swi2c.h ├── adc.h ├── sound.h ├── bootapp.h ├── qr_solve.h ├── uni_avr_rpi.h ├── spi.h ├── le.sh ├── Timer.h ├── bootapp.c ├── src.ino ├── motion_control.h ├── TimerRemaining.h ├── xflash_layout.h ├── SdFatUtil.h ├── sm4.h ├── la10compat.h ├── vector_3.h ├── printers.h ├── Timer.cpp ├── twi.h ├── xflash.h ├── stk500.h ├── adc.c ├── Dcodes.h ├── rbuf.c ├── AutoDeplete.cpp ├── swspi.cpp ├── ConfigurationStore.h ├── SdFile.h ├── la10compat.cpp ├── pins.h ├── util.h ├── mmu.h ├── xflash_dump.cpp ├── SdFatUtil.cpp ├── macros.h ├── config.h ├── twi.c ├── tone04.c ├── stepper.h ├── uart2.cpp ├── cmdqueue.h ├── speed_lookuptable.h ├── fsensor.h ├── timer02.c ├── backlight.cpp ├── mesh_bed_leveling.h ├── mesh_bed_leveling.cpp ├── swi2c.c ├── pins_Rambo_1_0.h ├── pins_Rambo_1_3.h ├── SdFatConfig.h ├── tmc2130.h ├── vector_3.cpp ├── language.h ├── sound.cpp ├── cardreader.h ├── xflash.c ├── menu.h ├── Servo.h ├── eeprom.cpp └── pins_Einsy_1_0.h ├── .build └── pre_build_script.py └── platformio.ini /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .pio 3 | .vscode 4 | /src/Configuration_prusa.h -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This FW is for use with MMU2S, in combination with [MMU2S-TZB-FW](https://github.com/TheZeroBeast/MM-control-01/tree/MMU2S-TZB) -------------------------------------------------------------------------------- /src/spi.c: -------------------------------------------------------------------------------- 1 | //spi.c - hardware SPI 2 | //#ifdef __SPI 3 | 4 | #include "spi.h" 5 | #include 6 | 7 | 8 | //#endif //__SPI 9 | -------------------------------------------------------------------------------- /src/optiboot_xflash.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIBOOT_XFLASH_H 2 | #define OPTIBOOT_XFLASH_H 3 | 4 | extern uint8_t optiboot_xflash_enter(); 5 | 6 | #endif /* OPTIBOOT_XFLASH_H */ 7 | -------------------------------------------------------------------------------- /src/BlinkM.h: -------------------------------------------------------------------------------- 1 | /* 2 | BlinkM.h 3 | Library header file for BlinkM library 4 | */ 5 | #if (ARDUINO >= 100) 6 | # include "Arduino.h" 7 | #else 8 | # include "WProgram.h" 9 | #endif 10 | 11 | #include "Wire.h" 12 | 13 | void SendColors(byte red, byte grn, byte blu); 14 | 15 | -------------------------------------------------------------------------------- /src/Configuration.cpp: -------------------------------------------------------------------------------- 1 | #include "Configuration.h" 2 | #include "Configuration_prusa.h" 3 | 4 | const uint16_t _nPrinterType PROGMEM=PRINTER_TYPE; 5 | const char _sPrinterName[] PROGMEM=PRINTER_NAME; 6 | const uint16_t _nPrinterMmuType PROGMEM=PRINTER_MMU_TYPE; 7 | const char _sPrinterMmuName[] PROGMEM=PRINTER_MMU_NAME; 8 | 9 | uint16_t nPrinterType; 10 | PGM_P sPrinterName; -------------------------------------------------------------------------------- /.build/pre_build_script.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | Import("env") 4 | 5 | my_flags = env.ParseFlags(env['BUILD_FLAGS']) 6 | defines = {k: v for (k, v) in my_flags.get("CPPDEFINES")} 7 | 8 | shutil.copyfile(os.path.join(os.getcwd(), "src/variants/{0}.h".format(defines.get('CONFIG'))), os.path.join(os.getcwd(), 'src/Configuration_prusa.h')), 9 | 10 | env.Replace(PROGNAME="TZB-{0}-{1}-BN{2}".format(defines.get('CONFIG'), defines.get('VERSION'), defines.get('BN'))) -------------------------------------------------------------------------------- /src/swspi.h: -------------------------------------------------------------------------------- 1 | // Software SPI 2 | #ifndef SWSPI_H 3 | #define SWSPI_H 4 | 5 | //initialize gpio 6 | extern void swspi_init(unsigned char miso, unsigned char mosi, unsigned char sck, unsigned char cfg); 7 | //transmit and receive (full duplex mode) 8 | extern unsigned char swspi_txrx(unsigned char tx); 9 | //transmit (half dublex mode, miso == mosi) 10 | extern void swspi_tx(unsigned char tx); 11 | //receive (half dublex mode, miso == mosi) 12 | extern unsigned char swspi_rx(); 13 | 14 | #endif //SWSPI_H 15 | -------------------------------------------------------------------------------- /src/asm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #ifdef __AVR_ATmega2560__ 5 | 6 | // return the current PC (on AVRs with 22bit PC) 7 | static inline void GETPC(uint32_t* v) 8 | { 9 | uint8_t a, b, c; 10 | asm 11 | ( 12 | "rcall .\n" 13 | "pop %2\n" 14 | "pop %1\n" 15 | "pop %0\n" 16 | : "=r" (a), "=r" (b), "=r" (c) 17 | ); 18 | ((uint8_t*)v)[0] = a; 19 | ((uint8_t*)v)[1] = b; 20 | ((uint8_t*)v)[2] = c; 21 | ((uint8_t*)v)[3] = 0; 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/first_lay_cal.h: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! @date Jun 10, 2019 3 | //! @author Marek Bel 4 | 5 | #ifndef FIRMWARE_FIRST_LAY_CAL_H_ 6 | #define FIRMWARE_FIRST_LAY_CAL_H_ 7 | #include 8 | 9 | void lay1cal_wait_preheat(); 10 | void lay1cal_load_filament(char *cmd_buffer, uint8_t filament); 11 | void lay1cal_intro_line(); 12 | void lay1cal_before_meander(); 13 | void lay1cal_meander(char *cmd_buffer); 14 | void lay1cal_square(char *cmd_buffer, uint8_t i); 15 | 16 | #endif /* FIRMWARE_FIRST_LAY_CAL_H_ */ 17 | -------------------------------------------------------------------------------- /src/boards.h: -------------------------------------------------------------------------------- 1 | #ifndef BOARDS_H 2 | #define BOARDS_H 3 | 4 | #define BOARD_UNKNOWN -1 5 | 6 | #define BOARD_RAMBO_MINI_1_0 200 // Rambo-mini 1.0 - 200 (orig 102) 7 | #define BOARD_RAMBO_MINI_1_3 203 // Rambo-mini 1.3 - 203 (orig 302) 8 | 9 | #define BOARD_EINSY_1_0a 310 // EINSy 1.0a - 310 (new) 10 | 11 | #define MB(board) (MOTHERBOARD==BOARD_##board) 12 | #define IS_RAMPS (MB(RAMPS_OLD) || MB(RAMPS_13_EFB) || MB(RAMPS_13_EEB) || MB(RAMPS_13_EFF) || MB(RAMPS_13_EEF)) 13 | 14 | #endif //__BOARDS_H 15 | -------------------------------------------------------------------------------- /src/AutoDeplete.h: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! @author: Marek Bel 3 | //! @brief Filament auto deplete engine for multi-material prints with MMUv2 (Now marketed as SpoolJoin) 4 | //! 5 | //! Interface for marking MMUv2 filaments as depleted and getting alternative filament for printing. 6 | 7 | #ifndef AUTODEPLETE_H 8 | #define AUTODEPLETE_H 9 | 10 | #include 11 | 12 | void ad_markDepleted(uint8_t filament); 13 | void ad_markLoaded(uint8_t filament); 14 | uint8_t ad_getAlternative(uint8_t filament); 15 | bool ad_allDepleted(); 16 | 17 | #endif /* AUTODEPLETE_H */ 18 | -------------------------------------------------------------------------------- /src/rbuf.h: -------------------------------------------------------------------------------- 1 | //rbuf.h 2 | #ifndef _RBUF_H 3 | #define _RBUF_H 4 | 5 | #include 6 | 7 | 8 | #define rbuf_l(ptr) (ptr[0]) 9 | #define rbuf_w(ptr) (ptr[1]) 10 | #define rbuf_r(ptr) (ptr[2]) 11 | #define rbuf_empty(ptr) (ptr[1] == ptr[2]) 12 | 13 | 14 | #if defined(__cplusplus) 15 | extern "C" { 16 | #endif //defined(__cplusplus) 17 | 18 | 19 | extern void rbuf_ini(uint8_t* ptr, uint8_t len); 20 | extern int rbuf_put(uint8_t* ptr, uint8_t val); 21 | extern int rbuf_get(uint8_t* ptr); 22 | 23 | 24 | #if defined(__cplusplus) 25 | } 26 | #endif //defined(__cplusplus) 27 | #endif //_RBUF_H -------------------------------------------------------------------------------- /src/tone04.h: -------------------------------------------------------------------------------- 1 | //tone04.h 2 | // use atmega timer4 as main tone timer instead of timer2 3 | // timer2 is used for System timer. 4 | #ifndef TIMER04_H 5 | #define TIMER04_H 6 | 7 | #include 8 | 9 | #if defined(__cplusplus) 10 | extern "C" { 11 | #endif //defined(__cplusplus) 12 | 13 | extern void timer4_init(void); 14 | 15 | extern void timer4_set_fan0(uint8_t duty); 16 | 17 | extern void tone4(uint8_t _pin, uint16_t frequency); 18 | 19 | extern void noTone4(uint8_t _pin); 20 | 21 | #if defined(__cplusplus) 22 | } 23 | #endif //defined(__cplusplus) 24 | 25 | #endif //TIMER02_H 26 | -------------------------------------------------------------------------------- /src/xflash_dump.h: -------------------------------------------------------------------------------- 1 | // XFLASH dumper 2 | #pragma once 3 | #include "xflash_layout.h" 4 | 5 | enum class dump_crash_reason : uint8_t 6 | { 7 | manual = 0, 8 | stack_error, 9 | watchdog, 10 | bad_isr, 11 | }; 12 | 13 | #ifdef XFLASH_DUMP 14 | void xfdump_reset(); // reset XFLASH dump state 15 | void xfdump_dump(); // create a new SRAM memory dump 16 | 17 | // return true if a dump is present, save type in "reason" if provided 18 | bool xfdump_check_state(dump_crash_reason* reason = NULL); 19 | 20 | // create a new dump containing registers and SRAM, then reset 21 | void xfdump_full_dump_and_reset(dump_crash_reason crash = dump_crash_reason::manual); 22 | #endif 23 | -------------------------------------------------------------------------------- /src/BlinkM.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | BlinkM.cpp - Library for controlling a BlinkM over i2c 3 | Created by Tim Koster, August 21 2013. 4 | */ 5 | #include "Marlin.h" 6 | #ifdef BLINKM 7 | 8 | #if (ARDUINO >= 100) 9 | # include "Arduino.h" 10 | #else 11 | # include "WProgram.h" 12 | #endif 13 | 14 | #include "BlinkM.h" 15 | 16 | void SendColors(byte red, byte grn, byte blu) 17 | { 18 | Wire.begin(); 19 | Wire.beginTransmission(0x09); 20 | Wire.write('o'); //to disable ongoing script, only needs to be used once 21 | Wire.write('n'); 22 | Wire.write(red); 23 | Wire.write(grn); 24 | Wire.write(blu); 25 | Wire.endTransmission(); 26 | } 27 | 28 | #endif //BLINKM 29 | 30 | -------------------------------------------------------------------------------- /src/system_timer.h: -------------------------------------------------------------------------------- 1 | //! @file 2 | 3 | #ifndef FIRMWARE_SYSTEM_TIMER_H_ 4 | #define FIRMWARE_SYSTEM_TIMER_H_ 5 | 6 | #include "Arduino.h" 7 | #define SYSTEM_TIMER_2 8 | 9 | #ifdef SYSTEM_TIMER_2 10 | #include "timer02.h" 11 | #include "tone04.h" 12 | #define _millis millis2 13 | #define _micros micros2 14 | #define _delay delay2 15 | #define _tone tone4 16 | #define _noTone noTone4 17 | 18 | #define timer02_set_pwm0(pwm0) 19 | 20 | #else //SYSTEM_TIMER_2 21 | #define _millis millis 22 | #define _micros micros 23 | #define _delay delay 24 | #define _tone tone 25 | #define _noTone noTone 26 | #define timer02_set_pwm0(pwm0) 27 | #endif //SYSTEM_TIMER_2 28 | 29 | #endif /* FIRMWARE_SYSTEM_TIMER_H_ */ 30 | -------------------------------------------------------------------------------- /src/uart2.h: -------------------------------------------------------------------------------- 1 | //uart2.h 2 | #ifndef _UART2_H 3 | #define _UART2_H 4 | 5 | #define USART2_BAUDRATE 38400UL 6 | #define MMU_F_CPU 16000000UL 7 | #define BAUD_PRESCALE (((MMU_F_CPU / (USART2_BAUDRATE * 16UL))) - 1) 8 | #define BLK 0x2D // Blank data filler "-" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "mmu.h" 15 | #include "Arduino.h" 16 | 17 | extern volatile unsigned char rxData1, rxData2, rxData3, rxData4, rxData5, rxFINDA; 18 | extern volatile bool confirmedPayload, confirmedFINDA, atomic_MMU_IRSENS; 19 | 20 | extern void uart2_txPayload(unsigned char*); 21 | 22 | extern void uart2_init(void); 23 | 24 | #endif //_UART2_H 25 | -------------------------------------------------------------------------------- /src/pat9125.h: -------------------------------------------------------------------------------- 1 | //pat9125.h 2 | #ifndef PAT9125_H 3 | #define PAT9125_H 4 | 5 | #include 6 | 7 | 8 | #if defined(__cplusplus) 9 | extern "C" { 10 | #endif //defined(__cplusplus) 11 | 12 | 13 | extern uint8_t pat9125_PID1; 14 | extern uint8_t pat9125_PID2; 15 | 16 | extern int16_t pat9125_x; 17 | extern int16_t pat9125_y; 18 | extern uint8_t pat9125_b; 19 | extern uint8_t pat9125_s; 20 | 21 | extern uint8_t pat9125_probe(void); // Return non-zero if PAT9125 can be trivially detected 22 | extern uint8_t pat9125_init(void); 23 | extern uint8_t pat9125_update(void); // update all sensor data 24 | extern uint8_t pat9125_update_y(void); // update _y only 25 | extern uint8_t pat9125_update_bs(void); // update _b/_s only 26 | 27 | 28 | #if defined(__cplusplus) 29 | } 30 | #endif //defined(__cplusplus) 31 | 32 | #endif //PAT9125_H 33 | -------------------------------------------------------------------------------- /src/backlight.h: -------------------------------------------------------------------------------- 1 | //backlight.h 2 | #ifndef _BACKLIGHT_H 3 | #define _BACKLIGHT_H 4 | 5 | #include 6 | #include "Marlin.h" 7 | #include "pins.h" 8 | 9 | enum Backlight_Mode 10 | { 11 | BACKLIGHT_MODE_DIM = 0, 12 | BACKLIGHT_MODE_BRIGHT = 1, 13 | BACKLIGHT_MODE_AUTO = 2, 14 | }; 15 | 16 | extern int16_t backlightLevel_HIGH; 17 | extern int16_t backlightLevel_LOW; 18 | extern uint8_t backlightMode; 19 | extern bool backlightSupport; 20 | extern int16_t backlightTimer_period; 21 | 22 | #define FORCE_BL_ON_START force_bl_on(true) 23 | #define FORCE_BL_ON_END force_bl_on(false) 24 | 25 | extern void force_bl_on(bool section_start); 26 | extern void backlight_update(); 27 | extern void backlight_init(); 28 | extern void backlight_save(); 29 | extern void backlight_wake(const uint8_t flashNo = 0); 30 | 31 | 32 | #endif //_BACKLIGHT_H 33 | -------------------------------------------------------------------------------- /src/conv2str.h: -------------------------------------------------------------------------------- 1 | //conv2str.h - Float conversion utilities 2 | #ifndef _CONV2STR_H 3 | #define _CONV2STR_H 4 | 5 | #include 6 | 7 | 8 | char *itostr2(const uint8_t &x); 9 | char *itostr31(const int &xx); 10 | char *itostr3(const int &xx); 11 | char *itostr3left(const int &xx); 12 | char *itostr4(const int &xx); 13 | 14 | char *ftostr3(const float &x); 15 | char *ftostr31ns(const float &x); // float to string without sign character 16 | char *ftostr31(const float &x); 17 | char *ftostr32(const float &x); 18 | char *ftostr32ns(const float &x); 19 | char *ftostr43(const float &x, uint8_t offset = 0); 20 | char *ftostr12ns(const float &x); 21 | char *ftostr13ns(const float &x); 22 | char *ftostr32sp(const float &x); // remove zero-padding from ftostr32 23 | char *ftostr5(const float &x); 24 | char *ftostr51(const float &x); 25 | char *ftostr52(const float &x); 26 | 27 | 28 | #endif //_CONV2STR_H 29 | -------------------------------------------------------------------------------- /src/xyzcal.h: -------------------------------------------------------------------------------- 1 | //xyzcal.h - xyz calibration with image processing 2 | #pragma once 3 | 4 | #include 5 | 6 | #include "mesh_bed_calibration.h" 7 | 8 | extern void xyzcal_meassure_enter(void); 9 | 10 | extern void xyzcal_meassure_leave(void); 11 | 12 | extern bool xyzcal_lineXYZ_to(int16_t x, int16_t y, int16_t z, uint16_t delay_us, int8_t check_pinda); 13 | 14 | extern bool xyzcal_spiral2(int16_t cx, int16_t cy, int16_t z0, int16_t dz, int16_t radius, int16_t rotation, uint16_t delay_us, int8_t check_pinda, uint16_t* pad); 15 | 16 | extern bool xyzcal_spiral8(int16_t cx, int16_t cy, int16_t z0, int16_t dz, int16_t radius, uint16_t delay_us, int8_t check_pinda, uint16_t* pad); 17 | 18 | //extern int8_t xyzcal_meassure_pinda_hysterezis(int16_t min_z, int16_t max_z, uint16_t delay_us, uint8_t samples); 19 | 20 | extern BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy(); 21 | -------------------------------------------------------------------------------- /src/timer02.h: -------------------------------------------------------------------------------- 1 | //timer02.h 2 | // use atmega timer2 as main system timer instead of timer0 3 | // timer0 is used for fast pwm (OC0B output) 4 | // original OVF handler is disabled 5 | #ifndef TIMER02_H 6 | #define TIMER02_H 7 | 8 | #include 9 | 10 | #if defined(__cplusplus) 11 | extern "C" { 12 | #endif //defined(__cplusplus) 13 | 14 | ///! Initializes TIMER0 for fast PWM mode-driven bed heating 15 | extern void timer0_init(void); 16 | 17 | ///! Initializes TIMER2 for time keeping and temperature interrupt 18 | extern void timer2_init(void); 19 | 20 | ///! Reimplemented original millis() using timer2 21 | extern unsigned long millis2(void); 22 | 23 | ///! Reimplemented original micros() using timer2 24 | extern unsigned long micros2(void); 25 | 26 | ///! Reimplemented original delay() using timer2 27 | extern void delay2(unsigned long ms); 28 | 29 | #if defined(__cplusplus) 30 | } 31 | #endif //defined(__cplusplus) 32 | 33 | #endif //TIMER02_H 34 | -------------------------------------------------------------------------------- /src/static_assert.h: -------------------------------------------------------------------------------- 1 | //static_assert.h 2 | //portable solution compatible with C++98 3 | 4 | #if (__cplusplus < 201103L) //std < C++11 5 | 6 | //source http://www.pixelbeat.org/programming/gcc/STATIC_ASSERT.html 7 | #define ASSERT_CONCAT_(a, b) a##b 8 | #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) 9 | 10 | // These can't be used after statements in c89. 11 | #ifdef __COUNTER__ 12 | #define static_assert(e,m) \ 13 | ;enum { ASSERT_CONCAT(STATIC_ASSERT_, __COUNTER__) = 1/(int)(!!(e)) } 14 | #else 15 | //This can't be used twice on the same line so ensure if using in headers 16 | //that the headers are not included twice (by wrapping in #ifndef...#endif) 17 | //Note it doesn't cause an issue when used on same line of separate modules 18 | //compiled with gcc -combine -fwhole-program. 19 | #define static_assert(e,m) \ 20 | ;enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(int)(!!(e)) } 21 | #endif //__COUNTER__ 22 | 23 | #endif //(__cplusplus < 201103L) 24 | -------------------------------------------------------------------------------- /src/swi2c.h: -------------------------------------------------------------------------------- 1 | //swi2c.h 2 | #ifndef SWI2C_H 3 | #define SWI2C_H 4 | 5 | #include 6 | #include "config.h" 7 | 8 | 9 | #if defined(__cplusplus) 10 | extern "C" { 11 | #endif //defined(__cplusplus) 12 | 13 | //initialize 14 | extern void swi2c_init(void); 15 | 16 | //check device address acknowledge 17 | extern uint8_t swi2c_check(uint8_t dev_addr); 18 | 19 | //read write functions - 8bit address (most i2c chips) 20 | #ifdef SWI2C_A8 21 | extern uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte); 22 | extern uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte); 23 | #endif //SWI2C_A8 24 | 25 | //read write functions - 16bit address (e.g. serial eeprom AT24C256) 26 | #ifdef SWI2C_A16 27 | extern uint8_t swi2c_readByte_A16(uint8_t dev_addr, uint16_t addr, uint8_t* pbyte); 28 | extern uint8_t swi2c_writeByte_A16(uint8_t dev_addr, uint16_t addr, uint8_t* pbyte); 29 | #endif //SWI2C_A16 30 | 31 | #if defined(__cplusplus) 32 | } 33 | #endif //defined(__cplusplus) 34 | 35 | #endif //SWI2C_H 36 | -------------------------------------------------------------------------------- /src/adc.h: -------------------------------------------------------------------------------- 1 | //adc.h 2 | #ifndef _ADC_H 3 | #define _ADC_H 4 | 5 | #include 6 | #include "config.h" 7 | 8 | 9 | #if defined(__cplusplus) 10 | extern "C" { 11 | #endif //defined(__cplusplus) 12 | 13 | /* 14 | http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html 15 | */ 16 | #define BITCOUNT(x) (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255) 17 | #define BX_(x) ((x) - (((x)>>1)&0x77777777) - (((x)>>2)&0x33333333) - (((x)>>3)&0x11111111)) 18 | 19 | #define ADC_PIN_IDX(pin) BITCOUNT(ADC_CHAN_MSK & ((1 << (pin)) - 1)) 20 | 21 | #if BITCOUNT(ADC_CHAN_MSK) != ADC_CHAN_CNT 22 | # error "ADC_CHAN_MSK oes not match ADC_CHAN_CNT" 23 | #endif 24 | 25 | extern uint8_t adc_state; 26 | extern uint8_t adc_count; 27 | extern uint16_t adc_values[ADC_CHAN_CNT]; 28 | extern uint16_t adc_sim_mask; 29 | 30 | 31 | extern void adc_init(void); 32 | 33 | extern void adc_reset(void); 34 | 35 | extern void adc_setmux(uint8_t ch); 36 | 37 | extern uint8_t adc_chan(uint8_t index); 38 | 39 | extern void adc_cycle(void); 40 | 41 | 42 | #if defined(__cplusplus) 43 | } 44 | #endif //defined(__cplusplus) 45 | #endif //_ADC_H 46 | -------------------------------------------------------------------------------- /src/sound.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef SOUND_H 3 | #define SOUND_H 4 | 5 | 6 | #define e_SOUND_MODE_NULL 0xFF 7 | typedef enum 8 | {e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_BLIND} eSOUND_MODE; 9 | #define e_SOUND_MODE_DEFAULT e_SOUND_MODE_LOUD 10 | 11 | typedef enum 12 | {e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert,e_SOUND_TYPE_EncoderMove,e_SOUND_TYPE_BlindAlert} eSOUND_TYPE; 13 | typedef enum 14 | {e_SOUND_CLASS_Echo,e_SOUND_CLASS_Prompt,e_SOUND_CLASS_Confirm,e_SOUND_CLASS_Warning,e_SOUND_CLASS_Alert} eSOUND_CLASS; 15 | 16 | 17 | extern eSOUND_MODE eSoundMode; 18 | 19 | 20 | extern void Sound_Init(void); 21 | extern void Sound_Default(void); 22 | extern void Sound_Save(void); 23 | extern void Sound_CycleState(void); 24 | extern void Sound_MakeSound(eSOUND_TYPE eSoundType); 25 | extern void Sound_MakeCustom(uint16_t ms,uint16_t tone_ ,bool critical); 26 | 27 | //static void Sound_DoSound_Echo(void); 28 | //static void Sound_DoSound_Prompt(void); 29 | 30 | #endif // SOUND_H 31 | -------------------------------------------------------------------------------- /src/bootapp.h: -------------------------------------------------------------------------------- 1 | //language.h 2 | #ifndef BOOTAPP_H 3 | #define BOOTAPP_H 4 | 5 | #include "config.h" 6 | #include 7 | #include 8 | 9 | 10 | #define RAMSIZE (RAMEND+1-RAMSTART) 11 | #define boot_src_addr (*((uint32_t*)(RAMSIZE - 16))) 12 | #define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12))) 13 | #define boot_copy_size (*((uint16_t*)(RAMSIZE - 8))) 14 | #define boot_reserved (*((uint8_t*)(RAMSIZE - 6))) 15 | #define boot_app_flags (*((uint8_t*)(RAMSIZE - 5))) 16 | #define boot_app_magic (*((uint32_t*)(RAMSIZE - 4))) 17 | #define BOOT_APP_FLG_ERASE 0x01 18 | #define BOOT_APP_FLG_COPY 0x02 19 | #define BOOT_APP_FLG_FLASH 0x04 20 | #define BOOT_APP_FLG_RUN 0x08 21 | 22 | #define BOOT_APP_FLG_USER0 0x80 23 | 24 | #define BOOT_APP_MAGIC 0x55aa55aa 25 | 26 | 27 | #if defined(__cplusplus) 28 | extern "C" { 29 | #endif //defined(__cplusplus) 30 | 31 | extern void bootapp_print_vars(void); 32 | 33 | extern void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size); 34 | 35 | extern void bootapp_reboot_user0(uint8_t reserved); 36 | 37 | #if defined(__cplusplus) 38 | } 39 | #endif //defined(__cplusplus) 40 | 41 | #endif //BOOTAPP_H 42 | -------------------------------------------------------------------------------- /src/qr_solve.h: -------------------------------------------------------------------------------- 1 | #include "Configuration.h" 2 | 3 | #ifdef AUTO_BED_LEVELING_GRID 4 | 5 | void daxpy ( int n, double da, double dx[], int incx, double dy[], int incy ); 6 | double ddot ( int n, double dx[], int incx, double dy[], int incy ); 7 | double dnrm2 ( int n, double x[], int incx ); 8 | void dqrank ( double a[], int lda, int m, int n, double tol, int *kr, 9 | int jpvt[], double qraux[] ); 10 | void dqrdc ( double a[], int lda, int n, int p, double qraux[], int jpvt[], 11 | double work[], int job ); 12 | int dqrls ( double a[], int lda, int m, int n, double tol, int *kr, double b[], 13 | double x[], double rsd[], int jpvt[], double qraux[], int itask ); 14 | void dqrlss ( double a[], int lda, int m, int n, int kr, double b[], double x[], 15 | double rsd[], int jpvt[], double qraux[] ); 16 | int dqrsl ( double a[], int lda, int n, int k, double qraux[], double y[], 17 | double qy[], double qty[], double b[], double rsd[], double ab[], int job ); 18 | void dscal ( int n, double sa, double x[], int incx ); 19 | void dswap ( int n, double x[], int incx, double y[], int incy ); 20 | double *qr_solve ( int m, int n, double a[], double b[] ); 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/uni_avr_rpi.h: -------------------------------------------------------------------------------- 1 | // unification for AVR and RPI 2 | 3 | #ifdef __AVR 4 | //#include "Arduino.h" 5 | #include "Marlin.h" 6 | #define GPIO_INP(gpio) pinMode(gpio, INPUT) 7 | #define GPIO_OUT(gpio) pinMode(gpio, OUTPUT) 8 | #define GPIO_SET(gpio) digitalWrite(gpio, HIGH) 9 | #define GPIO_CLR(gpio) digitalWrite(gpio, LOW) 10 | #define GPIO_GET(gpio) (digitalRead(gpio) != LOW) 11 | #define DELAY(delay) delayMicroseconds(delay) 12 | #define PRINT MYSERIAL.print 13 | #endif //RC522_AVR 14 | 15 | #ifdef __RPI 16 | #include 17 | #define GPIO_INP(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_INPT) 18 | #define GPIO_OUT(gpio) bcm2835_gpio_fsel(gpio, BCM2835_GPIO_FSEL_OUTP) 19 | #define GPIO_SET(gpio) bcm2835_gpio_write(gpio, HIGH) 20 | #define GPIO_CLR(gpio) bcm2835_gpio_write(gpio, LOW) 21 | #define GPIO_GET(gpio) (bcm2835_gpio_lev(gpio) != LOW) 22 | #include 23 | #define DELAY(delay) usleep(delay) 24 | #define PRINT(p) print(p) 25 | #define DEC 10 26 | #define HEX 16 27 | void print(const char* pc) { printf("%s", pc); } 28 | void print(int v) { printf("%d", v); } 29 | void print(float v) { printf("%f", v); } 30 | #endif //RC522_RPI 31 | 32 | -------------------------------------------------------------------------------- /src/spi.h: -------------------------------------------------------------------------------- 1 | //spi.h - hardware SPI 2 | #ifndef SPI_H 3 | #define SPI_H 4 | 5 | #include 6 | #include 7 | #include "config.h" 8 | 9 | 10 | #define SPI_SPCR(rat, pha, pol, mst, dor) ((rat & 3) | (pha?(1< 17 | class Timer 18 | { 19 | public: 20 | Timer(); 21 | void start(); 22 | void stop(){m_isRunning = false;} 23 | bool running()const {return m_isRunning;} 24 | bool expired(T msPeriod); 25 | protected: 26 | T started()const {return m_started;} 27 | private: 28 | bool m_isRunning; 29 | T m_started; 30 | }; 31 | 32 | /** 33 | * @brief Timer unsigned long specialization 34 | * 35 | * Maximum period is at least 49 days. 36 | */ 37 | #if __cplusplus>=201103L 38 | using LongTimer = Timer; 39 | #else 40 | typedef Timer LongTimer; 41 | #endif 42 | /** 43 | * @brief Timer unsigned short specialization 44 | * 45 | * Maximum period is at least 65 seconds. 46 | */ 47 | #if __cplusplus>=201103L 48 | using ShortTimer = Timer; 49 | #else 50 | typedef Timer ShortTimer; 51 | #endif 52 | 53 | #endif /* TIMER_H */ 54 | -------------------------------------------------------------------------------- /src/bootapp.c: -------------------------------------------------------------------------------- 1 | //bootapp.c 2 | #include "bootapp.h" 3 | #include 4 | #include 5 | #include 6 | 7 | 8 | #include 9 | extern FILE _uartout; 10 | #define uartout (&_uartout) 11 | 12 | extern void softReset(); 13 | 14 | void bootapp_print_vars(void) 15 | { 16 | fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr); 17 | fprintf_P(uartout, PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr); 18 | fprintf_P(uartout, PSTR("boot_copy_size =0x%04x\n"), boot_copy_size); 19 | fprintf_P(uartout, PSTR("boot_reserved =0x%02x\n"), boot_reserved); 20 | fprintf_P(uartout, PSTR("boot_app_flags =0x%02x\n"), boot_app_flags); 21 | fprintf_P(uartout, PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic); 22 | } 23 | 24 | 25 | void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size) 26 | { 27 | cli(); 28 | boot_app_magic = BOOT_APP_MAGIC; 29 | boot_app_flags |= BOOT_APP_FLG_COPY; 30 | boot_app_flags |= BOOT_APP_FLG_ERASE; 31 | boot_copy_size = (uint16_t)size; 32 | boot_src_addr = (uint32_t)rptr; 33 | boot_dst_addr = (uint32_t)fptr; 34 | bootapp_print_vars(); 35 | softReset(); 36 | } 37 | 38 | void bootapp_reboot_user0(uint8_t reserved) 39 | { 40 | cli(); 41 | boot_app_magic = BOOT_APP_MAGIC; 42 | boot_app_flags = BOOT_APP_FLG_USER0; 43 | boot_reserved = reserved; 44 | bootapp_print_vars(); 45 | softReset(); 46 | } 47 | -------------------------------------------------------------------------------- /src/src.ino: -------------------------------------------------------------------------------- 1 | /* -*- c++ -*- */ 2 | 3 | /* 4 | Reprap firmware based on Sprinter and grbl. 5 | Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm 6 | 7 | This program is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | This firmware is a mashup between Sprinter and grbl. 23 | (https://github.com/kliment/Sprinter) 24 | (https://github.com/simen/grbl/tree) 25 | 26 | It has preliminary support for Matthew Roberts advance algorithm 27 | http://reprap.org/pipermail/reprap-dev/2011-May/003323.html 28 | */ 29 | 30 | /* All the implementation is done in *.cpp files to get better compatibility with avr-gcc without the Arduino IDE */ 31 | /* Use this file to help the Arduino IDE find which Arduino libraries are needed and to keep documentation on GCode */ 32 | 33 | #include "Configuration.h" 34 | #include "pins.h" 35 | -------------------------------------------------------------------------------- /src/motion_control.h: -------------------------------------------------------------------------------- 1 | /* 2 | motion_control.h - high level interface for issuing motion commands 3 | Part of Grbl 4 | 5 | Copyright (c) 2009-2011 Simen Svale Skogsrud 6 | Copyright (c) 2011 Sungeun K. Jeon 7 | 8 | Grbl is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | Grbl is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with Grbl. If not, see . 20 | */ 21 | 22 | #ifndef motion_control_h 23 | #define motion_control_h 24 | 25 | // Execute an arc in offset mode format. position == current xyz, target == target xyz, 26 | // offset == offset from current xyz, axis_XXX defines circle plane in tool space, axis_linear is 27 | // the direction of helical travel, radius == circle radius, isclockwise boolean. Used 28 | // for vector transformation direction. 29 | void mc_arc(float *position, float *target, float *offset, unsigned char axis_0, unsigned char axis_1, 30 | unsigned char axis_linear, float feed_rate, float radius, unsigned char isclockwise, uint8_t extruder); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/TimerRemaining.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Marek Bel 4 | */ 5 | 6 | #ifndef TIMERREMAINING_H 7 | #define TIMERREMAINING_H 8 | 9 | #include "Timer.h" 10 | #include "Arduino.h" 11 | #include "system_timer.h" 12 | #include 13 | 14 | class TimerRemaining : public LongTimer 15 | { 16 | public: 17 | TimerRemaining() : m_period(){} 18 | void start() = delete; 19 | bool expired(unsigned long msPeriod) = delete; 20 | /** 21 | * @brief Start timer 22 | * @param msPeriod Time to expire in milliseconds 23 | */ 24 | void start(unsigned long msPeriod) 25 | { 26 | m_period = msPeriod; 27 | LongTimer::start(); 28 | } 29 | /** 30 | * @brief Time remaining to expiration 31 | * 32 | * @param msPeriod timer period in milliseconds 33 | * @return time remaining to expiration in milliseconds 34 | * @retval 0 Timer has expired, or was not even started. 35 | */ 36 | unsigned long remaining() 37 | { 38 | if (!running()) return 0; 39 | if (expired()) return 0; 40 | const unsigned long now = _millis(); 41 | return (started() + m_period - now); 42 | } 43 | /** 44 | * @brief Timer has expired. 45 | * @retval true Timer has expired. 46 | * @retval false Timer has not expired. 47 | */ 48 | bool expired() 49 | { 50 | return LongTimer::expired(m_period); 51 | } 52 | private: 53 | unsigned long m_period; //!< Timer period in milliseconds. 54 | }; 55 | 56 | #endif // ifndef TIMERREMAINING_H 57 | -------------------------------------------------------------------------------- /src/xflash_layout.h: -------------------------------------------------------------------------------- 1 | // XFLASH memory layout 2 | #pragma once 3 | #include 4 | #include "bootapp.h" // for RAMSIZE 5 | #include "config.h" 6 | 7 | #define XFLASH_SIZE 0x40000ul // size of XFLASH 8 | #define LANG_OFFSET 0x0 // offset for language data 9 | 10 | #ifndef XFLASH_DUMP 11 | #define LANG_SIZE XFLASH_SIZE 12 | #else 13 | 14 | #define DUMP_MAGIC 0x55525547ul 15 | 16 | struct dump_header_t 17 | { 18 | // start with a magic value to indicate the presence of a dump, so that clearing 19 | // a single page is sufficient for resetting the state 20 | uint32_t magic; 21 | 22 | uint8_t regs_present; // true when the lower segment containing registers is present 23 | uint8_t crash_reason; // uses values from dump_crash_source 24 | 25 | uint32_t pc; // PC nearby the crash location 26 | uint16_t sp; // SP nearby the crash location 27 | }; 28 | 29 | struct dump_data_t 30 | { 31 | // contiguous region containing all addressable ranges 32 | uint8_t regs[RAMSTART]; 33 | uint8_t sram[RAMSIZE]; 34 | }; 35 | 36 | struct dump_t 37 | { 38 | struct dump_header_t header; 39 | 40 | // data is page aligned (no real space waste, due to the larger 41 | // alignment required for the whole dump) 42 | struct dump_data_t __attribute__((aligned(256))) data; 43 | }; 44 | 45 | // dump offset must be aligned to lower 4kb sector boundary 46 | #define DUMP_OFFSET ((XFLASH_SIZE - sizeof(dump_t)) & ~0xFFFul) 47 | 48 | #define DUMP_SIZE (XFLASH_SIZE - DUMP_OFFSET) // effective dump size area 49 | #define LANG_SIZE DUMP_OFFSET // available language space 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/SdFatUtil.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2008 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #include "Marlin.h" 21 | #ifdef SDSUPPORT 22 | 23 | #ifndef SdFatUtil_h 24 | #define SdFatUtil_h 25 | /** 26 | * \file 27 | * \brief Useful utility functions. 28 | */ 29 | #include "Marlin.h" 30 | #include "MarlinSerial.h" 31 | /** Store and print a string in flash memory.*/ 32 | #define PgmPrint(x) SerialPrint_P(PSTR(x)) 33 | /** Store and print a string in flash memory followed by a CR/LF.*/ 34 | #define PgmPrintln(x) SerialPrintln_P(PSTR(x)) 35 | 36 | namespace SdFatUtil { 37 | int FreeRam(); 38 | void print_P( PGM_P str); 39 | void println_P( PGM_P str); 40 | void SerialPrint_P(PGM_P str); 41 | void SerialPrintln_P(PGM_P str); 42 | void set_stack_guard(); 43 | bool test_stack_integrity(); 44 | } 45 | 46 | using namespace SdFatUtil; // NOLINT 47 | #endif // #define SdFatUtil_h 48 | 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /src/sm4.h: -------------------------------------------------------------------------------- 1 | //sm4.h - simple 4-axis stepper control 2 | #ifndef _SM4_H 3 | #define _SM4_H 4 | 5 | #include 6 | #include "config.h" 7 | 8 | 9 | #if defined(__cplusplus) 10 | extern "C" { 11 | #endif //defined(__cplusplus) 12 | 13 | 14 | // callback prototype for stop condition (return 0 - continue, return 1 - stop) 15 | typedef uint8_t (*sm4_stop_cb_t)(); 16 | 17 | // callback prototype for updating position counters 18 | typedef void (*sm4_update_pos_cb_t)(uint16_t dx, uint16_t dy, uint16_t dz, uint16_t de); 19 | 20 | // callback prototype for calculating delay 21 | typedef uint16_t (*sm4_calc_delay_cb_t)(uint16_t nd, uint16_t dd); 22 | 23 | 24 | // callback pointer - stop 25 | extern sm4_stop_cb_t sm4_stop_cb; 26 | 27 | // callback pointer - update_pos 28 | extern sm4_update_pos_cb_t sm4_update_pos_cb; 29 | 30 | // callback pointer - calc_delay 31 | extern sm4_calc_delay_cb_t sm4_calc_delay_cb; 32 | 33 | 34 | // returns direction for single axis (0 - positive, 1 - negative) 35 | extern uint8_t sm4_get_dir(uint8_t axis); 36 | 37 | // set direction for single axis (0 - positive, 1 - negative) 38 | extern void sm4_set_dir(uint8_t axis, uint8_t dir); 39 | 40 | // returns direction of all axes as bitmask (0 - positive, 1 - negative) 41 | extern uint8_t sm4_get_dir_bits(void); 42 | 43 | // set direction for all axes as bitmask (0 - positive, 1 - negative) 44 | extern void sm4_set_dir_bits(uint8_t dir_bits); 45 | 46 | // step axes by bitmask 47 | extern void sm4_do_step(uint8_t axes_mask); 48 | 49 | // xyze linear-interpolated relative move, returns remaining diagonal steps (>0 means stoped) 50 | extern uint16_t sm4_line_xyze_ui(uint16_t dx, uint16_t dy, uint16_t dz, uint16_t de); 51 | extern uint16_t sm4_line_xyz_ui(uint16_t dx, uint16_t dy, uint16_t dz); 52 | 53 | 54 | #if defined(__cplusplus) 55 | } 56 | #endif //defined(__cplusplus) 57 | #endif //_SM4_H 58 | -------------------------------------------------------------------------------- /src/la10compat.h: -------------------------------------------------------------------------------- 1 | // la10compat: LA10->LA15 conversion 2 | // 3 | // When the current mode is UNKNOWN autodetection is active and any K<10 4 | // will set the mode to LA15, LA10 is set otherwise. When LA10 5 | // compatbility mode is active the K factor is converted to a LA15 6 | // equivalent (that is, the return value is always a LA15 value). 7 | // 8 | // E-jerk<2 is also bumped in LA10 mode to restore the the printing speed 9 | // to values comparable to existing settings. 10 | // 11 | // Once the interpretation mode has been set it is kept until the mode 12 | // is explicitly reset. This is done to handle transparent fallback for 13 | // old firmware revisions in combination with the following gcode 14 | // sequence: 15 | // 16 | // M900 K0.01 ; set LA15 value (interpreted by any firmware) 17 | // M900 K10 ; set LA10 value (ignored by LA15 firmware) 18 | // 19 | // A LA15 firmware without this module will only parse the first 20 | // correctly, rejecting the second. A LA10 FW will parse both, but keep 21 | // the last value. Since the LA15 value, if present, corresponds to the 22 | // truth value, the compatibility stub needs to "lock" onto the first 23 | // seen value for the current print. 24 | // 25 | // The mode needs to be carefully reset for each print in order for 26 | // diffent versions of M900 to be interpreted independently. 27 | 28 | #pragma once 29 | 30 | enum __attribute__((packed)) LA10C_MODE 31 | { 32 | LA10C_UNKNOWN = 0, 33 | LA10C_LA15 = 1, 34 | LA10C_LA10 = 2 35 | }; 36 | 37 | // Explicitly set/get/reset the interpretation mode for la10c_value() 38 | void la10c_mode_change(LA10C_MODE mode); 39 | LA10C_MODE la10c_mode_get(); 40 | static inline void la10c_reset() { la10c_mode_change(LA10C_UNKNOWN); } 41 | 42 | // Return a LA15 K value according to the supplied value and mode 43 | float la10c_value(float k); 44 | 45 | // Return an updated LA15 E-jerk value according to the current mode 46 | float la10c_jerk(float j); 47 | -------------------------------------------------------------------------------- /src/vector_3.h: -------------------------------------------------------------------------------- 1 | /* 2 | vector_3.cpp - Vector library for bed leveling 3 | Copyright (c) 2012 Lars Brubaker. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #ifndef VECTOR_3_H 20 | #define VECTOR_3_H 21 | 22 | #ifdef ENABLE_AUTO_BED_LEVELING 23 | class matrix_3x3; 24 | 25 | struct vector_3 26 | { 27 | float x, y, z; 28 | 29 | vector_3(); 30 | vector_3(float x, float y, float z); 31 | 32 | static vector_3 cross(vector_3 a, vector_3 b); 33 | 34 | vector_3 operator+(vector_3 v); 35 | vector_3 operator-(vector_3 v); 36 | void normalize(); 37 | float get_length(); 38 | vector_3 get_normal(); 39 | 40 | void debug(char* title); 41 | 42 | void apply_rotation(matrix_3x3 matrix); 43 | }; 44 | 45 | struct matrix_3x3 46 | { 47 | float matrix[9]; 48 | 49 | static matrix_3x3 create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2); 50 | static matrix_3x3 create_look_at(vector_3 target); 51 | static matrix_3x3 transpose(matrix_3x3 original); 52 | 53 | void set_to_identity(); 54 | 55 | void debug(char* title); 56 | }; 57 | 58 | 59 | void apply_rotation_xyz(matrix_3x3 rotationMatrix, float &x, float& y, float& z); 60 | #endif // ENABLE_AUTO_BED_LEVELING 61 | 62 | #endif // VECTOR_3_H 63 | -------------------------------------------------------------------------------- /src/printers.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINTERS_H 2 | #define PRINTERS_H 3 | 4 | #define PRINTER_UNKNOWN 0 5 | 6 | // *** MK1 7 | #define PRINTER_MK1 100 8 | #define PRINTER_MK1_NAME "MK1" 9 | // *** MK2 10 | #define PRINTER_MK2 200 11 | #define PRINTER_MK2_NAME "MK2" 12 | #define PRINTER_MK2_SNMM 201 // better is "10200" 13 | #define PRINTER_MK2_SNMM_NAME "MK2MM" // better is "MK2MMU1" 14 | // *** MK2S 15 | #define PRINTER_MK2S 202 16 | #define PRINTER_MK2S_NAME "MK2S" 17 | #define PRINTER_MK2S_SNMM 203 // better is "10202" 18 | #define PRINTER_MK2S_SNMM_NAME "MK2SMM" // better is "MK2SMMU1" 19 | // *** MK2.5 20 | #define PRINTER_MK25 250 21 | #define PRINTER_MK25_NAME "MK2.5" 22 | #define PRINTER_MK25_MMU2 20250 23 | #define PRINTER_MK25_MMU2_NAME "MK2.5MMU2" 24 | // *** MK2.5S 25 | #define PRINTER_MK25S 252 26 | #define PRINTER_MK25S_NAME "MK2.5S" 27 | #define PRINTER_MK25S_MMU2 20252 28 | #define PRINTER_MK25S_MMU2_NAME "MK2.5SMMU2S" 29 | // *** MK2.5S Bear 30 | #define PRINTER_MK25S_Bear 254 31 | #define PRINTER_MK25S_Bear_NAME "MK2.5SBear" 32 | #define PRINTER_MK25S_Bear_MMU2 20254 33 | #define PRINTER_MK25S_Bear_MMU2_NAME "MK2.5SBearMMU2S" 34 | // *** MK3 35 | #define PRINTER_MK3 300 36 | #define PRINTER_MK3_NAME "MK3" 37 | #define PRINTER_MK3_MMU2 20300 38 | #define PRINTER_MK3_MMU2_NAME "MK3MMU2" 39 | // *** MK3S 40 | #define PRINTER_MK3S 302 41 | #define PRINTER_MK3S_NAME "MK3S" 42 | #define PRINTER_MK3S_MMU2 20302 43 | #define PRINTER_MK3S_MMU2_NAME "MK3SMMU2S" 44 | 45 | // *** MK3S Bear 46 | #define PRINTER_MK3S_Bear 304 47 | #define PRINTER_MK3S_Bear_NAME "MK3SBear" 48 | #define PRINTER_MK3S_Bear_MMU2 20304 49 | #define PRINTER_MK3S_Bear_MMU2_NAME "MK3SBearMMU2S" 50 | 51 | #endif //PRINTERS_H 52 | -------------------------------------------------------------------------------- /src/Timer.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Marek Bel 4 | */ 5 | 6 | #include "Timer.h" 7 | #include "system_timer.h" 8 | 9 | /** 10 | * @brief construct Timer 11 | * 12 | * It is guaranteed, that construction is equivalent with zeroing all members. 13 | * This property can be exploited in menu_data. 14 | */ 15 | template 16 | Timer::Timer() : m_isRunning(false), m_started() 17 | { 18 | } 19 | 20 | /** 21 | * @brief Start timer 22 | */ 23 | template 24 | void Timer::start() 25 | { 26 | m_started = _millis(); 27 | m_isRunning = true; 28 | } 29 | 30 | /** 31 | * @brief Timer has expired 32 | * 33 | * Timer is considered expired after msPeriod has passed from time the timer was started. 34 | * Timer is stopped after expiration. 35 | * This function must be called at least each (T maximum value - msPeriod) milliseconds to be sure to 36 | * catch first expiration. 37 | * This function is expected to handle wrap around of time register well. 38 | * 39 | * @param msPeriod Time interval in milliseconds. Do not omit "ul" when using constant literal with LongTimer. 40 | * @retval true Timer has expired 41 | * @retval false Timer not expired yet, or is not running, or time window in which is timer considered expired passed. 42 | */ 43 | template 44 | bool Timer::expired(T msPeriod) 45 | { 46 | if (!m_isRunning) return false; 47 | bool expired = false; 48 | const T now = _millis(); 49 | if (m_started <= m_started + msPeriod) 50 | { 51 | if ((now >= m_started + msPeriod) || (now < m_started)) 52 | { 53 | expired = true; 54 | } 55 | } 56 | else 57 | { 58 | if ((now >= m_started + msPeriod) && (now < m_started)) 59 | { 60 | expired = true; 61 | } 62 | } 63 | if (expired) m_isRunning = false; 64 | return expired; 65 | } 66 | 67 | template class Timer; 68 | template class Timer; 69 | -------------------------------------------------------------------------------- /src/twi.h: -------------------------------------------------------------------------------- 1 | /* 2 | twi.h - Stripped-down TWI/I2C library 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | #pragma once 21 | 22 | #include 23 | #include 24 | 25 | #ifndef TWI_FREQ 26 | #define TWI_FREQ 400000L 27 | #endif 28 | 29 | /* 30 | * Function twi_init 31 | * Desc readys twi pins and sets twi bitrate 32 | * Input none 33 | * Output none 34 | */ 35 | void twi_init(void); 36 | 37 | /* 38 | * Function twi_disable 39 | * Desc disables twi pins 40 | * Input none 41 | * Output none 42 | */ 43 | void twi_disable(void); 44 | 45 | /* 46 | * Function twi_r8 47 | * Desc read a single byte from a device 48 | * Input address: 7bit i2c device address 49 | * reg: register address 50 | * data: pointer to byte for result 51 | * Output 0 on success 52 | */ 53 | uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data); 54 | 55 | /* 56 | * Function twi_w8 57 | * Desc write a single byte from a device 58 | * Input address: 7bit i2c device address 59 | * reg: register address 60 | * data: byte to write 61 | * Output 0 on success 62 | */ 63 | uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data); 64 | -------------------------------------------------------------------------------- /src/xflash.h: -------------------------------------------------------------------------------- 1 | //xflash.h 2 | #ifndef _XFLASH_H 3 | #define _XFLASH_H 4 | 5 | #include 6 | #include "config.h" 7 | #include "spi.h" 8 | 9 | 10 | 11 | #define XFLASH_STATUS_BUSY 0x01 12 | #define XFLASH_STATUS_WEL 0x02 13 | #define XFLASH_STATUS_BP0 0x04 14 | #define XFLASH_STATUS_BP1 0x08 15 | #define XFLASH_STATUS_TB 0x20 16 | #define XFLASH_STATUS_SRP 0x80 17 | 18 | #define XFLASH_SPI_RATE 0 // fosc/4 = 4MHz 19 | #define XFLASH_SPCR SPI_SPCR(XFLASH_SPI_RATE, 1, 1, 1, 0) 20 | #define XFLASH_SPSR SPI_SPSR(XFLASH_SPI_RATE) 21 | 22 | #define XFLASH_SPI_ENTER() spi_setup(XFLASH_SPCR, XFLASH_SPSR) 23 | 24 | #if defined(__cplusplus) 25 | extern "C" { 26 | #endif //defined(__cplusplus) 27 | 28 | 29 | extern int8_t xflash_init(void); 30 | extern void xflash_enable_wr(void); 31 | extern void xflash_disable_wr(void); 32 | extern uint8_t xflash_rd_status_reg(void); 33 | #if 0 34 | extern void w25x20cl_wr_status_reg(uint8_t val); 35 | #endif 36 | extern void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt); 37 | 38 | extern void xflash_sector_erase(uint32_t addr); 39 | extern void xflash_block32_erase(uint32_t addr); 40 | extern void xflash_block64_erase(uint32_t addr); 41 | extern void xflash_chip_erase(void); 42 | extern void xflash_rd_uid(uint8_t* uid); 43 | extern void xflash_wait_busy(void); 44 | 45 | // write up to a single page of data (256bytes) 46 | extern void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); 47 | 48 | // write up to a single page of data from program memory 49 | extern void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); 50 | 51 | // xflash_multipage_program: high-level interface for multi-page writes. 52 | // Write any amount of data, chunking writes to page boundaries as needed. 53 | // Automatically enables writes and waits for completion. 54 | extern void xflash_multipage_program(uint32_t addr, uint8_t* data, uint16_t cnt); 55 | 56 | #if defined(__cplusplus) 57 | } 58 | #endif //defined(__cplusplus) 59 | #endif //_XFLASH_H 60 | -------------------------------------------------------------------------------- /src/stk500.h: -------------------------------------------------------------------------------- 1 | /* STK500 constants list, from AVRDUDE 2 | * 3 | * Trivial set of constants derived from Atmel App Note AVR061 4 | * Not copyrighted. Released to the public domain. 5 | */ 6 | 7 | #define STK_OK 0x10 8 | #define STK_FAILED 0x11 // Not used 9 | #define STK_UNKNOWN 0x12 // Not used 10 | #define STK_NODEVICE 0x13 // Not used 11 | #define STK_INSYNC 0x14 // ' ' 12 | #define STK_NOSYNC 0x15 // Not used 13 | #define ADC_CHANNEL_ERROR 0x16 // Not used 14 | #define ADC_MEASURE_OK 0x17 // Not used 15 | #define PWM_CHANNEL_ERROR 0x18 // Not used 16 | #define PWM_ADJUST_OK 0x19 // Not used 17 | #define CRC_EOP 0x20 // 'SPACE' 18 | #define STK_GET_SYNC 0x30 // '0' 19 | #define STK_GET_SIGN_ON 0x31 // '1' 20 | #define STK_SET_PARAMETER 0x40 // '@' 21 | #define STK_GET_PARAMETER 0x41 // 'A' 22 | #define STK_SET_DEVICE 0x42 // 'B' 23 | #define STK_SET_DEVICE_EXT 0x45 // 'E' 24 | #define STK_ENTER_PROGMODE 0x50 // 'P' 25 | #define STK_LEAVE_PROGMODE 0x51 // 'Q' 26 | #define STK_CHIP_ERASE 0x52 // 'R' 27 | #define STK_CHECK_AUTOINC 0x53 // 'S' 28 | #define STK_LOAD_ADDRESS 0x55 // 'U' 29 | #define STK_UNIVERSAL 0x56 // 'V' 30 | #define STK_PROG_FLASH 0x60 // '`' 31 | #define STK_PROG_DATA 0x61 // 'a' 32 | #define STK_PROG_FUSE 0x62 // 'b' 33 | #define STK_PROG_LOCK 0x63 // 'c' 34 | #define STK_PROG_PAGE 0x64 // 'd' 35 | #define STK_PROG_FUSE_EXT 0x65 // 'e' 36 | #define STK_READ_FLASH 0x70 // 'p' 37 | #define STK_READ_DATA 0x71 // 'q' 38 | #define STK_READ_FUSE 0x72 // 'r' 39 | #define STK_READ_LOCK 0x73 // 's' 40 | #define STK_READ_PAGE 0x74 // 't' 41 | #define STK_READ_SIGN 0x75 // 'u' 42 | #define STK_READ_OSCCAL 0x76 // 'v' 43 | #define STK_READ_FUSE_EXT 0x77 // 'w' 44 | #define STK_READ_OSCCAL_EXT 0x78 // 'x' 45 | #define STK_SW_MAJOR 0x81 // ' ' 46 | #define STK_SW_MINOR 0x82 // ' ' 47 | 48 | /* AVR raw commands sent via STK_UNIVERSAL */ 49 | #define AVR_OP_LOAD_EXT_ADDR 0x4d 50 | -------------------------------------------------------------------------------- /src/adc.c: -------------------------------------------------------------------------------- 1 | //adc.c 2 | 3 | #include "adc.h" 4 | #include 5 | #include 6 | #include 7 | #include "pins.h" 8 | 9 | uint8_t adc_state; 10 | uint8_t adc_count; 11 | uint16_t adc_values[ADC_CHAN_CNT]; 12 | uint16_t adc_sim_mask; 13 | 14 | 15 | #ifdef ADC_CALLBACK 16 | extern void ADC_CALLBACK(void); 17 | #endif //ADC_CALLBACK 18 | 19 | 20 | void adc_init(void) 21 | { 22 | puts_P(PSTR("adc_init")); 23 | adc_sim_mask = 0x00; 24 | ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); 25 | ADMUX |= (1 << REFS0); 26 | ADCSRA |= (1 << ADEN); 27 | // ADCSRA |= (1 << ADIF) | (1 << ADSC); 28 | DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff); 29 | DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8); 30 | adc_reset(); 31 | // adc_sim_mask = 0b0101; 32 | // adc_sim_mask = 0b100101; 33 | // adc_values[0] = 1023 * 16; 34 | // adc_values[2] = 1023 * 16; 35 | // adc_values[5] = 1002 * 16; 36 | } 37 | 38 | void adc_reset(void) 39 | { 40 | adc_state = 0; 41 | adc_count = 0; 42 | uint8_t i; for (i = 0; i < ADC_CHAN_CNT; i++) 43 | if ((adc_sim_mask & (1 << i)) == 0) 44 | adc_values[i] = 0; 45 | } 46 | 47 | void adc_setmux(uint8_t ch) 48 | { 49 | ch &= 0x0f; 50 | if (ch & 0x08) ADCSRB |= (1 << MUX5); 51 | else ADCSRB &= ~(1 << MUX5); 52 | ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07); 53 | } 54 | 55 | uint8_t adc_chan(uint8_t index) 56 | { 57 | uint8_t chan = 0; 58 | uint16_t mask = 1; 59 | while (mask) 60 | { 61 | if ((mask & ADC_CHAN_MSK) && (index-- == 0)) break; 62 | mask <<= 1; 63 | chan++; 64 | } 65 | return chan; 66 | } 67 | 68 | void adc_cycle(void) 69 | { 70 | if (adc_state & 0x80) 71 | { 72 | uint8_t index = adc_state & 0x0f; 73 | if ((adc_sim_mask & (1 << index)) == 0) 74 | adc_values[index] += ADC; 75 | if (++index >= ADC_CHAN_CNT) 76 | { 77 | index = 0; 78 | adc_count++; 79 | if (adc_count >= ADC_OVRSAMPL) 80 | { 81 | #ifdef ADC_CALLBACK 82 | ADC_CALLBACK(); 83 | #endif //ADC_CALLBACK 84 | adc_reset(); 85 | } 86 | } 87 | adc_setmux(adc_chan(index)); 88 | adc_state = index; 89 | } 90 | else 91 | { 92 | ADCSRA |= (1 << ADSC); //start conversion 93 | adc_state |= 0x80; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/Dcodes.h: -------------------------------------------------------------------------------- 1 | #ifndef DCODES_H 2 | #define DCODES_H 3 | 4 | extern void dcode__1(); //D-1 - Endless loop (to simulate deadlock) 5 | extern void dcode_0(); //D0 - Reset 6 | extern void dcode_1(); //D1 - Clear EEPROM 7 | 8 | #if defined DEBUG_DCODE2 || defined DEBUG_DCODES 9 | extern void dcode_2(); //D2 - Read/Write RAM 10 | #endif 11 | 12 | #if defined DEBUG_DCODE3 || defined DEBUG_DCODES 13 | extern void dcode_3(); //D3 - Read/Write EEPROM 14 | #endif //DEBUG_DCODE3 15 | 16 | extern void dcode_4(); //D4 - Read/Write PIN 17 | 18 | #if defined DEBUG_DCODE5 || defined DEBUG_DCODES 19 | extern void dcode_5(); //D5 - Read/Write FLASH 20 | #endif //DEBUG_DCODE5 21 | 22 | #if defined DEBUG_DCODE6 || defined DEBUG_DCODES 23 | extern void dcode_6(); //D6 - Read/Write external FLASH 24 | #endif 25 | 26 | extern void dcode_7(); //D7 - Read/Write Bootloader 27 | extern void dcode_8(); //D8 - Read/Write PINDA 28 | extern void dcode_9(); //D9 - Read/Write ADC (Write=enable simulated, Read=disable simulated) 29 | extern void dcode_10(); //D10 - XYZ calibration = OK 30 | extern void dcode_12(); //D12 - Log time. Writes the current time in the log file. 31 | 32 | #ifdef XFLASH_DUMP 33 | extern void dcode_20(); //D20 - Generate an offline crash dump 34 | extern void dcode_21(); //D21 - Print crash dump to serial 35 | extern void dcode_22(); //D22 - Clear crash dump state 36 | #endif 37 | 38 | #ifdef EMERGENCY_SERIAL_DUMP 39 | #include "xflash_dump.h" 40 | extern void dcode_23(); //D23 - Request/generate an online serial crash dump 41 | extern bool emergency_serial_dump; //emergency dump enabled flag 42 | extern void serial_dump_and_reset(dump_crash_reason); 43 | #endif 44 | 45 | #ifdef HEATBED_ANALYSIS 46 | extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt". 47 | extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt". 48 | #endif //HEATBED_ANALYSIS 49 | 50 | extern void dcode_106(); //D106 - Print measured fan speed for different pwm values 51 | 52 | #ifdef TMC2130 53 | extern void dcode_2130(); //D2130 - TMC2130 54 | #endif //TMC2130 55 | 56 | #ifdef PAT9125 57 | extern void dcode_9125(); //D9125 - PAT9125 58 | #endif //PAT9125 59 | 60 | 61 | #endif //DCODES_H 62 | -------------------------------------------------------------------------------- /src/rbuf.c: -------------------------------------------------------------------------------- 1 | //rbuf.c 2 | #include "rbuf.h" 3 | //#include 4 | 5 | 6 | void rbuf_ini(uint8_t* ptr, uint8_t l) 7 | { 8 | ptr[0] = l; 9 | ptr[1] = 0; 10 | ptr[2] = 0; 11 | } 12 | 13 | //lock/unlock macros 14 | //#define _lock() uint8_t _sreg = SREG; cli(); 15 | //#define _unlock() SREG = _sreg; 16 | #define _lock() 17 | #define _unlock() 18 | 19 | //put single byte to buffer 20 | int rbuf_put(uint8_t* ptr, uint8_t b) 21 | { 22 | //#ifdef _NO_ASM 23 | _lock(); //lock 24 | uint8_t buf_w = ptr[1]; //get write index 25 | uint8_t buf_r = ptr[2]; //get read index 26 | _unlock(); //unlock 27 | ptr[4 + buf_w] = b; //store byte to buffer 28 | buf_w++; //incerment write index 29 | uint8_t buf_l = ptr[0]; //get length 30 | if (buf_w >= buf_l) buf_w = 0; //rotate write index 31 | if (buf_w == buf_r) return -1; //return -1 to signal buffer full 32 | ptr[1] = buf_w; //store write index 33 | return 0; //return 0 to signal success 34 | //#else //_NO_ASM 35 | // TODO - optimized assembler version 36 | // asm("movw r26, r24"); 37 | // asm("ld r18, X+"); 38 | // asm("cli"); 39 | // asm("ld r19, X+"); 40 | // asm("ld r20, X"); 41 | // asm("cp r19, r18"); 42 | // asm("brne .-6");*/ 43 | //#endif //_NO_ASM 44 | } 45 | 46 | //get single byte from buffer 47 | int rbuf_get(uint8_t* ptr) 48 | { 49 | //#ifdef _NO_ASM 50 | _lock(); //lock 51 | uint8_t buf_w = ptr[1]; //get write index 52 | uint8_t buf_r = ptr[2]; //get read index 53 | _unlock(); //unlock 54 | if (buf_r == buf_w) return -1; //return -1 to signal buffer empty 55 | int ret = ptr[4 + buf_r]; //get byte from buffer 56 | buf_r++; //increment read index 57 | uint8_t buf_l = ptr[0]; //get length 58 | if (buf_r >= buf_l) buf_r = 0; //rotate read index 59 | ptr[2] = buf_r; //store read index 60 | return ret; //return byte (0-255) 61 | // return 0; //return 0 to signal success 62 | //#else //_NO_ASM 63 | // TODO - optimized assembler version 64 | //#endif //_NO_ASM 65 | } -------------------------------------------------------------------------------- /src/AutoDeplete.cpp: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! @author: Marek Bel 3 | //! @date Jan 3, 2019 4 | 5 | #include "AutoDeplete.h" 6 | #include "assert.h" 7 | 8 | //! @brief bit field marking depleted filaments 9 | //! 10 | //! binary 1 marks filament as depleted 11 | //! Zero initialized value means, that no filament is depleted. 12 | static uint8_t depleted; 13 | static const uint8_t filamentCount = 5; 14 | 15 | //! @return binary 1 for all filaments 16 | //! @par fCount number of filaments 17 | static constexpr uint8_t allDepleted(uint8_t fCount) 18 | { 19 | return fCount == 1 ? 1 : ((1 << (fCount - 1)) | allDepleted(fCount - 1)); 20 | } 21 | 22 | //! @brief Is filament available for printing? 23 | //! @par filament Filament number to be checked 24 | //! @retval true Filament is available for printing. 25 | //! @retval false Filament is not available for printing. 26 | static bool loaded(uint8_t filament) 27 | { 28 | if (depleted & (1 << filament)) return false; 29 | return true; 30 | } 31 | 32 | //! @brief Mark filament as not available for printing. 33 | //! @par filament filament to be marked 34 | void ad_markDepleted(uint8_t filament) 35 | { 36 | assert(filament < filamentCount); 37 | if (filament < filamentCount) 38 | { 39 | depleted |= 1 << filament; 40 | } 41 | } 42 | 43 | //! @brief Mark filament as available for printing. 44 | //! @par filament filament to be marked 45 | void ad_markLoaded(uint8_t filament) 46 | { 47 | assert(filament < filamentCount); 48 | if (filament < filamentCount) 49 | { 50 | depleted &= ~(1 << filament); 51 | } 52 | } 53 | 54 | //! @brief Get alternative filament, which is not depleted 55 | //! @par filament filament 56 | //! @return Filament, if it is depleted, returns next available, 57 | //! if all filaments are depleted, returns filament function parameter. 58 | uint8_t ad_getAlternative(uint8_t filament) 59 | { 60 | assert(filament < filamentCount); 61 | for (uint8_t i = 0; i 7 | #include 8 | 9 | typedef struct 10 | { 11 | char version[4]; 12 | float axis_steps_per_unit[4]; 13 | float max_feedrate_normal[4]; 14 | unsigned long max_acceleration_units_per_sq_second_normal[4]; 15 | float acceleration; //!< Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX 16 | float retract_acceleration; //!< mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX 17 | float minimumfeedrate; 18 | float mintravelfeedrate; 19 | unsigned long minsegmenttime; 20 | float max_jerk[4]; //!< Jerk is a maximum immediate velocity change. 21 | float add_homing[3]; 22 | float zprobe_zoffset; 23 | float Kp; 24 | float Ki; 25 | float Kd; 26 | float bedKp; 27 | float bedKi; 28 | float bedKd; 29 | int lcd_contrast; //!< unused 30 | bool autoretract_enabled; 31 | float retract_length; 32 | float retract_feedrate; 33 | float retract_zlift; 34 | float retract_recover_length; 35 | float retract_recover_feedrate; 36 | bool volumetric_enabled; 37 | float filament_size[1]; //!< cross-sectional area of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder. 38 | float max_feedrate_silent[4]; //!< max speeds for silent mode 39 | unsigned long max_acceleration_units_per_sq_second_silent[4]; 40 | unsigned char axis_ustep_resolution[4]; 41 | float travel_acceleration; //!< travel acceleration mm/s^2 42 | } M500_conf; 43 | 44 | extern M500_conf cs; 45 | 46 | void Config_ResetDefault(); 47 | 48 | #ifndef DISABLE_M503 49 | void Config_PrintSettings(uint8_t level = 0); 50 | #else 51 | FORCE_INLINE void Config_PrintSettings() {} 52 | #endif 53 | 54 | #ifdef EEPROM_SETTINGS 55 | void Config_StoreSettings(); 56 | bool Config_RetrieveSettings(); 57 | #else 58 | FORCE_INLINE void Config_StoreSettings() {} 59 | FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_PrintSettings(); } 60 | #endif 61 | 62 | inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); } 63 | inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); } 64 | inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); } 65 | 66 | #endif//CONFIG_STORE_H 67 | -------------------------------------------------------------------------------- /src/SdFile.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | /** 21 | * \file 22 | * \brief SdFile class 23 | */ 24 | #include "Marlin.h" 25 | 26 | #ifdef SDSUPPORT 27 | #include "SdBaseFile.h" 28 | //#include 29 | #ifndef SdFile_h 30 | #define SdFile_h 31 | //------------------------------------------------------------------------------ 32 | /** 33 | * \class SdFile 34 | * \brief SdBaseFile with Print. 35 | */ 36 | class SdFile : public SdBaseFile/*, public Print*/ { 37 | // GCode filtering vars and methods - due to optimization reasons not wrapped in a separate class 38 | 39 | // beware - this read ptr is manipulated inside just 2 methods - readFilteredGcode and gfReset 40 | // If you even want to call gfReset from readFilteredGcode, you must make sure 41 | // to update gfReadPtr inside readFilteredGcode from a local copy (see explanation of this trick in readFilteredGcode) 42 | const uint8_t *gfReadPtr; 43 | 44 | uint32_t gfBlock; // remember the current file block to be kept in cache - due to reuse of the memory, the block may fall out a must be read back 45 | uint16_t gfOffset; 46 | 47 | const uint8_t *gfBlockBuffBegin()const; 48 | 49 | void gfReset(); 50 | 51 | bool gfEnsureBlock(); 52 | bool gfComputeNextFileBlock(); 53 | void gfUpdateCurrentPosition(uint16_t inc); 54 | public: 55 | SdFile() {} 56 | SdFile(const char* name, uint8_t oflag); 57 | #if ARDUINO >= 100 58 | size_t write(uint8_t b); 59 | #else 60 | void write(uint8_t b); 61 | #endif 62 | 63 | bool openFilteredGcode(SdBaseFile* dirFile, const char* path); 64 | int16_t readFilteredGcode(); 65 | bool seekSetFilteredGcode(uint32_t pos); 66 | int16_t write(const void* buf, uint16_t nbyte); 67 | void write(const char* str); 68 | void write_P(PGM_P str); 69 | void writeln_P(PGM_P str); 70 | }; 71 | #endif // SdFile_h 72 | 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/la10compat.cpp: -------------------------------------------------------------------------------- 1 | #include "la10compat.h" 2 | #include "Marlin.h" 3 | #include 4 | 5 | 6 | static LA10C_MODE la10c_mode = LA10C_UNKNOWN; // Current LA compatibility mode 7 | static float la10c_orig_jerk = 0; // Unadjusted/saved e-jerk 8 | 9 | 10 | LA10C_MODE la10c_mode_get() 11 | { 12 | return la10c_mode; 13 | } 14 | 15 | 16 | void la10c_mode_change(LA10C_MODE mode) 17 | { 18 | if(mode == la10c_mode) return; 19 | 20 | // always restore to the last unadjusted E-jerk value 21 | if(la10c_orig_jerk) 22 | cs.max_jerk[E_AXIS] = la10c_orig_jerk; 23 | 24 | SERIAL_ECHOPGM("LA10C: Linear Advance mode: "); 25 | switch(mode) 26 | { 27 | case LA10C_UNKNOWN: SERIAL_ECHOLNPGM("UNKNOWN"); break; 28 | case LA10C_LA15: SERIAL_ECHOLNPGM("1.5"); break; 29 | case LA10C_LA10: SERIAL_ECHOLNPGM("1.0"); break; 30 | } 31 | la10c_mode = mode; 32 | 33 | // adjust the E-jerk if needed 34 | cs.max_jerk[E_AXIS] = la10c_jerk(cs.max_jerk[E_AXIS]); 35 | } 36 | 37 | 38 | // Approximate a LA10 value to a LA15 equivalent. 39 | static float la10c_convert(float k) 40 | { 41 | float new_K = k * 0.002 - 0.01; 42 | return new_K < 0? 0: 43 | new_K > (LA_K_MAX - FLT_EPSILON)? (LA_K_MAX - FLT_EPSILON): 44 | new_K; 45 | } 46 | 47 | 48 | float la10c_value(float k) 49 | { 50 | if(la10c_mode == LA10C_UNKNOWN) 51 | { 52 | // do not autodetect until a valid value is seen 53 | if(k == 0) 54 | return 0; 55 | else if(k < 0) 56 | return -1; 57 | 58 | la10c_mode_change(k < LA_LA10_MIN? LA10C_LA15: LA10C_LA10); 59 | } 60 | 61 | if(la10c_mode == LA10C_LA15) 62 | return (k >= 0 && k < LA_K_MAX? k: -1); 63 | else 64 | return (k >= 0? la10c_convert(k): -1); 65 | } 66 | 67 | 68 | float la10c_jerk(float j) 69 | { 70 | la10c_orig_jerk = j; 71 | 72 | if(la10c_mode != LA10C_LA10) 73 | return j; 74 | 75 | // check for a compatible range of values prior to convert (be sure that 76 | // a higher E-jerk would still be compatible wrt the E accell range) 77 | if(j < 4.5 && cs.max_acceleration_units_per_sq_second_normal[E_AXIS] < 2000) 78 | return j; 79 | 80 | // bring low E-jerk values into equivalent LA 1.5 values by 81 | // flattening the response in the (0.3-4.5) range using a piecewise 82 | // function. Is it truly worth to preserve the difference between 83 | // 1.5/2.5 E-jerk for LA1.0? Probably not, but we try nonetheless. 84 | j = j < 0.3? j * 11.5: 85 | j < 4.5? j * 0.25 + 3.375: 86 | j; 87 | 88 | SERIAL_ECHOPGM("LA10C: Adjusted E-Jerk: "); 89 | SERIAL_ECHOLN(j); 90 | return j; 91 | } 92 | -------------------------------------------------------------------------------- /src/pins.h: -------------------------------------------------------------------------------- 1 | #ifndef PINS_H 2 | #define PINS_H 3 | 4 | #include "boards.h" 5 | 6 | #define LARGE_FLASH true 7 | 8 | /***************************************************************** 9 | * Rambo Pin Assignments 1.3 10 | ******************************************************************/ 11 | 12 | #if MOTHERBOARD == BOARD_RAMBO_MINI_1_0 //200 - orig 102 13 | #include "pins_Rambo_1_0.h" 14 | #endif //MOTHERBOARD == BOARD_RAMBO_MINI_1_0 15 | 16 | #if MOTHERBOARD == BOARD_RAMBO_MINI_1_3 //203 - orig 302 17 | #include "pins_Rambo_1_3.h" 18 | #endif //MOTHERBOARD == BOARD_RAMBO_MINI_1_3 19 | 20 | #if MOTHERBOARD == BOARD_EINSY_1_0a //310 - new 21 | #include "pins_Einsy_1_0.h" 22 | #endif //MOTHERBOARD == BOARD_EINSY_1_0a 23 | 24 | #ifndef KNOWN_BOARD 25 | #error Unknown MOTHERBOARD value in configuration.h 26 | #endif 27 | 28 | #if !defined(SDA_PIN) && (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) 29 | #define SDA_PIN 20 30 | #define SCL_PIN 21 31 | #endif 32 | 33 | //List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! 34 | #define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, 35 | #if EXTRUDERS > 1 36 | #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN, 37 | #else 38 | #define _E1_PINS 39 | #endif 40 | #if EXTRUDERS > 2 41 | #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN, 42 | #else 43 | #define _E2_PINS 44 | #endif 45 | 46 | #ifdef X_STOP_PIN 47 | #if X_HOME_DIR < 0 48 | #define X_MIN_PIN X_STOP_PIN 49 | #define X_MAX_PIN -1 50 | #else 51 | #define X_MIN_PIN -1 52 | #define X_MAX_PIN X_STOP_PIN 53 | #endif 54 | #endif 55 | 56 | #ifdef Y_STOP_PIN 57 | #if Y_HOME_DIR < 0 58 | #define Y_MIN_PIN Y_STOP_PIN 59 | #define Y_MAX_PIN -1 60 | #else 61 | #define Y_MIN_PIN -1 62 | #define Y_MAX_PIN Y_STOP_PIN 63 | #endif 64 | #endif 65 | 66 | #ifdef Z_STOP_PIN 67 | #if Z_HOME_DIR < 0 68 | #define Z_MIN_PIN Z_STOP_PIN 69 | #define Z_MAX_PIN -1 70 | #else 71 | #define Z_MIN_PIN -1 72 | #define Z_MAX_PIN Z_STOP_PIN 73 | #endif 74 | #endif 75 | 76 | #ifdef DISABLE_MAX_ENDSTOPS 77 | #define X_MAX_PIN -1 78 | #define Y_MAX_PIN -1 79 | #define Z_MAX_PIN -1 80 | #endif 81 | 82 | #ifdef DISABLE_MIN_ENDSTOPS 83 | #define X_MIN_PIN -1 84 | #define Y_MIN_PIN -1 85 | #define Z_MIN_PIN -1 86 | #endif 87 | 88 | #define SENSITIVE_PINS {0, 1, X_STEP_PIN, X_DIR_PIN, X_ENABLE_PIN, X_MIN_PIN, X_MAX_PIN, Y_STEP_PIN, Y_DIR_PIN, Y_ENABLE_PIN, Y_MIN_PIN, Y_MAX_PIN, Z_STEP_PIN, Z_DIR_PIN, Z_ENABLE_PIN, Z_MIN_PIN, Z_MAX_PIN, PS_ON_PIN, \ 89 | HEATER_BED_PIN, FAN_PIN, \ 90 | _E0_PINS _E1_PINS _E2_PINS \ 91 | analogInputToDigitalPin(TEMP_0_PIN), analogInputToDigitalPin(TEMP_1_PIN), analogInputToDigitalPin(TEMP_2_PIN), analogInputToDigitalPin(TEMP_BED_PIN) } 92 | 93 | #endif //__PINS_H 94 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | 4 | extern const char* FW_VERSION_STR_P(); 5 | 6 | // Definition of a firmware flavor numerical values. 7 | enum FirmwareRevisionFlavorType 8 | { 9 | FIRMWARE_REVISION_DEV = 0, 10 | FIRMWARE_REVISION_ALPHA = 1, 11 | FIRMWARE_REVISION_BETA = 2, 12 | FIRMWARE_REVISION_RC, 13 | FIRMWARE_REVISION_RC2, 14 | FIRMWARE_REVISION_RC3, 15 | FIRMWARE_REVISION_RC4, 16 | FIRMWARE_REVISION_RC5, 17 | FIRMWARE_REVISION_RELEASED = 127 18 | }; 19 | 20 | extern bool show_upgrade_dialog_if_version_newer(const char *version_string); 21 | extern bool force_selftest_if_fw_version(); 22 | 23 | extern void update_current_firmware_version_to_eeprom(); 24 | 25 | 26 | 27 | inline int8_t eeprom_read_int8(unsigned char* addr) { 28 | uint8_t v = eeprom_read_byte(addr); 29 | return *reinterpret_cast(&v); 30 | } 31 | 32 | inline void eeprom_update_int8(unsigned char* addr, int8_t v) { 33 | eeprom_update_byte(addr, *reinterpret_cast(&v)); 34 | } 35 | 36 | 37 | //-// 38 | #define EEPROM_NOZZLE_DIAMETER_uM_DEFAULT 400 39 | 40 | enum class ClPrintChecking:uint_least8_t 41 | { 42 | _Nozzle=1, 43 | _Model=2, 44 | _Smodel=3, 45 | _Version=4, 46 | _Gcode=5 47 | }; 48 | 49 | enum class ClNozzleDiameter:uint_least8_t 50 | { 51 | _Diameter_250=25, 52 | _Diameter_400=40, 53 | _Diameter_600=60, 54 | _Diameter_800=80, 55 | _Diameter_Undef=EEPROM_EMPTY_VALUE 56 | }; 57 | 58 | enum class ClCheckMode:uint_least8_t 59 | { 60 | _None, 61 | _Warn, 62 | _Strict, 63 | _Undef=EEPROM_EMPTY_VALUE 64 | }; 65 | 66 | enum class ClCheckModel:uint_least8_t 67 | { 68 | _None, 69 | _Warn, 70 | _Strict, 71 | _Undef=EEPROM_EMPTY_VALUE 72 | }; 73 | 74 | enum class ClCheckVersion:uint_least8_t 75 | { 76 | _None, 77 | _Warn, 78 | _Strict, 79 | _Undef=EEPROM_EMPTY_VALUE 80 | }; 81 | 82 | enum class ClCheckGcode:uint_least8_t 83 | { 84 | _None, 85 | _Warn, 86 | _Strict, 87 | _Undef=EEPROM_EMPTY_VALUE 88 | }; 89 | 90 | #define COMPARE_VALUE_EQUAL (((uint8_t)ClCompareValue::_Equal<<6)+((uint8_t)ClCompareValue::_Equal<<4)+((uint8_t)ClCompareValue::_Equal<<2)+((uint8_t)ClCompareValue::_Equal)) 91 | enum class ClCompareValue:uint_least8_t 92 | { 93 | _Less=0, 94 | _Equal=1, 95 | _Greater=2 96 | }; 97 | 98 | extern ClNozzleDiameter oNozzleDiameter; 99 | extern ClCheckMode oCheckMode; 100 | extern ClCheckModel oCheckModel; 101 | extern ClCheckVersion oCheckVersion; 102 | extern ClCheckGcode oCheckGcode; 103 | 104 | void fCheckModeInit(); 105 | void nozzle_diameter_check(uint16_t nDiameter); 106 | void printer_model_check(uint16_t nPrinterModel); 107 | void printer_smodel_check(char* pStrPos); 108 | void fw_version_check(const char *pVersion); 109 | void gcode_level_check(uint16_t nGcodeLevel); 110 | 111 | void fSetMmuMode(bool bMMu); 112 | 113 | #define IP4_STR_SIZE 16 114 | extern void ip4_to_str(char* dest, uint8_t* IP); 115 | 116 | #endif /* UTIL_H */ 117 | -------------------------------------------------------------------------------- /src/mmu.h: -------------------------------------------------------------------------------- 1 | //mmu.h 2 | 3 | #ifndef MMU_H 4 | #define MMU_H 5 | 6 | #include 7 | 8 | extern bool mmu_enabled; 9 | extern bool mmuFSensorLoading; 10 | extern bool mmu_fil_loaded; 11 | extern bool mmu_idl_sens; 12 | extern uint32_t mmu_last_request; 13 | extern uint32_t mmu_last_finda_response; 14 | extern uint8_t mmu_filament_types[]; 15 | 16 | extern bool mmu_enabled; 17 | extern bool ir_sensor_detected; 18 | extern uint8_t mmu_extruder; 19 | extern uint8_t tmp_extruder; 20 | extern int8_t mmu_finda; 21 | extern int16_t mmu_version; 22 | extern int16_t mmu_buildnr; 23 | extern uint16_t mmu_power_failures; 24 | 25 | #define MMU_FILAMENT_UNKNOWN 255 26 | 27 | #define MMU_LOAD_FEEDRATE 19.02f //mm/s 28 | #define MMU_LOAD_TIME_MS 2000 //should be fine tuned to load time for shortest allowed PTFE tubing and maximum loading speed 29 | #define isEXTLoaded (READ(IR_SENSOR_PIN) == 0) 30 | 31 | enum class MmuCmd : uint_least8_t 32 | { 33 | None, 34 | T0, 35 | T1, 36 | T2, 37 | T3, 38 | T4, 39 | L0, 40 | L1, 41 | L2, 42 | L3, 43 | L4, 44 | C0, 45 | U0, 46 | E0, 47 | E1, 48 | E2, 49 | E3, 50 | E4, 51 | F0, 52 | F1, 53 | F2, 54 | F3, 55 | F4, 56 | K0, 57 | K1, 58 | K2, 59 | K3, 60 | K4, 61 | R0, 62 | S3, 63 | W0 //!< Wait and signal load error 64 | }; 65 | 66 | inline MmuCmd operator+ (MmuCmd cmd, uint8_t filament) 67 | { 68 | return static_cast(static_cast(cmd) + filament ); 69 | } 70 | 71 | inline uint8_t operator- (MmuCmd cmda, MmuCmd cmdb) 72 | { 73 | return (static_cast(cmda) - static_cast(cmdb)); 74 | } 75 | 76 | extern void mmu_init(void); 77 | extern void mmu_loop(void); 78 | extern void mmu_reset(void); 79 | extern bool check_for_ir_sensor(); 80 | extern void mmu_set_filament_type(uint8_t extruder, uint8_t filament); 81 | extern void mmu_command(MmuCmd cmd); 82 | extern bool mmu_get_response(uint8_t move); 83 | extern void manage_response(bool move_axes, bool turn_off_nozzle); //, uint8_t move = MMU_NO_MOVE); 84 | extern void mmu_load_to_nozzle(); 85 | extern void mmu_M600_load_filament(bool automatic, float nozzle_temp); 86 | extern void mmu_wait_for_heater_blocking(); 87 | extern void mmu_M600_wait_and_beep(); 88 | extern void extr_mov(float shift, float feed_rate); 89 | extern void extr_adj(uint8_t extruder); 90 | extern void extr_unload(); 91 | extern void load_all(); 92 | extern void extr_unload_(); 93 | 94 | extern void mmu_filament_ramming(); 95 | extern void mmu_load_step(bool synchronize = true); 96 | extern void mmu_continue_loading(void); 97 | #ifdef MMU_HAS_CUTTER 98 | extern void mmu_cut_filament(uint8_t filament_nr); 99 | #endif //MMU_HAS_CUTTER 100 | 101 | extern bool mmu_check_version(); 102 | extern void mmu_show_warning(); 103 | extern void lcd_mmu_load_to_nozzle(uint8_t filament_nr); 104 | extern void mmu_eject_filament(uint8_t filament, bool recover); 105 | 106 | #endif //MMU_H -------------------------------------------------------------------------------- /src/xflash_dump.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "xflash_dump.h" 7 | #ifdef XFLASH_DUMP 8 | #include "asm.h" 9 | #include "xflash.h" 10 | #include "Marlin.h" // for softReset 11 | 12 | bool xfdump_check_state(dump_crash_reason* reason) 13 | { 14 | uint32_t magic; 15 | 16 | XFLASH_SPI_ENTER(); 17 | xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.magic), 18 | (uint8_t*)&magic, sizeof(magic)); 19 | if (magic != DUMP_MAGIC) 20 | return false; 21 | 22 | if (reason) 23 | { 24 | xflash_rd_data(DUMP_OFFSET + offsetof(dump_t, header.crash_reason), 25 | (uint8_t*)reason, sizeof(*reason)); 26 | } 27 | return true; 28 | } 29 | 30 | 31 | void xfdump_reset() 32 | { 33 | XFLASH_SPI_ENTER(); 34 | xflash_enable_wr(); 35 | xflash_sector_erase(DUMP_OFFSET + offsetof(dump_t, header.magic)); 36 | xflash_wait_busy(); 37 | } 38 | 39 | 40 | static void xfdump_erase() 41 | { 42 | for(uint32_t addr = DUMP_OFFSET; 43 | addr < DUMP_OFFSET + DUMP_SIZE; 44 | addr += 4096) 45 | { 46 | xflash_enable_wr(); 47 | xflash_sector_erase(addr); 48 | xflash_wait_busy(); 49 | } 50 | } 51 | 52 | 53 | static void __attribute__((noinline)) xfdump_dump_core(dump_header_t& hdr, uint32_t addr, uint8_t* buf, uint16_t cnt) 54 | { 55 | XFLASH_SPI_ENTER(); 56 | 57 | // start by clearing all sectors (we need all of them in any case) 58 | xfdump_erase(); 59 | 60 | // sample SP/PC 61 | hdr.sp = SP; 62 | GETPC(&hdr.pc); 63 | 64 | // write header 65 | static_assert(sizeof(hdr) <= 256, "header is larger than a single page write"); 66 | xflash_enable_wr(); 67 | xflash_page_program(DUMP_OFFSET, (uint8_t*)&hdr, sizeof(hdr)); 68 | xflash_wait_busy(); 69 | 70 | // write data 71 | static_assert(sizeof(dump_t::data) <= RAMEND+1, "dump area size insufficient"); 72 | xflash_multipage_program(addr, buf, cnt); 73 | } 74 | 75 | 76 | void xfdump_dump() 77 | { 78 | dump_header_t buf; 79 | buf.magic = DUMP_MAGIC; 80 | buf.regs_present = false; 81 | buf.crash_reason = (uint8_t)dump_crash_reason::manual; 82 | 83 | // write sram only 84 | xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data.sram), 85 | (uint8_t*)RAMSTART, RAMSIZE); 86 | } 87 | 88 | 89 | void xfdump_full_dump_and_reset(dump_crash_reason reason) 90 | { 91 | dump_header_t buf; 92 | buf.magic = DUMP_MAGIC; 93 | buf.regs_present = true; 94 | buf.crash_reason = (uint8_t)reason; 95 | 96 | // disable interrupts for a cleaner register dump 97 | cli(); 98 | 99 | // ensure there's always enough time (with some margin) to dump 100 | // dump time on w25x20cl: ~150ms 101 | wdt_enable(WDTO_500MS); 102 | 103 | // write all addressable ranges (this will trash bidirectional registers) 104 | xfdump_dump_core(buf, DUMP_OFFSET + offsetof(dump_t, data), 0, RAMEND+1); 105 | 106 | // force a reset even sooner 107 | softReset(); 108 | } 109 | #endif 110 | -------------------------------------------------------------------------------- /src/SdFatUtil.cpp: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2008 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | #include "Marlin.h" 21 | 22 | #ifdef SDSUPPORT 23 | #include "SdFatUtil.h" 24 | 25 | //------------------------------------------------------------------------------ 26 | /** Amount of free RAM 27 | * \return The number of free bytes. 28 | */ 29 | #ifdef __arm__ 30 | extern "C" char* sbrk(int incr); 31 | int SdFatUtil::FreeRam() { 32 | char top; 33 | return &top - reinterpret_cast(sbrk(0)); 34 | } 35 | #else // __arm__ 36 | extern char *__brkval; 37 | extern char __bss_end; 38 | /** Amount of free RAM 39 | * \return The number of free bytes. 40 | */ 41 | int SdFatUtil::FreeRam() { 42 | char top; 43 | return __brkval ? &top - __brkval : &top - &__bss_end; 44 | } 45 | #endif // __arm 46 | 47 | void SdFatUtil::set_stack_guard() 48 | { 49 | uint32_t *stack_guard; 50 | 51 | stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN); 52 | *stack_guard = STACK_GUARD_TEST_VALUE; 53 | } 54 | 55 | bool SdFatUtil::test_stack_integrity() 56 | { 57 | uint32_t* stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN); 58 | return (*stack_guard == STACK_GUARD_TEST_VALUE); 59 | } 60 | 61 | //------------------------------------------------------------------------------ 62 | /** %Print a string in flash memory. 63 | * 64 | * \param[in] pr Print object for output. 65 | * \param[in] str Pointer to string stored in flash memory. 66 | */ 67 | void SdFatUtil::print_P( PGM_P str) { 68 | for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c); 69 | } 70 | //------------------------------------------------------------------------------ 71 | /** %Print a string in flash memory followed by a CR/LF. 72 | * 73 | * \param[in] pr Print object for output. 74 | * \param[in] str Pointer to string stored in flash memory. 75 | */ 76 | void SdFatUtil::println_P( PGM_P str) { 77 | print_P( str); 78 | MYSERIAL.println(); 79 | } 80 | //------------------------------------------------------------------------------ 81 | /** %Print a string in flash memory to Serial. 82 | * 83 | * \param[in] str Pointer to string stored in flash memory. 84 | */ 85 | void SdFatUtil::SerialPrint_P(PGM_P str) { 86 | print_P(str); 87 | } 88 | //------------------------------------------------------------------------------ 89 | /** %Print a string in flash memory to Serial followed by a CR/LF. 90 | * 91 | * \param[in] str Pointer to string stored in flash memory. 92 | */ 93 | void SdFatUtil::SerialPrintln_P(PGM_P str) { 94 | println_P( str); 95 | } 96 | #endif 97 | -------------------------------------------------------------------------------- /src/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef MACROS_H 2 | #define MACROS_H 3 | 4 | #include //for cli() and sei() 5 | 6 | #define FORCE_INLINE __attribute__((always_inline)) inline 7 | #define _UNUSED __attribute__((unused)) 8 | 9 | #ifndef CRITICAL_SECTION_START 10 | #define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli(); 11 | #define CRITICAL_SECTION_END SREG = _sreg; 12 | #endif //CRITICAL_SECTION_START 13 | 14 | // Macros to make a string from a macro 15 | #define STRINGIFY_(M) #M 16 | #define STRINGIFY(M) STRINGIFY_(M) 17 | 18 | // Macros for bit masks 19 | #undef _BV 20 | #define _BV(n) (1<<(n)) 21 | #define TEST(n,b) (!!((n)&_BV(b))) 22 | #define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0) 23 | 24 | #ifndef SBI 25 | #define SBI(A,B) (A |= (1 << (B))) 26 | #endif 27 | 28 | #ifndef CBI 29 | #define CBI(A,B) (A &= ~(1 << (B))) 30 | #endif 31 | 32 | #define TBI(N,B) (N ^= _BV(B)) 33 | 34 | 35 | // Macros to chain up to 12 conditions 36 | #define _DO_1(W,C,A) (_##W##_1(A)) 37 | #define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B)) 38 | #define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V)) 39 | #define _DO_4(W,C,A,V...) (_##W##_1(A) C _DO_3(W,C,V)) 40 | #define _DO_5(W,C,A,V...) (_##W##_1(A) C _DO_4(W,C,V)) 41 | #define _DO_6(W,C,A,V...) (_##W##_1(A) C _DO_5(W,C,V)) 42 | #define _DO_7(W,C,A,V...) (_##W##_1(A) C _DO_6(W,C,V)) 43 | #define _DO_8(W,C,A,V...) (_##W##_1(A) C _DO_7(W,C,V)) 44 | #define _DO_9(W,C,A,V...) (_##W##_1(A) C _DO_8(W,C,V)) 45 | #define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V)) 46 | #define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V)) 47 | #define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V)) 48 | #define __DO_N(W,C,N,V...) _DO_##N(W,C,V) 49 | #define _DO_N(W,C,N,V...) __DO_N(W,C,N,V) 50 | #define DO(W,C,V...) _DO_N(W,C,NUM_ARGS(V),V) 51 | 52 | // Macros to support option testing 53 | #define _CAT(a,V...) a##V 54 | #define CAT(a,V...) _CAT(a,V) 55 | 56 | #define _ISENA_ ~,1 57 | #define _ISENA_1 ~,1 58 | #define _ISENA_0x1 ~,1 59 | #define _ISENA_true ~,1 60 | #define _ISENA(V...) IS_PROBE(V) 61 | 62 | #define _ENA_1(O) _ISENA(CAT(_IS,CAT(ENA_, O))) 63 | #define _DIS_1(O) NOT(_ENA_1(O)) 64 | #define ENABLED(V...) DO(ENA,&&,V) 65 | #define DISABLED(V...) DO(DIS,&&,V) 66 | 67 | #define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1' 68 | #define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0' 69 | #define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1' 70 | #define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or '' 71 | #define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1' 72 | #define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1' 73 | #define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B. 74 | 75 | 76 | // Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments 77 | #define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT 78 | #define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) 79 | 80 | // 81 | // Primitives supporting precompiler REPEAT 82 | // 83 | #define FIRST(a,...) a 84 | #define SECOND(a,b,...) b 85 | #define THIRD(a,b,c,...) c 86 | 87 | #define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0 88 | #define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'. 89 | 90 | #endif //MACROS_H 91 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H 2 | #define _CONFIG_H 3 | 4 | 5 | #include "Configuration_prusa.h" 6 | #include "pins.h" 7 | 8 | #if (defined(VOLT_IR_PIN) && defined(IR_SENSOR)) 9 | # define IR_SENSOR_ANALOG 10 | #endif 11 | 12 | //ADC configuration 13 | #ifndef IR_SENSOR_ANALOG 14 | #define ADC_CHAN_MSK 0b0000001001011111 //used AD channels bit mask (0,1,2,3,4,6,9) 15 | #define ADC_DIDR_MSK 0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input) 16 | #define ADC_CHAN_CNT 7 //number of used channels) 17 | #else //!IR_SENSOR_ANALOG 18 | #define ADC_CHAN_MSK 0b0000001101011111 //used AD channels bit mask (0,1,2,3,4,6,8,9) 19 | #define ADC_DIDR_MSK 0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input) 20 | #define ADC_CHAN_CNT 8 //number of used channels) 21 | #endif //!IR_SENSOR_ANALOG 22 | #define ADC_OVRSAMPL 16 //oversampling multiplier 23 | #define ADC_CALLBACK adc_ready //callback function () 24 | 25 | //SWI2C configuration 26 | //#define SWI2C_SDA 20 //SDA on P3 27 | //#define SWI2C_SCL 21 //SCL on P3 28 | #define SWI2C_A8 29 | #define SWI2C_DEL 20 //2us clock delay 30 | #define SWI2C_TMO 2048 //2048 cycles timeout 31 | 32 | //PAT9125 configuration 33 | //#define PAT9125_SWSPI // software SPI mode (incomplete) 34 | #ifdef SWI2C_SCL 35 | #define PAT9125_SWI2C // software I2C mode 36 | #else 37 | #define PAT9125_I2C // hardware I2C mode 38 | #endif 39 | 40 | #define PAT9125_I2C_ADDR 0x75 //ID=LO 41 | //#define PAT9125_I2C_ADDR 0x79 //ID=HI 42 | //#define PAT9125_I2C_ADDR 0x73 //ID=NC 43 | #define PAT9125_XRES 0 44 | #define PAT9125_YRES 240 // maximum resolution (5*X cpi) 45 | #define PAT9124_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm 46 | 47 | //SM4 configuration 48 | #define SM4_DEFDELAY 500 //default step delay [us] 49 | 50 | //TMC2130 - Trinamic stepper driver 51 | //pinout - hardcoded 52 | //spi: 53 | #define TMC2130_SPI_RATE 0 // fosc/4 = 4MHz 54 | #define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0) 55 | #define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE) 56 | 57 | //LANG - Multi-language support 58 | #define LANG_MODE 0 // primary language only 59 | //#define LANG_MODE 1 // sec. language support 60 | 61 | #define LANG_SIZE_RESERVED 0x3000 // reserved space for secondary language (12288 bytes) 62 | 63 | //Community language support 64 | #define COMMUNITY_LANG_NL // Community Dutch language 65 | //#define COMMUNITY_LANG_QR // Community new language //..use this as a template and replace 'QR' 66 | 67 | #if defined(COMMUNITY_LANG_NL) //|| defined(COMMUNITY_LANG_QR) //..use last part as a template and replace 'QR' 68 | #define COMMUNITY_LANG_SUPPORT 69 | #endif 70 | 71 | // Sanity checks for correct configuration of XFLASH_DUMP options 72 | #if defined(XFLASH_DUMP) && !defined(XFLASH) 73 | #error "XFLASH_DUMP requires XFLASH support" 74 | #endif 75 | #if (defined(MENU_DUMP) || defined(EMERGENCY_DUMP)) && !defined(XFLASH_DUMP) 76 | #error "MENU_DUMP and EMERGENCY_DUMP require XFLASH_DUMP" 77 | #endif 78 | 79 | // Support for serial dumps is mutually exclusive with XFLASH_DUMP features 80 | #if defined(EMERGENCY_DUMP) && defined(EMERGENCY_SERIAL_DUMP) 81 | #error "EMERGENCY_DUMP and EMERGENCY_SERIAL_DUMP are mutually exclusive" 82 | #endif 83 | #if defined(MENU_DUMP) && defined(MENU_SERIAL_DUMP) 84 | #error "MENU_DUMP and MENU_SERIAL_DUMP are mutually exclusive" 85 | #endif 86 | 87 | // Reduce internal duplication 88 | #if defined(EMERGENCY_DUMP) || defined(EMERGENCY_SERIAL_DUMP) 89 | #define EMERGENCY_HANDLERS 90 | #endif 91 | 92 | #endif //_CONFIG_H 93 | -------------------------------------------------------------------------------- /src/twi.c: -------------------------------------------------------------------------------- 1 | /* 2 | twi.c - Stripped-down TWI/I2C library 3 | Copyright (c) 2006 Nicholas Zambetti. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | 19 | Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts 20 | */ 21 | 22 | 23 | #include 24 | #include "config.h" 25 | #include "fastio.h" 26 | #include "twi.h" 27 | 28 | 29 | void twi_init(void) 30 | { 31 | // activate internal pullups for twi. 32 | WRITE(SDA_PIN, 1); 33 | WRITE(SCL_PIN, 1); 34 | 35 | // initialize twi prescaler and bit rate 36 | TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); 37 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; 38 | 39 | /* twi bit rate formula from atmega128 manual pg 204 40 | SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) 41 | note: TWBR should be 10 or higher for master mode 42 | It is 72 for a 16mhz Wiring board with 100kHz TWI */ 43 | } 44 | 45 | void twi_disable(void) 46 | { 47 | // deactivate internal pullups for twi. 48 | WRITE(SDA_PIN, 0); 49 | WRITE(SCL_PIN, 0); 50 | } 51 | 52 | 53 | static void twi_stop() 54 | { 55 | TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTO); 56 | } 57 | 58 | 59 | static uint8_t twi_wait(uint8_t status) 60 | { 61 | while(!(TWCR & _BV(TWINT))); 62 | if(TW_STATUS != status) 63 | { 64 | twi_stop(); 65 | return 1; 66 | } 67 | return 0; 68 | } 69 | 70 | 71 | static uint8_t twi_start(uint8_t address, uint8_t reg) 72 | { 73 | // send start condition 74 | TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); 75 | if(twi_wait(TW_START)) 76 | return 1; 77 | 78 | // send address 79 | TWDR = TW_WRITE | (address << 1); 80 | TWCR = _BV(TWEN) | _BV(TWINT); 81 | if(twi_wait(TW_MT_SLA_ACK)) 82 | return 2; 83 | 84 | // send register 85 | TWDR = reg; 86 | TWCR = _BV(TWEN) | _BV(TWINT); 87 | if(twi_wait(TW_MT_DATA_ACK)) 88 | return 3; 89 | 90 | return 0; 91 | } 92 | 93 | 94 | uint8_t twi_r8(uint8_t address, uint8_t reg, uint8_t* data) 95 | { 96 | if(twi_start(address, reg)) 97 | return 1; 98 | 99 | // repeat start 100 | TWCR = _BV(TWEN) | _BV(TWINT) | _BV(TWSTA); 101 | if(twi_wait(TW_REP_START)) 102 | return 2; 103 | 104 | // start receiving 105 | TWDR = TW_READ | (address << 1); 106 | TWCR = _BV(TWEN) | _BV(TWINT); 107 | if(twi_wait(TW_MR_SLA_ACK)) 108 | return 3; 109 | 110 | // receive data 111 | TWCR = _BV(TWEN) | _BV(TWINT); 112 | if(twi_wait(TW_MR_DATA_NACK)) 113 | return 4; 114 | 115 | *data = TWDR; 116 | 117 | // send stop 118 | twi_stop(); 119 | return 0; 120 | } 121 | 122 | 123 | uint8_t twi_w8(uint8_t address, uint8_t reg, uint8_t data) 124 | { 125 | if(twi_start(address, reg)) 126 | return 1; 127 | 128 | // send data 129 | TWDR = data; 130 | TWCR = _BV(TWEN) | _BV(TWINT); 131 | if(twi_wait(TW_MT_DATA_ACK)) 132 | return 2; 133 | 134 | // send stop 135 | twi_stop(); 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /src/tone04.c: -------------------------------------------------------------------------------- 1 | //tone04.c 2 | // use atmega timer4 as main tone timer instead of timer2 3 | // timer2 is used for System timer. 4 | 5 | #include "system_timer.h" 6 | #include "Configuration_prusa.h" 7 | 8 | #ifdef SYSTEM_TIMER_2 9 | 10 | #include "pins.h" 11 | #include "fastio.h" 12 | #include "macros.h" 13 | 14 | void timer4_init(void) 15 | { 16 | CRITICAL_SECTION_START; 17 | 18 | SET_OUTPUT(BEEPER); 19 | WRITE(BEEPER, LOW); 20 | 21 | SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN); 22 | 23 | // Set timer mode 9 (PWM,Phase and Frequency Correct) 24 | // Prescaler is CLK/1024 25 | // Output compare is disabled on all timer pins 26 | // Input capture is disabled 27 | // All interrupts are disabled 28 | TCCR4A = (1 << WGM40); 29 | TCCR4B = (1 << WGM43) | (1 << CS42) | (1 << CS40); 30 | OCR4A = 255; 31 | OCR4B = 255; 32 | OCR4C = 255; 33 | TIMSK4 = 0; 34 | 35 | CRITICAL_SECTION_END; 36 | } 37 | 38 | #ifdef EXTRUDER_0_AUTO_FAN_PIN 39 | void timer4_set_fan0(uint8_t duty) 40 | { 41 | if (duty == 0 || duty == 255) 42 | { 43 | // We use digital logic if the duty cycle is 0% or 100% 44 | TCCR4A &= ~(1 << COM4C1); 45 | OCR4C = 0; 46 | WRITE(EXTRUDER_0_AUTO_FAN_PIN, duty); 47 | } 48 | else 49 | { 50 | // Use the timer for fan speed. Enable the timer compare output and set the duty cycle. 51 | // This function also handles the impossible scenario of a fan speed change during a Tone. 52 | // Better be safe than sorry. 53 | CRITICAL_SECTION_START; 54 | // Enable the PWM output on the fan pin. 55 | TCCR4A |= (1 << COM4C1); 56 | OCR4C = (((uint32_t)duty) * ((uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255))) / ((uint32_t)255); 57 | CRITICAL_SECTION_END; 58 | } 59 | } 60 | #endif //EXTRUDER_0_AUTO_FAN_PIN 61 | 62 | // Because of the timer mode change, we need two interrupts. We could also try to assume that the frequency is x2 63 | // and use a TOGGLE(), but this seems to work well enough so I left it as it is now. 64 | ISR(TIMER4_COMPA_vect) 65 | { 66 | WRITE(BEEPER, 1); 67 | } 68 | 69 | ISR(TIMER4_OVF_vect) 70 | { 71 | WRITE(BEEPER, 0); 72 | } 73 | 74 | void tone4(_UNUSED uint8_t _pin, uint16_t frequency) 75 | { 76 | //this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only 77 | uint8_t prescalarbits = 0b001; 78 | uint32_t ocr = F_CPU / frequency / 2 - 1; 79 | 80 | if (ocr > 0xffff) 81 | { 82 | ocr = F_CPU / frequency / 2 / 64 - 1; 83 | prescalarbits = 0b011; 84 | } 85 | 86 | CRITICAL_SECTION_START; 87 | // Set calcualted prescaler 88 | TCCR4B = (TCCR4B & 0b11111000) | prescalarbits; 89 | #ifdef EXTRUDER_0_AUTO_FAN_PIN 90 | // Scale the fan PWM duty cycle so that it remains constant, but at the tone frequency 91 | OCR4C = (((uint32_t)OCR4C) * ocr) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); 92 | #endif //EXTRUDER_0_AUTO_FAN_PIN 93 | // Set calcualted ocr 94 | OCR4A = ocr; 95 | // Enable Output compare A interrupt and timer overflow interrupt 96 | TIMSK4 |= (1 << OCIE4A) | (1 << TOIE4); 97 | CRITICAL_SECTION_END; 98 | } 99 | 100 | void noTone4(_UNUSED uint8_t _pin) 101 | { 102 | CRITICAL_SECTION_START; 103 | // Revert prescaler to CLK/1024 104 | TCCR4B = (TCCR4B & 0b11111000) | (1 << CS42) | (1 << CS40); 105 | #ifdef EXTRUDER_0_AUTO_FAN_PIN 106 | // Scale the fan OCR back to the original value. 107 | OCR4C = (((uint32_t)OCR4C) * (uint32_t)255) / (uint32_t)((TIMSK4 & (1 << OCIE4A))?OCR4A:255); 108 | #endif //EXTRUDER_0_AUTO_FAN_PIN 109 | OCR4A = 255; 110 | // Disable Output compare A interrupt and timer overflow interrupt 111 | TIMSK4 &= ~((1 << OCIE4A) | (1 << TOIE4)); 112 | CRITICAL_SECTION_END; 113 | // Turn beeper off if it was on when noTone was called 114 | WRITE(BEEPER, 0); 115 | } 116 | 117 | 118 | #endif //SYSTEM_TIMER_2 119 | -------------------------------------------------------------------------------- /src/stepper.h: -------------------------------------------------------------------------------- 1 | /* 2 | stepper.h - stepper motor driver: executes motion plans of planner.c using the stepper motors 3 | Part of Grbl 4 | 5 | Copyright (c) 2009-2011 Simen Svale Skogsrud 6 | 7 | Grbl is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | Grbl is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with Grbl. If not, see . 19 | */ 20 | 21 | #ifndef stepper_h 22 | #define stepper_h 23 | 24 | #include "planner.h" 25 | 26 | #define ENABLE_STEPPER_DRIVER_INTERRUPT() TIMSK1 |= (1< -1 83 | void digitalPotWrite(int address, int value); 84 | #endif //defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1 85 | void microstep_ms(uint8_t driver, int8_t ms1, int8_t ms2); 86 | void microstep_mode(uint8_t driver, uint8_t stepping); 87 | void st_current_init(); 88 | void st_current_set(uint8_t driver, int current); 89 | void microstep_init(); 90 | void microstep_readings(); 91 | 92 | #ifdef BABYSTEPPING 93 | void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention 94 | #endif 95 | 96 | #if defined(FILAMENT_SENSOR) && defined(PAT9125) 97 | // reset the internal filament sensor state 98 | void st_reset_fsensor(); 99 | #endif 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /src/uart2.cpp: -------------------------------------------------------------------------------- 1 | //uart2.cpp 2 | 3 | /** 4 | * Robert McKenzie 7 byte payload comms protol with 0x7F as start byte 5 | * and 0xF7 as finish bytes. 6 | * ACK is with 0x06 7 | * NACK is 0x15 8 | */ 9 | 10 | #include "uart2.h" 11 | #include "system_timer.h" 12 | 13 | volatile unsigned char readRxBuffer, rxData1 = 0, rxData2 = 0, rxData3 = 0, 14 | rxData4 = 0, rxData5 = 0, rxFINDA = 0; 15 | volatile bool confirmedPayload = false, confirmedFINDA = false, atomic_MMU_IRSENS = false; 16 | volatile long rxTimeout = _micros(); 17 | enum class rx 18 | { 19 | Idle, 20 | Data1, 21 | Data2, 22 | Data3, 23 | Data4, 24 | Data5, 25 | End, 26 | FINDA, 27 | EndFINDA 28 | }; 29 | rx rxCount = rx::Idle; 30 | 31 | inline rx& operator++(rx& byte, int) 32 | { 33 | const int i = static_cast(byte) + 1; 34 | byte = static_cast((i) % 9); 35 | return byte; 36 | } 37 | 38 | void uart2_init(void) 39 | { 40 | UCSR2A = (0 << U2X2); // baudrate multiplier 41 | UCSR2B = (1 << RXEN2) | (1 << TXEN2) | (0 << UCSZ22); // enable receiver and transmitter 42 | UCSR2C = (0 << UMSEL21) | (0 << UMSEL20) | (0 << UPM21) | 43 | (0 << UPM20) | (1 << USBS2) |(1 << UCSZ21) | (1 << UCSZ20); // Use 8-bit character sizes 44 | UBRR2H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register 45 | UBRR2L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register 46 | UCSR2B |= (1 << RXCIE2); // enable rx interrupt 47 | } 48 | 49 | ISR(USART2_RX_vect) 50 | { 51 | readRxBuffer = UDR2; 52 | if (rxTimeout + 1855 < _micros()) rxCount = rx::Idle; 53 | switch (rxCount) { 54 | case rx::Idle: 55 | if (readRxBuffer == 0x7F) { rxCount++; rxTimeout = _micros(); } 56 | if (readRxBuffer == 0x06) { rxCount = rx::FINDA; rxTimeout = _micros(); } 57 | break; 58 | case rx::Data1: 59 | rxData1 = readRxBuffer; 60 | rxCount++; 61 | break; 62 | case rx::Data2: 63 | rxData2 = readRxBuffer; 64 | rxCount++; 65 | break; 66 | case rx::Data3: 67 | rxData3 = readRxBuffer; 68 | rxCount++; 69 | break; 70 | case rx::Data4: 71 | rxData4 = readRxBuffer; 72 | rxCount++; 73 | break; 74 | case rx::Data5: 75 | rxData5 = readRxBuffer; 76 | rxCount++; 77 | break; 78 | case rx::End: 79 | if (readRxBuffer == 0xF7) { 80 | if (rxData1 == 'I' && rxData2 == 'R' && rxData3 == 'S' && rxData4 == 'E' && rxData5 == 'N') atomic_MMU_IRSENS = true; 81 | else confirmedPayload = true; 82 | } 83 | rxCount = rx::Idle; 84 | break; 85 | case rx::FINDA: 86 | rxFINDA = readRxBuffer; 87 | rxCount++; 88 | break; 89 | case rx::EndFINDA: 90 | if (readRxBuffer == 0xF7) confirmedFINDA = true; 91 | rxCount = rx::Idle; 92 | break; 93 | } 94 | } 95 | 96 | void uart2_txPayload(unsigned char payload[]) 97 | { 98 | #ifdef MMU_DEBUG 99 | printf_P(PSTR("\nUART2 TX 0x%2X %2X %2X\n"), payload[0], payload[1], payload[2]); 100 | #endif //MMU_DEBUG 101 | mmu_last_request = _millis(); 102 | loop_until_bit_is_set(UCSR2A, UDRE2); // Do nothing until UDR is ready for more data to be written to it 103 | UDR2 = 0x7F; 104 | for (uint8_t i = 0; i < 5; i++) { 105 | loop_until_bit_is_set(UCSR2A, UDRE2); // Do nothing until UDR is ready for more data to be written to it 106 | UDR2 = (0xFF & (int)payload[i]); 107 | } 108 | loop_until_bit_is_set(UCSR2A, UDRE2); // Do nothing until UDR is ready for more data to be written to it 109 | UDR2 = 0xF7; 110 | } 111 | -------------------------------------------------------------------------------- /src/cmdqueue.h: -------------------------------------------------------------------------------- 1 | #ifndef CMDQUEUE_H 2 | #define CMDQUEUE_H 3 | 4 | #include "Marlin.h" 5 | #include "language.h" 6 | 7 | 8 | // String circular buffer. Commands may be pushed to the buffer from both sides: 9 | // Chained commands will be pushed to the front, interactive (from LCD menu) 10 | // and printing commands (from serial line or from SD card) are pushed to the tail. 11 | // First character of each entry indicates the type of the entry: 12 | #define CMDBUFFER_CURRENT_TYPE_UNKNOWN 0 13 | // Command in cmdbuffer was sent over USB. 14 | #define CMDBUFFER_CURRENT_TYPE_USB 1 15 | // Command in cmdbuffer was read from SDCARD. 16 | #define CMDBUFFER_CURRENT_TYPE_SDCARD 2 17 | // Command in cmdbuffer was generated by the UI. 18 | #define CMDBUFFER_CURRENT_TYPE_UI 3 19 | // Command in cmdbuffer was generated by another G-code. 20 | #define CMDBUFFER_CURRENT_TYPE_CHAINED 4 21 | // Command has been processed and its SD card length has been possibly pushed 22 | // to the planner queue, but not yet removed from the cmdqueue. 23 | // This is a temporary state to reduce stepper interrupt locking time. 24 | #define CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED 5 25 | //Command in cmdbuffer was sent over USB and contains line number 26 | #define CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR 6 27 | 28 | // How much space to reserve for the chained commands 29 | // of type CMDBUFFER_CURRENT_TYPE_CHAINED, 30 | // which are pushed to the front of the queue? 31 | // Maximum 5 commands of max length 20 + null terminator. 32 | #define CMDBUFFER_RESERVE_FRONT (5*21) 33 | 34 | extern char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT]; 35 | extern size_t bufindr; 36 | extern int buflen; 37 | extern bool cmdbuffer_front_already_processed; 38 | extern bool cmdqueue_serial_disabled; 39 | 40 | // Type of a command, which is to be executed right now. 41 | #define CMDBUFFER_CURRENT_TYPE (cmdbuffer[bufindr]) 42 | // String of a command, which is to be executed right now. 43 | #define CMDBUFFER_CURRENT_STRING (cmdbuffer+bufindr+CMDHDRSIZE) 44 | 45 | // Enable debugging of the command buffer. 46 | // Debugging information will be sent to serial line. 47 | //#define CMDBUFFER_DEBUG 48 | 49 | extern uint32_t sdpos_atomic; 50 | 51 | extern int serial_count; 52 | extern boolean comment_mode; 53 | extern char *strchr_pointer; 54 | 55 | extern unsigned long TimeSent; 56 | extern unsigned long TimeNow; 57 | 58 | extern long gcode_N; 59 | extern long gcode_LastN; 60 | extern long Stopped_gcode_LastN; 61 | 62 | extern bool cmdqueue_pop_front(); 63 | extern void cmdqueue_reset(); 64 | #ifdef CMDBUFFER_DEBUG 65 | extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p); 66 | extern void cmdqueue_dump_to_serial(); 67 | #endif /* CMDBUFFER_DEBUG */ 68 | extern bool cmd_buffer_empty(); 69 | extern void enquecommand(const char *cmd, bool from_progmem = false); 70 | extern void enquecommand_front(const char *cmd, bool from_progmem = false); 71 | extern void repeatcommand_front(); 72 | extern void get_command(); 73 | extern uint16_t cmdqueue_calc_sd_length(); 74 | 75 | // Return True if a character was found 76 | static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; } 77 | static inline bool code_seen_P(const char *code_PROGMEM) { return (strchr_pointer = strstr_P(CMDBUFFER_CURRENT_STRING, code_PROGMEM)) != NULL; } 78 | static inline float code_value() { return strtod(strchr_pointer+1, NULL);} 79 | static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); } 80 | static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); }; 81 | static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); }; 82 | 83 | static inline float code_value_float() 84 | { 85 | char* e = strchr(strchr_pointer, 'E'); 86 | if (!e) return strtod(strchr_pointer + 1, NULL); 87 | *e = 0; 88 | float ret = strtod(strchr_pointer + 1, NULL); 89 | *e = 'E'; 90 | return ret; 91 | } 92 | 93 | 94 | #endif //CMDQUEUE_H 95 | -------------------------------------------------------------------------------- /src/speed_lookuptable.h: -------------------------------------------------------------------------------- 1 | #ifndef SPEED_LOOKUPTABLE_H 2 | #define SPEED_LOOKUPTABLE_H 3 | 4 | #include "Marlin.h" 5 | 6 | extern const uint16_t speed_lookuptable_fast[256][2] PROGMEM; 7 | extern const uint16_t speed_lookuptable_slow[256][2] PROGMEM; 8 | 9 | #ifndef _NO_ASM 10 | 11 | // intRes = intIn1 * intIn2 >> 16 12 | // uses: 13 | // r26 to store 0 14 | // r27 to store the byte 1 of the 24 bit result 15 | #define MultiU16X8toH16(intRes, charIn1, intIn2) \ 16 | asm volatile ( \ 17 | "clr r26 \n\t" \ 18 | "mul %A1, %B2 \n\t" \ 19 | "movw %A0, r0 \n\t" \ 20 | "mul %A1, %A2 \n\t" \ 21 | "add %A0, r1 \n\t" \ 22 | "adc %B0, r26 \n\t" \ 23 | "lsr r0 \n\t" \ 24 | "adc %A0, r26 \n\t" \ 25 | "adc %B0, r26 \n\t" \ 26 | "clr r1 \n\t" \ 27 | : \ 28 | "=&r" (intRes) \ 29 | : \ 30 | "d" (charIn1), \ 31 | "d" (intIn2) \ 32 | : \ 33 | "r26" \ 34 | ) 35 | 36 | // intRes = longIn1 * longIn2 >> 24 37 | // uses: 38 | // r26 to store 0 39 | // r27 to store the byte 1 of the 48bit result 40 | #define MultiU24X24toH16(intRes, longIn1, longIn2) \ 41 | asm volatile ( \ 42 | "clr r26 \n\t" \ 43 | "mul %A1, %B2 \n\t" \ 44 | "mov r27, r1 \n\t" \ 45 | "mul %B1, %C2 \n\t" \ 46 | "movw %A0, r0 \n\t" \ 47 | "mul %C1, %C2 \n\t" \ 48 | "add %B0, r0 \n\t" \ 49 | "mul %C1, %B2 \n\t" \ 50 | "add %A0, r0 \n\t" \ 51 | "adc %B0, r1 \n\t" \ 52 | "mul %A1, %C2 \n\t" \ 53 | "add r27, r0 \n\t" \ 54 | "adc %A0, r1 \n\t" \ 55 | "adc %B0, r26 \n\t" \ 56 | "mul %B1, %B2 \n\t" \ 57 | "add r27, r0 \n\t" \ 58 | "adc %A0, r1 \n\t" \ 59 | "adc %B0, r26 \n\t" \ 60 | "mul %C1, %A2 \n\t" \ 61 | "add r27, r0 \n\t" \ 62 | "adc %A0, r1 \n\t" \ 63 | "adc %B0, r26 \n\t" \ 64 | "mul %B1, %A2 \n\t" \ 65 | "add r27, r1 \n\t" \ 66 | "adc %A0, r26 \n\t" \ 67 | "adc %B0, r26 \n\t" \ 68 | "lsr r27 \n\t" \ 69 | "adc %A0, r26 \n\t" \ 70 | "adc %B0, r26 \n\t" \ 71 | "clr r1 \n\t" \ 72 | : \ 73 | "=&r" (intRes) \ 74 | : \ 75 | "d" (longIn1), \ 76 | "d" (longIn2) \ 77 | : \ 78 | "r26" , "r27" \ 79 | ) 80 | 81 | #else //_NO_ASM 82 | 83 | static inline void MultiU16X8toH16(uint16_t& intRes, uint8_t& charIn1, uint16_t& intIn2) 84 | { 85 | intRes = ((uint32_t)charIn1 * (uint32_t)intIn2) >> 16; 86 | } 87 | 88 | static inline void MultiU24X24toH16(uint16_t& intRes, uint32_t& longIn1, uint32_t& longIn2) 89 | { 90 | intRes = ((uint64_t)longIn1 * (uint64_t)longIn2) >> 24; 91 | } 92 | 93 | #endif //_NO_ASM 94 | 95 | 96 | FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) { 97 | uint16_t timer; 98 | if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; 99 | 100 | if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times 101 | step_rate = (step_rate >> 2)&0x3fff; 102 | step_loops = 4; 103 | } 104 | else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times 105 | step_rate = (step_rate >> 1)&0x7fff; 106 | step_loops = 2; 107 | } 108 | else { 109 | step_loops = 1; 110 | } 111 | 112 | if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); 113 | step_rate -= (F_CPU/500000); // Correct for minimal speed 114 | if(step_rate >= (8*256)){ // higher step rate 115 | unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; 116 | unsigned char tmp_step_rate = (step_rate & 0x00ff); 117 | uint16_t gain = (uint16_t)pgm_read_word_near(table_address+2); 118 | MultiU16X8toH16(timer, tmp_step_rate, gain); 119 | timer = (unsigned short)pgm_read_word_near(table_address) - timer; 120 | } 121 | else { // lower step rates 122 | unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; 123 | table_address += ((step_rate)>>1) & 0xfffc; 124 | timer = (unsigned short)pgm_read_word_near(table_address); 125 | timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); 126 | } 127 | if(timer < 100) { timer = 100; }//(20kHz this should never happen)////MSG_STEPPER_TOO_HIGH c=0 r=0 128 | return timer; 129 | } 130 | 131 | #endif 132 | -------------------------------------------------------------------------------- /src/fsensor.h: -------------------------------------------------------------------------------- 1 | //! @file 2 | #ifndef FSENSOR_H 3 | #define FSENSOR_H 4 | 5 | #include 6 | #include "config.h" 7 | 8 | 9 | // enable/disable flag 10 | extern bool fsensor_enabled; 11 | // not responding flag 12 | extern bool fsensor_not_responding; 13 | #ifdef PAT9125 14 | // optical checking "chunk lenght" (already in steps) 15 | extern int16_t fsensor_chunk_len; 16 | // count of soft failures 17 | extern uint8_t fsensor_softfail; 18 | #endif 19 | 20 | //! @name save restore printing 21 | //! @{ 22 | extern void fsensor_stop_and_save_print(void); 23 | //! restore print - restore position and heatup to original temperature 24 | extern void fsensor_restore_print_and_continue(void); 25 | //! split the current gcode stream to insert new instructions 26 | extern void fsensor_checkpoint_print(void); 27 | //! @} 28 | 29 | //! initialize 30 | extern void fsensor_init(void); 31 | 32 | #ifdef PAT9125 33 | //! update axis resolution 34 | extern void fsensor_set_axis_steps_per_unit(float u); 35 | #endif 36 | 37 | //! @name enable/disable 38 | //! @{ 39 | extern bool fsensor_enable(bool bUpdateEEPROM=true); 40 | extern void fsensor_disable(bool bUpdateEEPROM=true); 41 | //! @} 42 | 43 | //autoload feature enabled 44 | extern bool fsensor_autoload_enabled; 45 | extern void fsensor_autoload_set(bool State); 46 | 47 | extern void fsensor_update(void); 48 | #ifdef PAT9125 49 | //! setup pin-change interrupt 50 | extern void fsensor_setup_interrupt(void); 51 | 52 | //! @name autoload support 53 | //! @{ 54 | 55 | extern void fsensor_autoload_check_start(void); 56 | extern void fsensor_autoload_check_stop(void); 57 | #endif //PAT9125 58 | extern bool fsensor_check_autoload(void); 59 | //! @} 60 | 61 | #ifdef PAT9125 62 | //! @name optical quality measurement support 63 | //! @{ 64 | extern bool fsensor_oq_meassure_enabled; 65 | extern void fsensor_oq_meassure_set(bool State); 66 | extern void fsensor_oq_meassure_start(uint8_t skip); 67 | extern void fsensor_oq_meassure_stop(void); 68 | extern bool fsensor_oq_result(void); 69 | //! @} 70 | 71 | //! @name callbacks from stepper 72 | //! @{ 73 | extern void fsensor_st_block_chunk(int cnt); 74 | 75 | // debugging 76 | extern uint8_t fsensor_log; 77 | 78 | // There's really nothing to do in block_begin: the stepper ISR likely has 79 | // called us already at the end of the last block, making this integration 80 | // redundant. LA1.5 might not always do that during a coasting move, so attempt 81 | // to drain fsensor_st_cnt anyway at the beginning of the new block. 82 | #define fsensor_st_block_begin(rev) fsensor_st_block_chunk(0) 83 | //! @} 84 | #endif //PAT9125 85 | 86 | #define VOLT_DIV_REF 5 87 | 88 | #ifdef IR_SENSOR_ANALOG 89 | #define IR_SENSOR_STEADY 10 // [ms] 90 | 91 | enum class ClFsensorPCB:uint_least8_t 92 | { 93 | _Old=0, 94 | _Rev04=1, 95 | _Undef=EEPROM_EMPTY_VALUE 96 | }; 97 | 98 | enum class ClFsensorActionNA:uint_least8_t 99 | { 100 | _Continue=0, 101 | _Pause=1, 102 | _Undef=EEPROM_EMPTY_VALUE 103 | }; 104 | 105 | extern ClFsensorPCB oFsensorPCB; 106 | extern ClFsensorActionNA oFsensorActionNA; 107 | extern const char* FsensorIRVersionText(); 108 | 109 | extern bool fsensor_IR_check(); 110 | constexpr uint16_t Voltage2Raw(float V){ 111 | return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F; 112 | } 113 | constexpr float Raw2Voltage(uint16_t raw){ 114 | return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) ); 115 | } 116 | constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982 117 | constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910 118 | constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821 119 | constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059 120 | constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368 121 | 122 | #endif //IR_SENSOR_ANALOG 123 | 124 | #endif //FSENSOR_H 125 | -------------------------------------------------------------------------------- /src/timer02.c: -------------------------------------------------------------------------------- 1 | //timer02.c 2 | // use atmega timer2 as main system timer instead of timer0 3 | // timer0 is used for fast pwm (OC0B output) 4 | // original OVF handler is disabled 5 | 6 | #include "system_timer.h" 7 | 8 | #ifdef SYSTEM_TIMER_2 9 | 10 | #include 11 | #include 12 | #include "macros.h" 13 | 14 | void timer0_init(void) 15 | { 16 | CRITICAL_SECTION_START; 17 | 18 | TCNT0 = 0; 19 | // Fast PWM duty (0-255). 20 | // Due to invert mode (following rows) the duty is set to 255, which means zero all the time (bed not heating) 21 | OCR0B = 255; 22 | // Set fast PWM mode and inverting mode. 23 | TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B1) | (1 << COM0B0); 24 | TCCR0B = (1 << CS01); // CLK/8 prescaling 25 | TIMSK0 |= (1 << TOIE0); // enable timer overflow interrupt 26 | 27 | CRITICAL_SECTION_END; 28 | } 29 | 30 | void timer2_init(void) 31 | { 32 | CRITICAL_SECTION_START; 33 | 34 | // Everything, that used to be on timer0 was moved to timer2 (delay, beeping, millis etc.) 35 | //setup timer2 36 | TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00 37 | TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011 38 | //mask timer2 interrupts - enable OVF, disable others 39 | TIMSK2 |= (1<> 3) 64 | #define FRACT_MAX (1000 >> 3) 65 | 66 | volatile unsigned long timer2_overflow_count; 67 | volatile unsigned long timer2_millis; 68 | unsigned char timer2_fract = 0; 69 | 70 | ISR(TIMER2_OVF_vect) 71 | { 72 | // copy these to local variables so they can be stored in registers 73 | // (volatile variables must be read from memory on every access) 74 | unsigned long m = timer2_millis; 75 | unsigned char f = timer2_fract; 76 | m += MILLIS_INC; 77 | f += FRACT_INC; 78 | if (f >= FRACT_MAX) 79 | { 80 | f -= FRACT_MAX; 81 | m += 1; 82 | } 83 | timer2_fract = f; 84 | timer2_millis = m; 85 | timer2_overflow_count++; 86 | } 87 | 88 | unsigned long millis2(void) 89 | { 90 | unsigned long m; 91 | uint8_t oldSREG = SREG; 92 | 93 | // disable interrupts while we read timer0_millis or we might get an 94 | // inconsistent value (e.g. in the middle of a write to timer0_millis) 95 | cli(); 96 | m = timer2_millis; 97 | SREG = oldSREG; 98 | 99 | return m; 100 | } 101 | 102 | unsigned long micros2(void) 103 | { 104 | unsigned long m; 105 | uint8_t oldSREG = SREG, t; 106 | cli(); 107 | m = timer2_overflow_count; 108 | #if defined(TCNT2) 109 | t = TCNT2; 110 | #elif defined(TCNT2L) 111 | t = TCNT2L; 112 | #else 113 | #error TIMER 2 not defined 114 | #endif 115 | #ifdef TIFR2 116 | if ((TIFR2 & _BV(TOV2)) && (t < 255)) 117 | m++; 118 | #else 119 | if ((TIFR & _BV(TOV2)) && (t < 255)) 120 | m++; 121 | #endif 122 | SREG = oldSREG; 123 | return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); 124 | } 125 | 126 | void delay2(unsigned long ms) 127 | { 128 | uint32_t start = micros2(); 129 | while (ms > 0) 130 | { 131 | yield(); 132 | while ( ms > 0 && (micros2() - start) >= 1000) 133 | { 134 | ms--; 135 | start += 1000; 136 | } 137 | } 138 | } 139 | 140 | #endif //SYSTEM_TIMER_2 141 | -------------------------------------------------------------------------------- /src/backlight.cpp: -------------------------------------------------------------------------------- 1 | //backlight.cpp 2 | 3 | #include "backlight.h" 4 | #include "macros.h" 5 | #include 6 | #include 7 | #include "eeprom.h" 8 | #include "pins.h" 9 | #include "fastio.h" 10 | #include "Timer.h" 11 | 12 | #ifdef LCD_BL_PIN 13 | 14 | #define BL_FLASH_DELAY_MS 25 15 | 16 | bool backlightSupport = 0; //only if it's true will any of the settings be visible to the user 17 | int16_t backlightLevel_HIGH = 0; 18 | int16_t backlightLevel_LOW = 0; 19 | uint8_t backlightMode = BACKLIGHT_MODE_BRIGHT; 20 | int16_t backlightTimer_period = 10; 21 | LongTimer backlightTimer; 22 | 23 | static void backlightTimer_reset() //used for resetting the timer and waking the display. Triggered on user interactions. 24 | { 25 | if (!backlightSupport) return; 26 | backlightTimer.start(); 27 | backlight_update(); 28 | } 29 | 30 | void force_bl_on(bool section_start) 31 | { 32 | if (section_start) 33 | { 34 | backlightMode = BACKLIGHT_MODE_BRIGHT; 35 | if (backlightLevel_HIGH < 30) backlightLevel_HIGH = 30; 36 | } 37 | else 38 | { 39 | backlightMode = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_MODE); 40 | backlightLevel_HIGH = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH); 41 | } 42 | backlight_update(); 43 | } 44 | 45 | void backlight_wake(const uint8_t flashNo) 46 | { 47 | if (!backlightSupport) return; 48 | 49 | if (flashNo) 50 | { 51 | uint8_t backlightMode_bck = backlightMode; 52 | for (uint8_t i = 0; i < (((backlightMode_bck == BACKLIGHT_MODE_AUTO) && !backlightTimer.running()) + (flashNo * 2)); i++) 53 | { 54 | backlightMode = !backlightMode; //toggles between BACKLIGHT_MODE_BRIGHT and BACKLIGHT_MODE_DIM 55 | backlight_update(); 56 | _delay(BL_FLASH_DELAY_MS); 57 | } 58 | backlightMode = backlightMode_bck; 59 | } 60 | backlightTimer_reset(); 61 | } 62 | 63 | void backlight_save() //saves all backlight data to eeprom. 64 | { 65 | eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH, (uint8_t)backlightLevel_HIGH); 66 | eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, (uint8_t)backlightLevel_LOW); 67 | eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_MODE, backlightMode); 68 | eeprom_update_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, backlightTimer_period); 69 | } 70 | 71 | void backlight_update() 72 | { 73 | if (!backlightSupport) return; 74 | 75 | if (backlightMode == BACKLIGHT_MODE_AUTO) 76 | { 77 | if (backlightTimer.expired((uint32_t)backlightTimer_period * 1000ul)) analogWrite(LCD_BL_PIN, backlightLevel_LOW); 78 | else if (backlightTimer.running()) analogWrite(LCD_BL_PIN, backlightLevel_HIGH); 79 | else {/*do nothing*/;} //display is dimmed. 80 | } 81 | else if (backlightMode == BACKLIGHT_MODE_DIM) analogWrite(LCD_BL_PIN, backlightLevel_LOW); 82 | else analogWrite(LCD_BL_PIN, backlightLevel_HIGH); 83 | } 84 | 85 | void backlight_init() 86 | { 87 | //check for backlight support on lcd 88 | SET_INPUT(LCD_BL_PIN); 89 | WRITE(LCD_BL_PIN,HIGH); 90 | _delay(10); 91 | backlightSupport = !READ(LCD_BL_PIN); 92 | if (!backlightSupport) return; 93 | 94 | //initialize backlight 95 | backlightMode = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_MODE); 96 | if (backlightMode == 0xFF) //set default values 97 | { 98 | backlightMode = BACKLIGHT_MODE_AUTO; 99 | backlightLevel_HIGH = 130; 100 | backlightLevel_LOW = 50; 101 | backlightTimer_period = 10; //in seconds 102 | backlight_save(); 103 | } 104 | backlightLevel_HIGH = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH); 105 | backlightLevel_LOW = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW); 106 | backlightTimer_period = eeprom_read_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT); 107 | 108 | SET_OUTPUT(LCD_BL_PIN); 109 | backlightTimer_reset(); 110 | } 111 | 112 | #else //LCD_BL_PIN 113 | 114 | void force_bl_on(bool) {} 115 | void backlight_update() {} 116 | void backlight_init() {} 117 | void backlight_save() {} 118 | void backlight_wake(const uint8_t) {} 119 | 120 | #endif //LCD_BL_PIN 121 | -------------------------------------------------------------------------------- /src/mesh_bed_leveling.h: -------------------------------------------------------------------------------- 1 | #include "Marlin.h" 2 | 3 | #ifdef MESH_BED_LEVELING 4 | 5 | #define MEAS_NUM_X_DIST (float(MESH_MAX_X - MESH_MIN_X)/float(MESH_MEAS_NUM_X_POINTS - 1)) 6 | #define MEAS_NUM_Y_DIST (float(MESH_MAX_Y - MESH_MIN_Y)/float(MESH_MEAS_NUM_Y_POINTS - 1)) 7 | 8 | #define MESH_X_DIST (float(MESH_MAX_X - MESH_MIN_X)/float(MESH_NUM_X_POINTS - 1)) 9 | #define MESH_Y_DIST (float(MESH_MAX_Y - MESH_MIN_Y)/float(MESH_NUM_Y_POINTS - 1)) 10 | 11 | class mesh_bed_leveling { 12 | public: 13 | uint8_t active; 14 | float z_values[MESH_NUM_Y_POINTS][MESH_NUM_X_POINTS]; 15 | 16 | mesh_bed_leveling(); 17 | 18 | void reset(); 19 | 20 | #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 21 | void upsample_3x3(); 22 | #endif 23 | 24 | static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); } 25 | static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); } 26 | 27 | // Measurement point for the Z probe. 28 | // If use_default=true, then the default positions for a correctly built printer are used. 29 | // Otherwise a correction matrix is pulled from the EEPROM if available. 30 | static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default); 31 | 32 | void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; } 33 | 34 | int select_x_index(float x) { 35 | int i = 1; 36 | while (x > get_x(i) && i < MESH_NUM_X_POINTS - 1) i++; 37 | return i - 1; 38 | } 39 | 40 | int select_y_index(float y) { 41 | int i = 1; 42 | while (y > get_y(i) && i < MESH_NUM_Y_POINTS - 1) i++; 43 | return i - 1; 44 | } 45 | 46 | float get_z(float x, float y) { 47 | int i, j; 48 | float s, t; 49 | 50 | #if MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 51 | #define MESH_MID_X (0.5f*(MESH_MIN_X+MESH_MAX_X)) 52 | #define MESH_MID_Y (0.5f*(MESH_MIN_Y+MESH_MAX_Y)) 53 | if (x < MESH_MID_X) { 54 | i = 0; 55 | s = (x - MESH_MIN_X) / MESH_X_DIST; 56 | if (s > 1.f) 57 | s = 1.f; 58 | } else { 59 | i = 1; 60 | s = (x - MESH_MID_X) / MESH_X_DIST; 61 | if (s < 0) 62 | s = 0; 63 | } 64 | if (y < MESH_MID_Y) { 65 | j = 0; 66 | t = (y - MESH_MIN_Y) / MESH_Y_DIST; 67 | if (t > 1.f) 68 | t = 1.f; 69 | } else { 70 | j = 1; 71 | t = (y - MESH_MID_Y) / MESH_Y_DIST; 72 | if (t < 0) 73 | t = 0; 74 | } 75 | #else 76 | i = int(floor((x - MESH_MIN_X) / MESH_X_DIST)); 77 | if (i < 0) { 78 | i = 0; 79 | s = (x - MESH_MIN_X) / MESH_X_DIST; 80 | if (s > 1.f) 81 | s = 1.f; 82 | } 83 | else if (i > MESH_NUM_X_POINTS - 2) { 84 | i = MESH_NUM_X_POINTS - 2; 85 | s = (x - get_x(i)) / MESH_X_DIST; 86 | if (s < 0) 87 | s = 0; 88 | } else { 89 | s = (x - get_x(i)) / MESH_X_DIST; 90 | if (s < 0) 91 | s = 0; 92 | else if (s > 1.f) 93 | s = 1.f; 94 | } 95 | j = int(floor((y - MESH_MIN_Y) / MESH_Y_DIST)); 96 | if (j < 0) { 97 | j = 0; 98 | t = (y - MESH_MIN_Y) / MESH_Y_DIST; 99 | if (t > 1.f) 100 | t = 1.f; 101 | } else if (j > MESH_NUM_Y_POINTS - 2) { 102 | j = MESH_NUM_Y_POINTS - 2; 103 | t = (y - get_y(j)) / MESH_Y_DIST; 104 | if (t < 0) 105 | t = 0; 106 | } else { 107 | t = (y - get_y(j)) / MESH_Y_DIST; 108 | if (t < 0) 109 | t = 0; 110 | else if (t > 1.f) 111 | t = 1.f; 112 | } 113 | #endif /* MESH_NUM_X_POINTS==3 && MESH_NUM_Y_POINTS==3 */ 114 | 115 | float si = 1.f-s; 116 | float z0 = si * z_values[j ][i] + s * z_values[j ][i+1]; 117 | float z1 = si * z_values[j+1][i] + s * z_values[j+1][i+1]; 118 | return (1.f-t) * z0 + t * z1; 119 | } 120 | 121 | }; 122 | 123 | extern mesh_bed_leveling mbl; 124 | 125 | #endif // MESH_BED_LEVELING 126 | -------------------------------------------------------------------------------- /src/mesh_bed_leveling.cpp: -------------------------------------------------------------------------------- 1 | #include "mesh_bed_leveling.h" 2 | #include "mesh_bed_calibration.h" 3 | #include "Configuration.h" 4 | 5 | #ifdef MESH_BED_LEVELING 6 | 7 | mesh_bed_leveling mbl; 8 | 9 | mesh_bed_leveling::mesh_bed_leveling() { reset(); } 10 | 11 | void mesh_bed_leveling::reset() { 12 | active = 0; 13 | for (int y = 0; y < MESH_NUM_Y_POINTS; y++) 14 | for (int x = 0; x < MESH_NUM_X_POINTS; x++) 15 | z_values[y][x] = 0; 16 | } 17 | 18 | static inline bool vec_undef(const float v[2]) 19 | { 20 | const uint32_t *vx = (const uint32_t*)v; 21 | return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF; 22 | } 23 | 24 | #if MESH_NUM_X_POINTS>=5 && MESH_NUM_Y_POINTS>=5 && (MESH_NUM_X_POINTS&1)==1 && (MESH_NUM_Y_POINTS&1)==1 25 | // Works for an odd number of MESH_NUM_X_POINTS and MESH_NUM_Y_POINTS 26 | 27 | // #define MBL_BILINEAR 28 | void mesh_bed_leveling::upsample_3x3() 29 | { 30 | int idx0 = 0; 31 | int idx1 = MESH_NUM_X_POINTS / 2; 32 | int idx2 = MESH_NUM_X_POINTS - 1; 33 | { 34 | // First interpolate the points in X axis. 35 | static const float x0 = MESH_MIN_X; 36 | static const float x1 = 0.5f * float(MESH_MIN_X + MESH_MAX_X); 37 | static const float x2 = MESH_MAX_X; 38 | for (int j = 0; j < 3; ++ j) { 39 | // 1) Copy the source points to their new destination. 40 | z_values[j][idx2] = z_values[j][2]; 41 | z_values[j][idx1] = z_values[j][1]; 42 | // 2) Interpolate the remaining values by Largrangian polynomials. 43 | for (int i = idx0 + 1; i < idx2; ++ i) { 44 | if (i == idx1) 45 | continue; 46 | float x = get_x(i); 47 | #ifdef MBL_BILINEAR 48 | z_values[j][i] = (x < x1) ? 49 | ((z_values[j][idx0] * (x - x0) + z_values[j][idx1] * (x1 - x)) / (x1 - x0)) : 50 | ((z_values[j][idx1] * (x - x1) + z_values[j][idx2] * (x2 - x)) / (x2 - x1)); 51 | #else 52 | z_values[j][i] = 53 | z_values[j][idx0] * (x - x1) * (x - x2) / ((x0 - x1) * (x0 - x2)) + 54 | z_values[j][idx1] * (x - x0) * (x - x2) / ((x1 - x0) * (x1 - x2)) + 55 | z_values[j][idx2] * (x - x0) * (x - x1) / ((x2 - x0) * (x2 - x1)); 56 | #endif 57 | } 58 | } 59 | } 60 | { 61 | // Second interpolate the points in Y axis. 62 | static const float y0 = MESH_MIN_Y; 63 | static const float y1 = 0.5f * float(MESH_MIN_Y + MESH_MAX_Y); 64 | static const float y2 = MESH_MAX_Y; 65 | for (int i = 0; i < MESH_NUM_X_POINTS; ++ i) { 66 | // 1) Copy the intermediate points to their new destination. 67 | z_values[idx2][i] = z_values[2][i]; 68 | z_values[idx1][i] = z_values[1][i]; 69 | // 2) Interpolate the remaining values by Largrangian polynomials. 70 | for (int j = 1; j + 1 < MESH_NUM_Y_POINTS; ++ j) { 71 | if (j == idx1) 72 | continue; 73 | float y = get_y(j); 74 | #ifdef MBL_BILINEAR 75 | z_values[j][i] = (y < y1) ? 76 | ((z_values[idx0][i] * (y - y0) + z_values[idx1][i] * (y1 - y)) / (y1 - y0)) : 77 | ((z_values[idx1][i] * (y - y1) + z_values[idx2][i] * (y2 - y)) / (y2 - y1)); 78 | #else 79 | z_values[j][i] = 80 | z_values[idx0][i] * (y - y1) * (y - y2) / ((y0 - y1) * (y0 - y2)) + 81 | z_values[idx1][i] * (y - y0) * (y - y2) / ((y1 - y0) * (y1 - y2)) + 82 | z_values[idx2][i] * (y - y0) * (y - y1) / ((y2 - y0) * (y2 - y1)); 83 | #endif 84 | } 85 | } 86 | } 87 | 88 | /* 89 | // Relax the non-measured points. 90 | const float weight = 0.2f; 91 | for (uint8_t iter = 0; iter < 20; ++ iter) { 92 | for (int8_t j = 1; j < 6; ++ j) { 93 | for (int8_t i = 1; i < 6; ++ i) { 94 | if (i == 3 || j == 3) 95 | continue; 96 | if ((i % 3) == 0 && (j % 3) == 0) 97 | continue; 98 | float avg = 0.25f * (z_values[j][i-1]+z_values[j][i+1]+z_values[j-1][i]+z_values[j+1][i]); 99 | z_values[j][i] = (1.f-weight)*z_values[j][i] + weight*avg; 100 | } 101 | } 102 | } 103 | */ 104 | } 105 | #endif 106 | 107 | #endif // MESH_BED_LEVELING 108 | -------------------------------------------------------------------------------- /src/swi2c.c: -------------------------------------------------------------------------------- 1 | //swi2c.c 2 | #include "swi2c.h" 3 | #include 4 | #include 5 | #include 6 | #include "stdbool.h" 7 | #include "Configuration_prusa.h" 8 | #include "pins.h" 9 | #include "fastio.h" 10 | 11 | #ifdef SWI2C_SCL 12 | 13 | #define SWI2C_RMSK 0x01 //read mask (bit0 = 1) 14 | #define SWI2C_WMSK 0x00 //write mask (bit0 = 0) 15 | #define SWI2C_ASHF 0x01 //address shift (<< 1) 16 | #define SWI2C_DMSK 0x7f //device address mask 17 | 18 | 19 | void __delay(void) 20 | { 21 | _delay_us(1.5); 22 | } 23 | 24 | void swi2c_init(void) 25 | { 26 | WRITE(SWI2C_SDA, 1); 27 | WRITE(SWI2C_SCL, 1); 28 | SET_OUTPUT(SWI2C_SDA); 29 | SET_OUTPUT(SWI2C_SCL); 30 | uint8_t i; for (i = 0; i < 100; i++) 31 | __delay(); 32 | } 33 | 34 | void swi2c_start(void) 35 | { 36 | WRITE(SWI2C_SDA, 0); 37 | __delay(); 38 | WRITE(SWI2C_SCL, 0); 39 | __delay(); 40 | } 41 | 42 | void swi2c_stop(void) 43 | { 44 | WRITE(SWI2C_SCL, 1); 45 | __delay(); 46 | WRITE(SWI2C_SDA, 1); 47 | __delay(); 48 | } 49 | 50 | void swi2c_ack(void) 51 | { 52 | WRITE(SWI2C_SDA, 0); 53 | __delay(); 54 | WRITE(SWI2C_SCL, 1); 55 | __delay(); 56 | WRITE(SWI2C_SCL, 0); 57 | __delay(); 58 | } 59 | 60 | uint8_t swi2c_wait_ack() 61 | { 62 | SET_INPUT(SWI2C_SDA); 63 | __delay(); 64 | // WRITE(SWI2C_SDA, 1); 65 | __delay(); 66 | WRITE(SWI2C_SCL, 1); 67 | // __delay(); 68 | uint8_t ack = 0; 69 | uint16_t ackto = SWI2C_TMO; 70 | while (!(ack = (!READ(SWI2C_SDA))) && ackto--) __delay(); 71 | WRITE(SWI2C_SCL, 0); 72 | __delay(); 73 | SET_OUTPUT(SWI2C_SDA); 74 | __delay(); 75 | WRITE(SWI2C_SDA, 0); 76 | __delay(); 77 | return ack; 78 | } 79 | 80 | uint8_t swi2c_read(void) 81 | { 82 | WRITE(SWI2C_SDA, 1); 83 | __delay(); 84 | SET_INPUT(SWI2C_SDA); 85 | uint8_t data = 0; 86 | int8_t bit; for (bit = 7; bit >= 0; bit--) 87 | { 88 | WRITE(SWI2C_SCL, 1); 89 | __delay(); 90 | data |= (READ(SWI2C_SDA)) << bit; 91 | WRITE(SWI2C_SCL, 0); 92 | __delay(); 93 | } 94 | SET_OUTPUT(SWI2C_SDA); 95 | return data; 96 | } 97 | 98 | void swi2c_write(uint8_t data) 99 | { 100 | int8_t bit; for (bit = 7; bit >= 0; bit--) 101 | { 102 | WRITE(SWI2C_SDA, data & _BV(bit)); 103 | __delay(); 104 | WRITE(SWI2C_SCL, 1); 105 | __delay(); 106 | WRITE(SWI2C_SCL, 0); 107 | __delay(); 108 | } 109 | } 110 | 111 | uint8_t swi2c_check(uint8_t dev_addr) 112 | { 113 | swi2c_start(); 114 | swi2c_write((dev_addr & SWI2C_DMSK) << SWI2C_ASHF); 115 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 116 | swi2c_stop(); 117 | return 1; 118 | } 119 | 120 | #ifdef SWI2C_A8 //8bit address 121 | 122 | uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte) 123 | { 124 | swi2c_start(); 125 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 126 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 127 | swi2c_write(addr & 0xff); 128 | if (!swi2c_wait_ack()) return 0; 129 | swi2c_stop(); 130 | swi2c_start(); 131 | swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 132 | if (!swi2c_wait_ack()) return 0; 133 | uint8_t byte = swi2c_read(); 134 | swi2c_stop(); 135 | if (pbyte) *pbyte = byte; 136 | return 1; 137 | } 138 | 139 | uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte) 140 | { 141 | swi2c_start(); 142 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 143 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 144 | swi2c_write(addr & 0xff); 145 | if (!swi2c_wait_ack()) return 0; 146 | swi2c_write(*pbyte); 147 | if (!swi2c_wait_ack()) return 0; 148 | swi2c_stop(); 149 | return 1; 150 | } 151 | 152 | #endif //SWI2C_A8 153 | 154 | #ifdef SWI2C_A16 //16bit address 155 | 156 | uint8_t swi2c_readByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte) 157 | { 158 | swi2c_start(); 159 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 160 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 161 | swi2c_write(addr >> 8); 162 | if (!swi2c_wait_ack()) return 0; 163 | swi2c_write(addr & 0xff); 164 | if (!swi2c_wait_ack()) return 0; 165 | swi2c_stop(); 166 | swi2c_start(); 167 | swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 168 | if (!swi2c_wait_ack()) return 0; 169 | uint8_t byte = swi2c_read(); 170 | swi2c_stop(); 171 | if (pbyte) *pbyte = byte; 172 | return 1; 173 | } 174 | 175 | uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte) 176 | { 177 | swi2c_start(); 178 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 179 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 180 | swi2c_write(addr >> 8); 181 | if (!swi2c_wait_ack()) return 0; 182 | swi2c_write(addr & 0xff); 183 | if (!swi2c_wait_ack()) return 0; 184 | swi2c_write(*pbyte); 185 | if (!swi2c_wait_ack()) return 0; 186 | swi2c_stop(); 187 | return 1; 188 | } 189 | 190 | #endif //SWI2C_A16 191 | 192 | #endif //SWI2C_SCL 193 | -------------------------------------------------------------------------------- /src/pins_Rambo_1_0.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * Rambo mini 1.0 Pin Assignments 3 | ******************************************************************/ 4 | 5 | #define ELECTRONICS "RAMBo10a" 6 | 7 | #define KNOWN_BOARD 8 | #ifndef __AVR_ATmega2560__ 9 | #error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu. 10 | #endif 11 | 12 | #define PINDA_THERMISTOR 13 | 14 | #define SWI2C_SDA 20 //SDA on P3 15 | #define SWI2C_SCL 84 //PH2 on P3, sensor cable must be rewired 16 | 17 | 18 | 19 | #define X_STEP_PIN 37 20 | #define X_DIR_PIN 48 21 | #define X_MIN_PIN 12 22 | #define X_MAX_PIN -1 23 | #define X_ENABLE_PIN 29 24 | #define X_MS1_PIN 40 25 | #define X_MS2_PIN 41 26 | 27 | #define Y_STEP_PIN 36 28 | #define Y_DIR_PIN 49 29 | #define Y_MIN_PIN 11 30 | #define Y_MAX_PIN -1 31 | #define Y_ENABLE_PIN 28 32 | #define Y_MS1_PIN 69 33 | #define Y_MS2_PIN 39 34 | 35 | #define Z_STEP_PIN 35 36 | #define Z_DIR_PIN 47 37 | #define Z_MIN_PIN 10 38 | #define Z_MAX_PIN 23 39 | #define Z_ENABLE_PIN 27 40 | #define Z_MS1_PIN 68 41 | #define Z_MS2_PIN 67 42 | 43 | #define HEATER_BED_PIN 4 //PG5 44 | #define TEMP_BED_PIN 2 //A2 45 | 46 | #define HEATER_0_PIN 3 //PE5 47 | #define TEMP_0_PIN 0 //A0 48 | 49 | #define HEATER_1_PIN -1 50 | #define TEMP_1_PIN -1 //A1 51 | 52 | #define HEATER_2_PIN -1 53 | #define TEMP_2_PIN -1 54 | 55 | #define TEMP_AMBIENT_PIN 6 //A6 56 | 57 | #define TEMP_PINDA_PIN 1 //A1 58 | 59 | 60 | 61 | #define E0_STEP_PIN 34 62 | #define E0_DIR_PIN 43 63 | #define E0_ENABLE_PIN 26 64 | #define E0_MS1_PIN 65 65 | #define E0_MS2_PIN 66 66 | 67 | #ifdef SNMM 68 | #define E_MUX0_PIN 17 69 | #define E_MUX1_PIN 16 70 | #endif 71 | 72 | 73 | #define MOTOR_CURRENT_PWM_XY_PIN 46 74 | #define MOTOR_CURRENT_PWM_Z_PIN 45 75 | #define MOTOR_CURRENT_PWM_E_PIN 44 76 | #define SDPOWER -1 77 | #define SDSS 53 78 | #define LED_PIN 13 79 | #define FAN_PIN 6 80 | #define FAN_1_PIN -1 81 | #define PS_ON_PIN -1 82 | #define KILL_PIN -1 // 80 with Smart Controller LCD 83 | #define SUICIDE_PIN -1 // PIN that has to be turned on right after start, to keep power flowing. 84 | #define TACH_0 30 // noctua extruder fan 85 | 86 | 87 | //#define KILL_PIN 32 88 | 89 | 90 | #define BEEPER 78 // Beeper on AUX-4 91 | #define LCD_PINS_RS 38 92 | #define LCD_PINS_ENABLE 5 93 | #define LCD_PINS_D4 14 94 | #define LCD_PINS_D5 15 95 | #define LCD_PINS_D6 32 96 | #define LCD_PINS_D7 31 97 | 98 | //buttons are directly attached using AUX-2 99 | #define BTN_EN1 80 100 | #define BTN_EN2 73 101 | #define BTN_ENC 21 // the click 102 | 103 | #define SDCARDDETECT 72 104 | 105 | #define IR_SENSOR_PIN 20 //idler sensor 106 | 107 | // Support for an 8 bit logic analyzer, for example the Saleae. 108 | // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop. 109 | #define LOGIC_ANALYZER_CH0 X_MIN_PIN // PB6 110 | #define LOGIC_ANALYZER_CH1 Y_MIN_PIN // PB5 111 | #define LOGIC_ANALYZER_CH2 53 // PB0 (PROC_nCS) 112 | // Channels 3-7 are slow, they could generate 113 | // 0.889Mhz waveform with a software loop and interrupt locking, 114 | // 1.333MHz waveform without interrupt locking. 115 | #define LOGIC_ANALYZER_CH3 73 // PJ3 116 | // PK0 has no Arduino digital pin assigned, so we set it directly. 117 | #define WRITE_LOGIC_ANALYZER_CH4(value) if (value) PORTK |= (1 << 0); else PORTK &= ~(1 << 0) // PK0 118 | #define LOGIC_ANALYZER_CH5 16 // PH0 (RXD2) 119 | #define LOGIC_ANALYZER_CH6 17 // PH1 (TXD2) 120 | #define LOGIC_ANALYZER_CH7 76 // PJ5 121 | 122 | #define LOGIC_ANALYZER_CH0_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH0) 123 | #define LOGIC_ANALYZER_CH1_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH1) 124 | #define LOGIC_ANALYZER_CH2_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH2) 125 | #define LOGIC_ANALYZER_CH3_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH3) 126 | #define LOGIC_ANALYZER_CH4_ENABLE do { DDRK |= 1 << 0; } while (0) 127 | #define LOGIC_ANALYZER_CH5_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH5); } while (0) 128 | #define LOGIC_ANALYZER_CH6_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH6); } while (0) 129 | #define LOGIC_ANALYZER_CH7_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH7) 130 | 131 | -------------------------------------------------------------------------------- /src/pins_Rambo_1_3.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * Rambo mini 1.3 Pin Assignments 3 | ******************************************************************/ 4 | 5 | #define ELECTRONICS "RAMBo13a" 6 | 7 | #define KNOWN_BOARD 8 | #ifndef __AVR_ATmega2560__ 9 | #error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu. 10 | #endif 11 | 12 | #define PINDA_THERMISTOR 13 | 14 | #ifdef MICROMETER_LOGGING 15 | #define D_DATACLOCK 24 //Y_MAX (green) 16 | #define D_DATA 30 //X_MAX (blue) 17 | #define D_REQUIRE 23 //Z_MAX (white) 18 | #endif //MICROMETER_LOGGING 19 | 20 | 21 | 22 | #define X_STEP_PIN 37 23 | #define X_DIR_PIN 48 24 | #define X_MIN_PIN 12 25 | #define X_MAX_PIN -1 26 | #define X_ENABLE_PIN 29 27 | #define X_MS1_PIN 40 28 | #define X_MS2_PIN 41 29 | 30 | #define Y_STEP_PIN 36 31 | #define Y_DIR_PIN 49 32 | #define Y_MIN_PIN 11 33 | #define Y_MAX_PIN -1 34 | #define Y_ENABLE_PIN 28 35 | #define Y_MS1_PIN 69 36 | #define Y_MS2_PIN 39 37 | 38 | #define Z_STEP_PIN 35 39 | #define Z_DIR_PIN 47 40 | #define Z_MIN_PIN 10 41 | #define Z_MAX_PIN 23 42 | #define Z_ENABLE_PIN 27 43 | #define Z_MS1_PIN 68 44 | #define Z_MS2_PIN 67 45 | 46 | #define HEATER_BED_PIN 4 //PG5 47 | #define TEMP_BED_PIN 2 //A2 48 | 49 | #define HEATER_0_PIN 3 //PE5 50 | #define TEMP_0_PIN 0 //A0 51 | 52 | #define HEATER_1_PIN -1 53 | #define TEMP_1_PIN -1 //A1 54 | 55 | #define HEATER_2_PIN -1 56 | #define TEMP_2_PIN -1 57 | 58 | #define TEMP_AMBIENT_PIN 6 //A6 59 | 60 | #define TEMP_PINDA_PIN 1 //A1 61 | 62 | 63 | 64 | #define E0_STEP_PIN 34 65 | #define E0_DIR_PIN 43 66 | #define E0_ENABLE_PIN 26 67 | #define E0_MS1_PIN 65 68 | #define E0_MS2_PIN 66 69 | 70 | #ifdef SNMM 71 | #define E_MUX0_PIN 17 72 | #define E_MUX1_PIN 16 73 | #endif 74 | 75 | 76 | #define MOTOR_CURRENT_PWM_XY_PIN 46 77 | #define MOTOR_CURRENT_PWM_Z_PIN 45 78 | #define MOTOR_CURRENT_PWM_E_PIN 44 79 | #define SDPOWER -1 80 | #define SDSS 53 81 | #define LED_PIN 13 82 | #define FAN_PIN 6 83 | #define FAN_1_PIN -1 84 | #define PS_ON_PIN -1 85 | #define KILL_PIN -1 // 80 with Smart Controller LCD 86 | #define SUICIDE_PIN -1 // PIN that has to be turned on right after start, to keep power flowing. 87 | #define TACH_0 30 // noctua extruder fan 88 | 89 | 90 | //#define KILL_PIN 32 91 | 92 | 93 | #define BEEPER 84 // Beeper on AUX-4 94 | #define LCD_PINS_RS 82 95 | #define LCD_PINS_ENABLE 18 96 | #define LCD_PINS_D4 19 97 | #define LCD_PINS_D5 70 98 | #define LCD_PINS_D6 85 99 | #define LCD_PINS_D7 71 100 | 101 | //buttons are directly attached using AUX-2 102 | #define BTN_EN1 72 103 | #define BTN_EN2 14 104 | #define BTN_ENC 9 // the click 105 | 106 | #define SDCARDDETECT 15 107 | 108 | #define IR_SENSOR_PIN 20 //idler sensor 109 | 110 | // Support for an 8 bit logic analyzer, for example the Saleae. 111 | // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop. 112 | #define LOGIC_ANALYZER_CH0 X_MIN_PIN // PB6 113 | #define LOGIC_ANALYZER_CH1 Y_MIN_PIN // PB5 114 | #define LOGIC_ANALYZER_CH2 53 // PB0 (PROC_nCS) 115 | // Channels 3-7 are slow, they could generate 116 | // 0.889Mhz waveform with a software loop and interrupt locking, 117 | // 1.333MHz waveform without interrupt locking. 118 | #define LOGIC_ANALYZER_CH3 73 // PJ3 119 | // PK0 has no Arduino digital pin assigned, so we set it directly. 120 | #define WRITE_LOGIC_ANALYZER_CH4(value) if (value) PORTK |= (1 << 0); else PORTK &= ~(1 << 0) // PK0 121 | #define LOGIC_ANALYZER_CH5 16 // PH0 (RXD2) 122 | #define LOGIC_ANALYZER_CH6 17 // PH1 (TXD2) 123 | #define LOGIC_ANALYZER_CH7 76 // PJ5 124 | 125 | #define LOGIC_ANALYZER_CH0_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH0) 126 | #define LOGIC_ANALYZER_CH1_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH1) 127 | #define LOGIC_ANALYZER_CH2_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH2) 128 | #define LOGIC_ANALYZER_CH3_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH3) 129 | #define LOGIC_ANALYZER_CH4_ENABLE do { DDRK |= 1 << 0; } while (0) 130 | #define LOGIC_ANALYZER_CH5_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH5); } while (0) 131 | #define LOGIC_ANALYZER_CH6_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH6); } while (0) 132 | #define LOGIC_ANALYZER_CH7_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH7) 133 | 134 | -------------------------------------------------------------------------------- /src/SdFatConfig.h: -------------------------------------------------------------------------------- 1 | /* Arduino SdFat Library 2 | * Copyright (C) 2009 by William Greiman 3 | * 4 | * This file is part of the Arduino SdFat Library 5 | * 6 | * This Library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This Library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with the Arduino SdFat Library. If not, see 18 | * . 19 | */ 20 | /** 21 | * \file 22 | * \brief configuration definitions 23 | */ 24 | #include "Marlin.h" 25 | #ifdef SDSUPPORT 26 | 27 | #ifndef SdFatConfig_h 28 | #define SdFatConfig_h 29 | #include 30 | //------------------------------------------------------------------------------ 31 | /** 32 | * To use multiple SD cards set USE_MULTIPLE_CARDS nonzero. 33 | * 34 | * Using multiple cards costs 400 - 500 bytes of flash. 35 | * 36 | * Each card requires about 550 bytes of SRAM so use of a Mega is recommended. 37 | */ 38 | #define USE_MULTIPLE_CARDS 0 39 | //------------------------------------------------------------------------------ 40 | /** 41 | * Call flush for endl if ENDL_CALLS_FLUSH is nonzero 42 | * 43 | * The standard for iostreams is to call flush. This is very costly for 44 | * SdFat. Each call to flush causes 2048 bytes of I/O to the SD. 45 | * 46 | * SdFat has a single 512 byte buffer for SD I/O so it must write the current 47 | * data block to the SD, read the directory block from the SD, update the 48 | * directory entry, write the directory block to the SD and read the data 49 | * block back into the buffer. 50 | * 51 | * The SD flash memory controller is not designed for this many rewrites 52 | * so performance may be reduced by more than a factor of 100. 53 | * 54 | * If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force 55 | * all data to be written to the SD. 56 | */ 57 | #define ENDL_CALLS_FLUSH 0 58 | //------------------------------------------------------------------------------ 59 | /** 60 | * Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero 61 | */ 62 | #define ALLOW_DEPRECATED_FUNCTIONS 1 63 | //------------------------------------------------------------------------------ 64 | /** 65 | * Allow FAT12 volumes if FAT12_SUPPORT is nonzero. 66 | * FAT12 has not been well tested. 67 | */ 68 | #define FAT12_SUPPORT 0 69 | //------------------------------------------------------------------------------ 70 | /** 71 | * SPI init rate for SD initialization commands. Must be 5 (F_CPU/64) 72 | * or 6 (F_CPU/128). 73 | */ 74 | #define SPI_SD_INIT_RATE 5 75 | //------------------------------------------------------------------------------ 76 | /** 77 | * Set the SS pin high for hardware SPI. If SS is chip select for another SPI 78 | * device this will disable that device during the SD init phase. 79 | */ 80 | #define SET_SPI_SS_HIGH 1 81 | //------------------------------------------------------------------------------ 82 | /** 83 | * Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos. 84 | * Pins used are SS 10, MOSI 11, MISO 12, and SCK 13. 85 | * 86 | * MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used 87 | * on Mega Arduinos. Software SPI works well with GPS Shield V1.1 88 | * but many SD cards will fail with GPS Shield V1.0. 89 | */ 90 | #define MEGA_SOFT_SPI 0 91 | //------------------------------------------------------------------------------ 92 | /** 93 | * Set USE_SOFTWARE_SPI nonzero to always use software SPI. 94 | */ 95 | #define USE_SOFTWARE_SPI 0 96 | // define software SPI pins so Mega can use unmodified 168/328 shields 97 | /** Software SPI chip select pin for the SD */ 98 | uint8_t const SOFT_SPI_CS_PIN = 10; 99 | /** Software SPI Master Out Slave In pin */ 100 | uint8_t const SOFT_SPI_MOSI_PIN = 11; 101 | /** Software SPI Master In Slave Out pin */ 102 | uint8_t const SOFT_SPI_MISO_PIN = 12; 103 | /** Software SPI Clock pin */ 104 | uint8_t const SOFT_SPI_SCK_PIN = 13; 105 | //------------------------------------------------------------------------------ 106 | /** 107 | * The __cxa_pure_virtual function is an error handler that is invoked when 108 | * a pure virtual function is called. 109 | */ 110 | #define USE_CXA_PURE_VIRTUAL 1 111 | /** 112 | * Defines for long (vfat) filenames 113 | */ 114 | /** Number of VFAT entries used. Every entry has 13 UTF-16 characters */ 115 | #define MAX_VFAT_ENTRIES (4) 116 | /** Number of UTF-16 characters per entry */ 117 | #define FILENAME_LENGTH 13 118 | /** Total size of the buffer used to store the long filenames */ 119 | #define LONG_FILENAME_LENGTH (13*MAX_VFAT_ENTRIES+1) 120 | #endif // SdFatConfig_h 121 | 122 | 123 | #endif 124 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ;PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [common_env_data] 12 | build_flags = 13 | -D BN=2528 14 | -D VERSION=4.0.2 15 | 16 | [env:MK3S_Bondtech-16-Mosquito_Magnum] 17 | platform = atmelavr 18 | extra_scripts = pre:.build/pre_build_script.py 19 | board = prusa_rambo 20 | framework = arduino 21 | lib_ignore = RF24_STM32 22 | src_filter = +<*> - 23 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 24 | ${common_env_data.build_flags} 25 | -D CONFIG=MK3S_Bondtech-16-Mosquito_Magnum 26 | 27 | [env:MK3S_Bondtech-16-Mosquito] 28 | platform = atmelavr 29 | extra_scripts = pre:.build/pre_build_script.py 30 | board = prusa_rambo 31 | framework = arduino 32 | lib_ignore = RF24_STM32 33 | src_filter = +<*> - 34 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 35 | ${common_env_data.build_flags} 36 | -D CONFIG=MK3S_Bondtech-16-Mosquito 37 | 38 | [env:MK3S_Bondtech-16-SE_HT-Mosquito_Magnum] 39 | platform = atmelavr 40 | extra_scripts = pre:.build/pre_build_script.py 41 | board = prusa_rambo 42 | framework = arduino 43 | lib_ignore = RF24_STM32 44 | src_filter = +<*> - 45 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 46 | ${common_env_data.build_flags} 47 | -D CONFIG=MK3S_Bondtech-16-SE_HT-Mosquito_Magnum 48 | 49 | [env:MK3S_Bondtech-16-SE_HT-Mosquito] 50 | platform = atmelavr 51 | extra_scripts = pre:.build/pre_build_script.py 52 | board = prusa_rambo 53 | framework = arduino 54 | lib_ignore = RF24_STM32 55 | src_filter = +<*> - 56 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 57 | ${common_env_data.build_flags} 58 | -D CONFIG=MK3S_Bondtech-16-SE_HT-Mosquito 59 | 60 | [env:MK3S_Bondtech-16-SE_HT-Thermistor] 61 | platform = atmelavr 62 | extra_scripts = pre:.build/pre_build_script.py 63 | board = prusa_rambo 64 | framework = arduino 65 | lib_ignore = RF24_STM32 66 | src_filter = +<*> - 67 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 68 | ${common_env_data.build_flags} 69 | -D CONFIG=MK3S_Bondtech-16-SE_HT-Thermistor 70 | 71 | [env:MK3S_Bondtech-16] 72 | platform = atmelavr 73 | extra_scripts = pre:.build/pre_build_script.py 74 | board = prusa_rambo 75 | framework = arduino 76 | lib_ignore = RF24_STM32 77 | src_filter = +<*> - 78 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 79 | ${common_env_data.build_flags} 80 | -D CONFIG=MK3S_Bondtech-16 81 | 82 | [env:MK3S_Bondtech-16-gizzburn] 83 | platform = atmelavr 84 | extra_scripts = pre:.build/pre_build_script.py 85 | board = prusa_rambo 86 | framework = arduino 87 | lib_ignore = RF24_STM32 88 | src_filter = +<*> - 89 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 90 | ${common_env_data.build_flags} 91 | -D CONFIG=MK3S_Bondtech-16-gizzburn 92 | 93 | [env:MK25S_RAMBo13a-Bear] 94 | platform = atmelavr 95 | extra_scripts = pre:.build/pre_build_script.py 96 | board = prusa_rambo 97 | framework = arduino 98 | lib_ignore = RF24_STM32 99 | src_filter = +<*> - 100 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 101 | ${common_env_data.build_flags} 102 | -D CONFIG=MK25S_RAMBo13a-Bear 103 | 104 | [env:MK25S_RAMBo13a] 105 | platform = atmelavr 106 | extra_scripts = pre:.build/pre_build_script.py 107 | board = prusa_rambo 108 | framework = arduino 109 | lib_ignore = RF24_STM32 110 | src_filter = +<*> - 111 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 112 | ${common_env_data.build_flags} 113 | -D CONFIG=MK25S_RAMBo13a 114 | 115 | [env:MK3S-BLTouch] 116 | platform = atmelavr 117 | extra_scripts = pre:.build/pre_build_script.py 118 | board = prusa_rambo 119 | framework = arduino 120 | lib_ignore = RF24_STM32 121 | src_filter = +<*> - 122 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 123 | ${common_env_data.build_flags} 124 | -D CONFIG=MK3S-BLTouch 125 | 126 | [env:MK3S-Bear] 127 | platform = atmelavr 128 | extra_scripts = pre:.build/pre_build_script.py 129 | board = prusa_rambo 130 | framework = arduino 131 | lib_ignore = RF24_STM32 132 | src_filter = +<*> - 133 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 134 | ${common_env_data.build_flags} 135 | -D CONFIG=MK3S-Bear 136 | 137 | [env:MK3S] 138 | platform = atmelavr 139 | extra_scripts = pre:.build/pre_build_script.py 140 | board = prusa_rambo 141 | framework = arduino 142 | lib_ignore = RF24_STM32 143 | src_filter = +<*> - 144 | build_flags = -w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections 145 | ${common_env_data.build_flags} 146 | -D CONFIG=MK3S -------------------------------------------------------------------------------- /src/tmc2130.h: -------------------------------------------------------------------------------- 1 | #ifndef TMC2130_H 2 | #define TMC2130_H 3 | 4 | #include 5 | 6 | //mode 7 | extern uint8_t tmc2130_mode; 8 | extern uint8_t tmc2130_current_h[4]; 9 | extern uint8_t tmc2130_current_r[4]; 10 | //microstep resolution (0 means 256usteps, 8 means 1ustep 11 | extern uint8_t tmc2130_mres[4]; 12 | 13 | //flags for axis stall detection 14 | extern uint8_t tmc2130_sg_thr[4]; 15 | 16 | extern bool tmc2130_sg_stop_on_crash; 17 | extern uint8_t tmc2130_sg_crash; //crash mask 18 | 19 | extern uint8_t tmc2130_sg_meassure; 20 | extern uint32_t tmc2130_sg_meassure_cnt; 21 | extern uint32_t tmc2130_sg_meassure_val; 22 | 23 | extern uint8_t tmc2130_sg_homing_axes_mask; 24 | 25 | extern const char eMotorCurrentScalingEnabled[]; 26 | 27 | #define TMC2130_MODE_NORMAL 0 28 | #define TMC2130_MODE_SILENT 1 29 | 30 | #define TMC2130_WAVE_FAC1000_MIN 30 31 | #define TMC2130_WAVE_FAC1000_MAX 200 32 | #define TMC2130_WAVE_FAC1000_STP 1 33 | 34 | #define TMC2130_MINIMUM_PULSE 0 // minimum pulse width in uS 35 | #define TMC2130_SET_DIR_DELAY 20 // minimum delay after setting direction in uS 36 | #define TMC2130_SET_PWR_DELAY 0 // minimum delay after changing pwr mode in uS 37 | 38 | #ifdef TMC2130_DEDGE_STEPPING 39 | #define TMC2130_MINIMUM_DELAY //NOP 40 | #elif TMC2130_MINIMUM_PULSE == 0 41 | #define TMC2130_MINIMUM_DELAY asm("nop") 42 | #else 43 | #define TMC2130_MINIMUM_DELAY delayMicroseconds(TMC2130_MINIMUM_PULSE) 44 | #endif 45 | 46 | extern uint8_t tmc2130_home_enabled; 47 | extern uint8_t tmc2130_home_origin[2]; 48 | extern uint8_t tmc2130_home_bsteps[2]; 49 | extern uint8_t tmc2130_home_fsteps[2]; 50 | 51 | extern uint8_t tmc2130_wave_fac[4]; 52 | 53 | #pragma pack(push) 54 | #pragma pack(1) 55 | typedef struct 56 | { 57 | uint8_t toff:4; 58 | uint8_t hstr:3; 59 | uint8_t hend:4; 60 | uint8_t tbl:2; 61 | uint8_t res:3; 62 | } tmc2130_chopper_config_t; 63 | #pragma pack(pop) 64 | 65 | extern tmc2130_chopper_config_t tmc2130_chopper_config[4]; 66 | 67 | //initialize tmc2130 68 | 69 | struct TMCInitParams { 70 | uint8_t bSuppressFlag : 1; // only relevant on MK3S with PSU_Delta 71 | uint8_t enableECool : 1; // experimental support for E-motor cooler operation 72 | inline TMCInitParams():bSuppressFlag(0), enableECool(0) { } 73 | inline explicit TMCInitParams(bool bSuppressFlag, bool enableECool):bSuppressFlag(bSuppressFlag), enableECool(enableECool) { } 74 | inline explicit TMCInitParams(bool enableECool) 75 | : bSuppressFlag( 76 | #ifdef PSU_delta 77 | 1 78 | #else 79 | 0 80 | #endif 81 | ) 82 | , enableECool(enableECool) { } 83 | }; 84 | extern void tmc2130_init(TMCInitParams params); 85 | //check diag pins (called from stepper isr) 86 | extern void tmc2130_st_isr(); 87 | //update stall guard (called from st_synchronize inside the loop) 88 | extern bool tmc2130_update_sg(); 89 | //temperature watching (called from ) 90 | extern void tmc2130_check_overtemp(); 91 | //enter homing (called from homeaxis before homing starts) 92 | extern void tmc2130_home_enter(uint8_t axes_mask); 93 | //exit homing (called from homeaxis after homing ends) 94 | extern void tmc2130_home_exit(); 95 | 96 | //start stallguard meassuring for single axis 97 | extern void tmc2130_sg_meassure_start(uint8_t axis); 98 | //stop current stallguard meassuring and report result 99 | extern uint16_t tmc2130_sg_meassure_stop(); 100 | 101 | extern void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r); 102 | 103 | //set holding current for any axis (M911) 104 | extern void tmc2130_set_current_h(uint8_t axis, uint8_t current); 105 | //set running current for any axis (M912) 106 | extern void tmc2130_set_current_r(uint8_t axis, uint8_t current); 107 | //print currents (M913) 108 | extern void tmc2130_print_currents(); 109 | 110 | //set PWM_AMPL for any axis (M917) 111 | extern void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl); 112 | //set PWM_GRAD for any axis (M918) 113 | extern void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_ampl); 114 | 115 | 116 | extern uint16_t tmc2130_rd_MSCNT(uint8_t axis); 117 | extern uint32_t tmc2130_rd_MSCURACT(uint8_t axis); 118 | 119 | extern uint8_t tmc2130_usteps2mres(uint16_t usteps); 120 | #define tmc2130_mres2usteps(mres) ((uint16_t)256 >> mres) 121 | 122 | extern bool tmc2130_wait_standstill_xy(int timeout); 123 | 124 | extern uint16_t tmc2130_get_res(uint8_t axis); 125 | extern void tmc2130_set_res(uint8_t axis, uint16_t res); 126 | extern uint8_t tmc2130_get_pwr(uint8_t axis); 127 | extern void tmc2130_set_pwr(uint8_t axis, uint8_t pwr); 128 | extern uint8_t tmc2130_get_inv(uint8_t axis); 129 | extern uint8_t tmc2130_get_dir(uint8_t axis); 130 | extern void tmc2130_set_dir(uint8_t axis, uint8_t dir); 131 | extern void tmc2130_do_step(uint8_t axis); 132 | extern void tmc2130_do_steps(uint8_t axis, uint16_t steps, uint8_t dir, uint16_t delay_us); 133 | extern void tmc2130_goto_step(uint8_t axis, uint8_t step, uint8_t dir, uint16_t delay_us, uint16_t microstep_resolution); 134 | extern void tmc2130_get_wave(uint8_t axis, uint8_t* data, FILE* stream); 135 | extern void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000); 136 | 137 | extern bool tmc2130_home_calibrate(uint8_t axis); 138 | 139 | extern uint8_t tmc2130_cur2val(float cur); 140 | extern float tmc2130_val2cur(uint8_t val); 141 | 142 | #endif //TMC2130_H 143 | -------------------------------------------------------------------------------- /src/vector_3.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | vector_3.cpp - Vector library for bed leveling 3 | Copyright (c) 2012 Lars Brubaker. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | #include 20 | #include "Marlin.h" 21 | 22 | #ifdef ENABLE_AUTO_BED_LEVELING 23 | #include "vector_3.h" 24 | 25 | vector_3::vector_3() : x(0), y(0), z(0) { } 26 | 27 | vector_3::vector_3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) { } 28 | 29 | vector_3 vector_3::cross(vector_3 left, vector_3 right) 30 | { 31 | return vector_3(left.y * right.z - left.z * right.y, 32 | left.z * right.x - left.x * right.z, 33 | left.x * right.y - left.y * right.x); 34 | } 35 | 36 | vector_3 vector_3::operator+(vector_3 v) 37 | { 38 | return vector_3((x + v.x), (y + v.y), (z + v.z)); 39 | } 40 | 41 | vector_3 vector_3::operator-(vector_3 v) 42 | { 43 | return vector_3((x - v.x), (y - v.y), (z - v.z)); 44 | } 45 | 46 | vector_3 vector_3::get_normal() 47 | { 48 | vector_3 normalized = vector_3(x, y, z); 49 | normalized.normalize(); 50 | return normalized; 51 | } 52 | 53 | float vector_3::get_length() 54 | { 55 | float length = sqrt((x * x) + (y * y) + (z * z)); 56 | return length; 57 | } 58 | 59 | void vector_3::normalize() 60 | { 61 | float length = get_length(); 62 | x /= length; 63 | y /= length; 64 | z /= length; 65 | } 66 | 67 | void vector_3::apply_rotation(matrix_3x3 matrix) 68 | { 69 | float resultX = x * matrix.matrix[3*0+0] + y * matrix.matrix[3*1+0] + z * matrix.matrix[3*2+0]; 70 | float resultY = x * matrix.matrix[3*0+1] + y * matrix.matrix[3*1+1] + z * matrix.matrix[3*2+1]; 71 | float resultZ = x * matrix.matrix[3*0+2] + y * matrix.matrix[3*1+2] + z * matrix.matrix[3*2+2]; 72 | 73 | x = resultX; 74 | y = resultY; 75 | z = resultZ; 76 | } 77 | 78 | void vector_3::debug(char* title) 79 | { 80 | SERIAL_PROTOCOL(title); 81 | SERIAL_PROTOCOLPGM(" x: "); 82 | SERIAL_PROTOCOL(x); 83 | SERIAL_PROTOCOLPGM(" y: "); 84 | SERIAL_PROTOCOL(y); 85 | SERIAL_PROTOCOLPGM(" z: "); 86 | SERIAL_PROTOCOL(z); 87 | SERIAL_PROTOCOLPGM("\n"); 88 | } 89 | 90 | void apply_rotation_xyz(matrix_3x3 matrix, float &x, float& y, float& z) 91 | { 92 | vector_3 vector = vector_3(x, y, z); 93 | vector.apply_rotation(matrix); 94 | x = vector.x; 95 | y = vector.y; 96 | z = vector.z; 97 | } 98 | 99 | matrix_3x3 matrix_3x3::create_from_rows(vector_3 row_0, vector_3 row_1, vector_3 row_2) 100 | { 101 | //row_0.debug("row_0"); 102 | //row_1.debug("row_1"); 103 | //row_2.debug("row_2"); 104 | matrix_3x3 new_matrix; 105 | new_matrix.matrix[0] = row_0.x; new_matrix.matrix[1] = row_0.y; new_matrix.matrix[2] = row_0.z; 106 | new_matrix.matrix[3] = row_1.x; new_matrix.matrix[4] = row_1.y; new_matrix.matrix[5] = row_1.z; 107 | new_matrix.matrix[6] = row_2.x; new_matrix.matrix[7] = row_2.y; new_matrix.matrix[8] = row_2.z; 108 | //new_matrix.debug("new_matrix"); 109 | 110 | return new_matrix; 111 | } 112 | 113 | void matrix_3x3::set_to_identity() 114 | { 115 | matrix[0] = 1; matrix[1] = 0; matrix[2] = 0; 116 | matrix[3] = 0; matrix[4] = 1; matrix[5] = 0; 117 | matrix[6] = 0; matrix[7] = 0; matrix[8] = 1; 118 | } 119 | 120 | matrix_3x3 matrix_3x3::create_look_at(vector_3 target) 121 | { 122 | vector_3 z_row = target.get_normal(); 123 | vector_3 x_row = vector_3(1, 0, -target.x/target.z).get_normal(); 124 | vector_3 y_row = vector_3::cross(z_row, x_row).get_normal(); 125 | 126 | // x_row.debug("x_row"); 127 | // y_row.debug("y_row"); 128 | // z_row.debug("z_row"); 129 | 130 | 131 | // create the matrix already correctly transposed 132 | matrix_3x3 rot = matrix_3x3::create_from_rows(x_row, y_row, z_row); 133 | 134 | // rot.debug("rot"); 135 | return rot; 136 | } 137 | 138 | 139 | matrix_3x3 matrix_3x3::transpose(matrix_3x3 original) 140 | { 141 | matrix_3x3 new_matrix; 142 | new_matrix.matrix[0] = original.matrix[0]; new_matrix.matrix[1] = original.matrix[3]; new_matrix.matrix[2] = original.matrix[6]; 143 | new_matrix.matrix[3] = original.matrix[1]; new_matrix.matrix[4] = original.matrix[4]; new_matrix.matrix[5] = original.matrix[7]; 144 | new_matrix.matrix[6] = original.matrix[2]; new_matrix.matrix[7] = original.matrix[5]; new_matrix.matrix[8] = original.matrix[8]; 145 | return new_matrix; 146 | } 147 | 148 | void matrix_3x3::debug(char* title) 149 | { 150 | SERIAL_PROTOCOL(title); 151 | SERIAL_PROTOCOL("\n"); 152 | int count = 0; 153 | for(int i=0; i<3; i++) 154 | { 155 | for(int j=0; j<3; j++) 156 | { 157 | SERIAL_PROTOCOL(matrix[count]); 158 | SERIAL_PROTOCOLPGM(" "); 159 | count++; 160 | } 161 | 162 | SERIAL_PROTOCOLPGM("\n"); 163 | } 164 | } 165 | 166 | #endif // #ifdef ENABLE_AUTO_BED_LEVELING 167 | 168 | -------------------------------------------------------------------------------- /src/language.h: -------------------------------------------------------------------------------- 1 | /** @file */ 2 | //language.h 3 | #ifndef LANGUAGE_H 4 | #define LANGUAGE_H 5 | 6 | 7 | #include "config.h" 8 | #include "macros.h" 9 | #include 10 | #ifdef DEBUG_SEC_LANG 11 | #include 12 | #endif //DEBUG_SEC_LANG 13 | 14 | #define PROTOCOL_VERSION "1.0" 15 | 16 | #ifndef CUSTOM_MENDEL_NAME 17 | #define MACHINE_NAME "Mendel" 18 | #endif 19 | 20 | #ifndef MACHINE_UUID 21 | #define MACHINE_UUID "00000000-0000-0000-0000-000000000000" 22 | #endif 23 | 24 | #if (LANG_MODE == 0) //primary language only 25 | #define PROGMEM_I2 __attribute__((section(".progmem0"))) 26 | #define PROGMEM_I1 __attribute__((section(".progmem1"))) 27 | #define PROGMEM_N1 __attribute__((section(".progmem2"))) 28 | #define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = s; &__c[0];})) 29 | #define ISTR(s) s 30 | #define _i(s) _I(s) 31 | #define _T(s) s 32 | #else //(LANG_MODE == 0) 33 | // section .loc_sec (originaly .progmem0) will be used for localized translated strings 34 | #define PROGMEM_I2 __attribute__((section(".loc_sec"))) 35 | // section .loc_pri (originaly .progmem1) will be used for localized strings in english 36 | #define PROGMEM_I1 __attribute__((section(".loc_pri"))) 37 | // section .noloc (originaly progmem2) will be used for not localized strings in english 38 | #define PROGMEM_N1 __attribute__((section(".noloc"))) 39 | #define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = "\xff\xff" s; &__c[0];})) 40 | #define ISTR(s) "\xff\xff" s 41 | #define _i(s) lang_get_translation(_I(s)) 42 | #define _T(s) lang_get_translation(s) 43 | #endif //(LANG_MODE == 0) 44 | #define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];})) 45 | #define _n(s) _N(s) 46 | 47 | /** @brief lang_table_header_t structure - (size= 16byte) */ 48 | typedef struct 49 | { 50 | uint32_t magic; //+0 51 | uint16_t size; //+4 52 | uint16_t count; //+6 53 | uint16_t checksum; //+8 54 | uint16_t code; //+10 55 | uint32_t signature; //+12 56 | } lang_table_header_t; 57 | 58 | /** @brief lang_table_t structure - (size= 16byte + 2*count) */ 59 | typedef struct 60 | { 61 | lang_table_header_t header; 62 | uint16_t table[]; 63 | } lang_table_t; 64 | 65 | /** @name Language indices into their particular symbol tables.*/ 66 | ///@{ 67 | #define LANG_ID_PRI 0 68 | #define LANG_ID_SEC 1 69 | ///@} 70 | 71 | /** @def LANG_ID_FORCE_SELECTION 72 | * @brief Language is not defined and it shall be selected from the menu.*/ 73 | #define LANG_ID_FORCE_SELECTION 254 74 | 75 | /** @def LANG_ID_UNDEFINED 76 | * @brief Language is not defined on a virgin RAMBo board. */ 77 | #define LANG_ID_UNDEFINED 255 78 | 79 | /** @def LANG_ID_DEFAULT 80 | * @brief Default language ID, if no language is selected. */ 81 | #define LANG_ID_DEFAULT LANG_ID_PRI 82 | 83 | /** @def LANG_MAGIC 84 | * @brief Magic number at begin of lang table. */ 85 | #define LANG_MAGIC 0x4bb45aa5 86 | 87 | /** @name Language codes (ISO639-1)*/ 88 | ///@{ 89 | #define LANG_CODE_XX 0x3f3f //!<'??' 90 | #define LANG_CODE_EN 0x656e //!<'en' 91 | #define LANG_CODE_CZ 0x6373 //!<'cs' 92 | #define LANG_CODE_DE 0x6465 //!<'de' 93 | #define LANG_CODE_ES 0x6573 //!<'es' 94 | #define LANG_CODE_FR 0x6672 //!<'fr' 95 | #define LANG_CODE_IT 0x6974 //!<'it' 96 | #define LANG_CODE_PL 0x706c //!<'pl' 97 | #ifdef COMMUNITY_LANG_SUPPORT //Community language support 98 | #ifdef COMMUNITY_LANG_NL 99 | #define LANG_CODE_NL 0x6e6c //!<'nl' 100 | #endif // COMMUNITY_LANG_NL 101 | //Use the 3 lines below as a template and replace 'QR', '0X7172' and 'qr' 102 | //#ifdef COMMUNITY_LANG_QR 103 | //#define LANG_CODE_QR 0x7172 //!<'qr' 104 | //#endif // COMMUNITY_LANG_QR 105 | #endif // COMMUNITY_LANG_SUPPORT 106 | ///@} 107 | 108 | #if defined(__cplusplus) 109 | extern "C" { 110 | #endif //defined(__cplusplus) 111 | 112 | /** @brief Currectly active language selection.*/ 113 | extern uint8_t lang_selected; 114 | 115 | #if (LANG_MODE != 0) 116 | extern const char _SEC_LANG[LANG_SIZE_RESERVED]; 117 | extern const char* lang_get_translation(const char* s); 118 | /** @def _SEC_LANG_TABLE 119 | * @brief Align table to start of 256 byte page */ 120 | #define _SEC_LANG_TABLE ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00) 121 | #endif //(LANG_MODE != 0) 122 | 123 | /** @brief selects language, eeprom is updated in case of success */ 124 | extern uint8_t lang_select(uint8_t lang); 125 | /** @brief performs checksum test of secondary language data */ 126 | extern uint8_t lang_check(uint16_t addr); 127 | /** @return total number of languages (primary + all in xflash) */ 128 | extern uint8_t lang_get_count(void); 129 | /** @brief reads lang table header and offset in xflash or progmem */ 130 | extern uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset); 131 | /** @brief reads lang code from xflash or progmem */ 132 | extern uint16_t lang_get_code(uint8_t lang); 133 | /** @return localized language name (text for menu item) */ 134 | extern const char* lang_get_name_by_code(uint16_t code); 135 | /** @brief reset language to "LANG_ID_FORCE_SELECTION", epprom is updated */ 136 | extern void lang_reset(void); 137 | /** @retval 1 language is selected */ 138 | extern uint8_t lang_is_selected(void); 139 | 140 | #ifdef DEBUG_SEC_LANG 141 | extern const char* lang_get_sec_lang_str_by_id(uint16_t id); 142 | extern uint16_t lang_print_sec_lang(FILE* out); 143 | #endif //DEBUG_SEC_LANG 144 | 145 | extern void lang_boot_update_start(uint8_t lang); 146 | 147 | #if defined(__cplusplus) 148 | } 149 | #endif //defined(__cplusplus) 150 | 151 | #define CAT2(_s1, _s2) _s1 152 | #define CAT4(_s1, _s2, _s3, _s4) _s1 153 | 154 | #include "messages.h" 155 | 156 | 157 | #endif //LANGUAGE_H 158 | 159 | -------------------------------------------------------------------------------- /src/sound.cpp: -------------------------------------------------------------------------------- 1 | #include "sound.h" 2 | 3 | #include "Marlin.h" 4 | 5 | //#include 6 | //#include 7 | //#include "eeprom.h" 8 | #include "backlight.h" 9 | 10 | 11 | //eSOUND_MODE eSoundMode=e_SOUND_MODE_LOUD; 12 | // nema vyznam, pokud se bude volat Sound_Init (tzn. poc. hodnota je v EEPROM) 13 | // !?! eSOUND_MODE eSoundMode; v ultraldc.cpp :: cd_settings_menu() se takto jevi jako lokalni promenna 14 | eSOUND_MODE eSoundMode; //=e_SOUND_MODE_DEFAULT; 15 | 16 | 17 | static void Sound_SaveMode(void); 18 | static void Sound_DoSound_Echo(void); 19 | static void Sound_DoSound_Prompt(void); 20 | static void Sound_DoSound_Alert(bool bOnce); 21 | static void Sound_DoSound_Encoder_Move(void); 22 | static void Sound_DoSound_Blind_Alert(void); 23 | 24 | void Sound_Init(void) 25 | { 26 | SET_OUTPUT(BEEPER); 27 | eSoundMode=(eSOUND_MODE)eeprom_read_byte((uint8_t*)EEPROM_SOUND_MODE); 28 | if(eSoundMode==e_SOUND_MODE_NULL) 29 | Sound_Default(); // je potreba provest i ulozeni do EEPROM 30 | } 31 | 32 | void Sound_Default(void) 33 | { 34 | eSoundMode=e_SOUND_MODE_DEFAULT; 35 | Sound_SaveMode(); 36 | } 37 | 38 | void Sound_SaveMode(void) 39 | { 40 | eeprom_update_byte((uint8_t*)EEPROM_SOUND_MODE,(uint8_t)eSoundMode); 41 | } 42 | 43 | void Sound_CycleState(void) 44 | { 45 | switch(eSoundMode) 46 | { 47 | case e_SOUND_MODE_LOUD: 48 | eSoundMode=e_SOUND_MODE_ONCE; 49 | break; 50 | case e_SOUND_MODE_ONCE: 51 | eSoundMode=e_SOUND_MODE_SILENT; 52 | break; 53 | case e_SOUND_MODE_SILENT: 54 | eSoundMode=e_SOUND_MODE_BLIND; 55 | break; 56 | case e_SOUND_MODE_BLIND: 57 | eSoundMode=e_SOUND_MODE_LOUD; 58 | break; 59 | default: 60 | eSoundMode=e_SOUND_MODE_LOUD; 61 | } 62 | Sound_SaveMode(); 63 | } 64 | 65 | //if critical is true then silend and once mode is ignored 66 | void Sound_MakeCustom(uint16_t ms,uint16_t tone_,bool critical){ 67 | backlight_wake(); 68 | if (!critical){ 69 | if (eSoundMode != e_SOUND_MODE_SILENT){ 70 | if(!tone_){ 71 | WRITE(BEEPER, HIGH); 72 | _delay(ms); 73 | WRITE(BEEPER, LOW); 74 | } 75 | else{ 76 | _tone(BEEPER, tone_); 77 | _delay(ms); 78 | _noTone(BEEPER); 79 | } 80 | } 81 | } 82 | else{ 83 | if(!tone_){ 84 | WRITE(BEEPER, HIGH); 85 | _delay(ms); 86 | WRITE(BEEPER, LOW); 87 | _delay(ms); 88 | } 89 | else{ 90 | _tone(BEEPER, tone_); 91 | _delay(ms); 92 | _noTone(BEEPER); 93 | } 94 | } 95 | } 96 | 97 | void Sound_MakeSound(eSOUND_TYPE eSoundType) 98 | { 99 | switch(eSoundMode) 100 | { 101 | case e_SOUND_MODE_LOUD: 102 | if(eSoundType==e_SOUND_TYPE_ButtonEcho) 103 | Sound_DoSound_Echo(); 104 | if(eSoundType==e_SOUND_TYPE_StandardPrompt) 105 | Sound_DoSound_Prompt(); 106 | if(eSoundType==e_SOUND_TYPE_StandardAlert) 107 | Sound_DoSound_Alert(false); 108 | break; 109 | case e_SOUND_MODE_ONCE: 110 | if(eSoundType==e_SOUND_TYPE_ButtonEcho) 111 | Sound_DoSound_Echo(); 112 | if(eSoundType==e_SOUND_TYPE_StandardPrompt) 113 | Sound_DoSound_Prompt(); 114 | if(eSoundType==e_SOUND_TYPE_StandardAlert) 115 | Sound_DoSound_Alert(true); 116 | break; 117 | case e_SOUND_MODE_SILENT: 118 | if(eSoundType==e_SOUND_TYPE_StandardAlert) 119 | Sound_DoSound_Alert(true); 120 | break; 121 | case e_SOUND_MODE_BLIND: 122 | if(eSoundType==e_SOUND_TYPE_ButtonEcho) 123 | Sound_DoSound_Echo(); 124 | if(eSoundType==e_SOUND_TYPE_StandardPrompt) 125 | Sound_DoSound_Prompt(); 126 | if(eSoundType==e_SOUND_TYPE_StandardAlert) 127 | Sound_DoSound_Alert(false); 128 | if(eSoundType==e_SOUND_TYPE_EncoderMove) 129 | Sound_DoSound_Encoder_Move(); 130 | if(eSoundType==e_SOUND_TYPE_BlindAlert) 131 | Sound_DoSound_Blind_Alert(); 132 | break; 133 | default: 134 | break; 135 | } 136 | } 137 | 138 | static void Sound_DoSound_Blind_Alert(void) 139 | { 140 | backlight_wake(1); 141 | uint8_t nI; 142 | 143 | for(nI=0; nI<20; nI++) 144 | { 145 | WRITE(BEEPER,HIGH); 146 | delayMicroseconds(94); 147 | WRITE(BEEPER,LOW); 148 | delayMicroseconds(94); 149 | } 150 | } 151 | 152 | static void Sound_DoSound_Encoder_Move(void) 153 | { 154 | backlight_wake(); 155 | uint8_t nI; 156 | 157 | for(nI=0;nI<5;nI++) 158 | { 159 | WRITE(BEEPER,HIGH); 160 | delayMicroseconds(75); 161 | WRITE(BEEPER,LOW); 162 | delayMicroseconds(75); 163 | } 164 | } 165 | 166 | static void Sound_DoSound_Echo(void) 167 | { 168 | backlight_wake(); 169 | uint8_t nI; 170 | 171 | for(nI=0;nI<10;nI++) 172 | { 173 | WRITE(BEEPER,HIGH); 174 | delayMicroseconds(100); 175 | WRITE(BEEPER,LOW); 176 | delayMicroseconds(100); 177 | } 178 | } 179 | 180 | static void Sound_DoSound_Prompt(void) 181 | { 182 | backlight_wake(2); 183 | WRITE(BEEPER,HIGH); 184 | _delay_ms(500); 185 | WRITE(BEEPER,LOW); 186 | } 187 | 188 | static void Sound_DoSound_Alert(bool bOnce) 189 | { 190 | backlight_wake(); 191 | uint8_t nI,nMax; 192 | 193 | nMax=bOnce?1:3; 194 | for(nI=0;nI=filesize; } 75 | FORCE_INLINE int16_t getFilteredGcodeChar() 76 | { 77 | int16_t c = (int16_t)file.readFilteredGcode(); 78 | sdpos = file.curPosition(); 79 | return c; 80 | }; 81 | void setIndex(long index) {sdpos = index;file.seekSetFilteredGcode(index);}; 82 | FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;}; 83 | FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;}; 84 | FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); }; 85 | 86 | bool ToshibaFlashAir_isEnabled() const { return card.getFlashAirCompatible(); } 87 | void ToshibaFlashAir_enable(bool enable) { card.setFlashAirCompatible(enable); } 88 | bool ToshibaFlashAir_GetIP(uint8_t *ip); 89 | 90 | public: 91 | bool saving; 92 | bool logging; 93 | bool sdprinting ; 94 | bool cardOK ; 95 | char filename[13]; 96 | // There are scenarios when simple modification time is not enough (on MS Windows) 97 | // Therefore these timestamps hold the most recent one of creation/modification date/times 98 | uint16_t crmodTime, crmodDate; 99 | uint32_t /* cluster, */ position; 100 | char longFilename[LONG_FILENAME_LENGTH]; 101 | bool filenameIsDir; 102 | int lastnr; //last number of the autostart; 103 | #ifdef SDCARD_SORT_ALPHA 104 | bool presort_flag; 105 | char dir_names[MAX_DIR_DEPTH][9]; 106 | #endif // SDCARD_SORT_ALPHA 107 | private: 108 | SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH]; 109 | uint16_t workDirDepth; 110 | 111 | // Sort files and folders alphabetically. 112 | #ifdef SDCARD_SORT_ALPHA 113 | uint16_t sort_count; // Count of sorted items in the current directory 114 | uint32_t sort_positions[SDSORT_LIMIT]; 115 | 116 | #endif // SDCARD_SORT_ALPHA 117 | 118 | #ifdef DEBUG_SD_SPEED_TEST 119 | public: 120 | #endif //DEBUG_SD_SPEED_TEST 121 | Sd2Card card; 122 | 123 | private: 124 | SdVolume volume; 125 | SdFile file; 126 | #define SD_PROCEDURE_DEPTH 1 127 | #define MAXPATHNAMELENGTH (13*MAX_DIR_DEPTH+MAX_DIR_DEPTH+1) 128 | uint8_t file_subcall_ctr; 129 | uint32_t filespos[SD_PROCEDURE_DEPTH]; 130 | char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH]; 131 | uint32_t filesize; 132 | //int16_t n; 133 | unsigned long autostart_atmillis; 134 | uint32_t sdpos ; 135 | 136 | bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware. 137 | 138 | uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory. 139 | char* diveDirName; 140 | 141 | bool diveSubfolder (const char *&fileName); 142 | void lsDive(const char *prepend, SdFile parent, const char * const match=NULL, LsAction lsAction = LS_GetFilename, ls_param lsParams = ls_param()); 143 | #ifdef SDCARD_SORT_ALPHA 144 | void flush_presort(); 145 | #endif 146 | }; 147 | extern bool Stopped; 148 | extern CardReader card; 149 | #define IS_SD_PRINTING (card.sdprinting) 150 | 151 | #if (SDCARDDETECT > -1) 152 | # ifdef SDCARDDETECTINVERTED 153 | # define IS_SD_INSERTED (READ(SDCARDDETECT)!=0) 154 | # else 155 | # define IS_SD_INSERTED (READ(SDCARDDETECT)==0) 156 | # endif //SDCARDTETECTINVERTED 157 | #else 158 | //If we don't have a card detect line, aways asume the card is inserted 159 | # define IS_SD_INSERTED true 160 | #endif 161 | 162 | #else 163 | 164 | #define IS_SD_PRINTING (false) 165 | 166 | #endif //SDSUPPORT 167 | #endif 168 | -------------------------------------------------------------------------------- /src/xflash.c: -------------------------------------------------------------------------------- 1 | //xflash.c 2 | 3 | #include "xflash.h" 4 | #include 5 | #include 6 | #include "spi.h" 7 | #include "fastio.h" 8 | 9 | #ifdef XFLASH 10 | 11 | #define _MFRID_W25X20CL 0xEF 12 | #define _DEVID_W25X20CL 0x11 13 | 14 | #define _MFRID_GD25Q20C 0xC8 15 | #define _DEVID_GD25Q20C 0x11 16 | 17 | #define _CMD_ENABLE_WR 0x06 18 | #define _CMD_ENABLE_WR_VSR 0x50 19 | #define _CMD_DISABLE_WR 0x04 20 | #define _CMD_RD_STATUS_REG 0x05 21 | #define _CMD_WR_STATUS_REG 0x01 22 | #define _CMD_RD_DATA 0x03 23 | #define _CMD_RD_FAST 0x0b 24 | #define _CMD_RD_FAST_D_O 0x3b 25 | #define _CMD_RD_FAST_D_IO 0xbb 26 | #define _CMD_PAGE_PROGRAM 0x02 27 | #define _CMD_SECTOR_ERASE 0x20 28 | #define _CMD_BLOCK32_ERASE 0x52 29 | #define _CMD_BLOCK64_ERASE 0xd8 30 | #define _CMD_CHIP_ERASE 0xc7 31 | #define _CMD_CHIP_ERASE2 0x60 32 | #define _CMD_PWR_DOWN 0xb9 33 | #define _CMD_PWR_DOWN_REL 0xab 34 | #define _CMD_MFRID_DEVID 0x90 35 | #define _CMD_MFRID_DEVID_D 0x92 36 | #define _CMD_JEDEC_ID 0x9f 37 | #define _CMD_RD_UID 0x4b 38 | 39 | #define _CS_LOW() WRITE(XFLASH_PIN_CS, 0) 40 | #define _CS_HIGH() WRITE(XFLASH_PIN_CS, 1) 41 | 42 | //#define _SPI_TX swspi_tx 43 | //#define _SPI_RX swspi_rx 44 | #define _SPI_TX(b) spi_txrx(b) 45 | #define _SPI_RX() spi_txrx(0xff) 46 | 47 | 48 | int xflash_mfrid_devid(void); 49 | 50 | 51 | int8_t xflash_init(void) 52 | { 53 | _CS_HIGH(); 54 | SET_OUTPUT(XFLASH_PIN_CS); 55 | XFLASH_SPI_ENTER(); 56 | if (!xflash_mfrid_devid()) return 0; 57 | return 1; 58 | } 59 | 60 | void xflash_enable_wr(void) 61 | { 62 | _CS_LOW(); 63 | _SPI_TX(_CMD_ENABLE_WR); // send command 0x06 64 | _CS_HIGH(); 65 | } 66 | 67 | void xflash_disable_wr(void) 68 | { 69 | _CS_LOW(); 70 | _SPI_TX(_CMD_DISABLE_WR); // send command 0x04 71 | _CS_HIGH(); 72 | } 73 | 74 | uint8_t xflash_rd_status_reg(void) 75 | { 76 | _CS_LOW(); 77 | _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90 78 | uint8_t val = _SPI_RX(); // receive value 79 | _CS_HIGH(); 80 | return val; 81 | } 82 | 83 | #if 0 84 | void w25x20cl_wr_status_reg(uint8_t val) 85 | { 86 | _CS_LOW(); 87 | _SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90 88 | _SPI_TX(val); // send value 89 | _CS_HIGH(); 90 | } 91 | #endif 92 | 93 | static void xflash_send_cmdaddr(uint8_t cmd, uint32_t addr) 94 | { 95 | _SPI_TX(cmd); // send command 0x03 96 | _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 97 | _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 98 | _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 99 | } 100 | 101 | void xflash_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) 102 | { 103 | _CS_LOW(); 104 | xflash_send_cmdaddr(_CMD_RD_DATA, addr); 105 | while (cnt--) // receive data 106 | *(data++) = _SPI_RX(); 107 | _CS_HIGH(); 108 | } 109 | 110 | void xflash_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) 111 | { 112 | _CS_LOW(); 113 | xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); 114 | while (cnt--) // send data 115 | _SPI_TX(*(data++)); 116 | _CS_HIGH(); 117 | } 118 | 119 | void xflash_multipage_program(uint32_t addr, uint8_t* data, uint16_t cnt) 120 | { 121 | while(cnt) 122 | { 123 | xflash_enable_wr(); 124 | _CS_LOW(); 125 | xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); 126 | while(1) 127 | { 128 | // send data 129 | _SPI_TX(*(data++)); 130 | if(!--cnt || !(++addr & 0xFF)) 131 | { 132 | // on a page boundary or end of write 133 | _CS_HIGH(); 134 | xflash_wait_busy(); 135 | break; 136 | } 137 | } 138 | } 139 | } 140 | 141 | void xflash_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) 142 | { 143 | _CS_LOW(); 144 | xflash_send_cmdaddr(_CMD_PAGE_PROGRAM, addr); 145 | while (cnt--) // send data 146 | _SPI_TX(pgm_read_byte(data++)); 147 | _CS_HIGH(); 148 | } 149 | 150 | void xflash_erase(uint8_t cmd, uint32_t addr) 151 | { 152 | _CS_LOW(); 153 | xflash_send_cmdaddr(cmd, addr); 154 | _CS_HIGH(); 155 | } 156 | 157 | void xflash_sector_erase(uint32_t addr) 158 | { 159 | return xflash_erase(_CMD_SECTOR_ERASE, addr); 160 | } 161 | 162 | void xflash_block32_erase(uint32_t addr) 163 | { 164 | return xflash_erase(_CMD_BLOCK32_ERASE, addr); 165 | } 166 | 167 | void xflash_block64_erase(uint32_t addr) 168 | { 169 | return xflash_erase(_CMD_BLOCK64_ERASE, addr); 170 | } 171 | 172 | void xflash_chip_erase(void) 173 | { 174 | _CS_LOW(); 175 | _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7 176 | _CS_HIGH(); 177 | } 178 | 179 | 180 | void xflash_rd_uid(uint8_t* uid) 181 | { 182 | _CS_LOW(); 183 | _SPI_TX(_CMD_RD_UID); // send command 0x4b 184 | uint8_t cnt = 4; // 4 dummy bytes 185 | while (cnt--) // transmit dummy bytes 186 | _SPI_TX(0x00); 187 | cnt = 8; // 8 bytes UID 188 | while (cnt--) // receive UID 189 | uid[7 - cnt] = _SPI_RX(); 190 | _CS_HIGH(); 191 | } 192 | 193 | int xflash_mfrid_devid(void) 194 | { 195 | _CS_LOW(); 196 | _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90 197 | uint8_t cnt = 3; // 3 address bytes 198 | while (cnt--) // send address bytes 199 | _SPI_TX(0x00); 200 | uint8_t xflash_mfrid = _SPI_RX(); // receive mfrid 201 | uint8_t xflash_devid = _SPI_RX(); // receive devid 202 | _CS_HIGH(); 203 | return 204 | ((xflash_mfrid == _MFRID_W25X20CL) && (xflash_devid == _DEVID_W25X20CL)) || 205 | ((xflash_mfrid == _MFRID_GD25Q20C) && (xflash_devid == _DEVID_GD25Q20C)); 206 | } 207 | 208 | void xflash_wait_busy(void) 209 | { 210 | while (xflash_rd_status_reg() & XFLASH_STATUS_BUSY) ; 211 | } 212 | 213 | #endif //XFLASH 214 | -------------------------------------------------------------------------------- /src/menu.h: -------------------------------------------------------------------------------- 1 | //menu.h 2 | #ifndef _MENU_H 3 | #define _MENU_H 4 | 5 | #include 6 | #include "eeprom.h" 7 | 8 | #define MENU_DATA_SIZE 32 9 | 10 | //Function pointer to menu functions. 11 | typedef void (*menu_func_t)(void); 12 | 13 | typedef struct 14 | { 15 | menu_func_t menu; 16 | int8_t position; 17 | } menu_record_t; 18 | 19 | typedef struct 20 | { 21 | //Variables used when editing values. 22 | const char* editLabel; 23 | void* editValue; 24 | int32_t minEditValue; 25 | int32_t maxEditValue; 26 | } menu_data_edit_t; 27 | 28 | extern uint8_t menu_data[MENU_DATA_SIZE]; 29 | 30 | extern uint8_t menu_depth; 31 | 32 | //! definition of serious errors possibly blocking the main menu 33 | //! Use them as bit mask, so that the code may set various errors at the same time 34 | enum ESeriousErrors { 35 | SERIOUS_ERR_NONE = 0, 36 | SERIOUS_ERR_MINTEMP_HEATER = 0x01, 37 | SERIOUS_ERR_MINTEMP_BED = 0x02 38 | }; // and possibly others in the future. 39 | 40 | //! this is a flag for disabling entering the main menu. If this is set 41 | //! to anything != 0, the only the main status screen will be shown on the 42 | //! LCD and the user will be prevented from entering the menu. 43 | //! Now used only to block doing anything with the printer when there is 44 | //! the infamous MINTEMP error (SERIOUS_ERR_MINTEMP). 45 | extern uint8_t menu_block_entering_on_serious_errors; 46 | 47 | //! a pair of macros for manipulating the serious errors 48 | //! a c++ class would have been better 49 | #define menu_set_serious_error(x) menu_block_entering_on_serious_errors |= x; 50 | #define menu_unset_serious_error(x) menu_block_entering_on_serious_errors &= ~x; 51 | #define menu_is_serious_error(x) (menu_block_entering_on_serious_errors & x) != 0 52 | 53 | extern uint8_t menu_line; 54 | extern uint8_t menu_item; 55 | extern uint8_t menu_row; 56 | 57 | //scroll offset in the current menu 58 | extern uint8_t menu_top; 59 | 60 | extern uint8_t menu_clicked; 61 | 62 | extern uint8_t menu_leaving; 63 | 64 | //function pointer to the currently active menu 65 | extern menu_func_t menu_menu; 66 | 67 | extern void menu_data_reset(void); 68 | 69 | extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state); 70 | 71 | #define MENU_BEGIN() menu_start(); for(menu_row = 0; menu_row < LCD_HEIGHT; menu_row++, menu_line++) { menu_item = 0; 72 | void menu_start(void); 73 | 74 | #define MENU_END() menu_end(); } 75 | extern void menu_end(void); 76 | 77 | extern void menu_back(void); 78 | extern void menu_back_no_reset(void); 79 | extern void menu_back(uint8_t nLevel); 80 | 81 | extern void menu_back_if_clicked(void); 82 | 83 | extern void menu_back_if_clicked_fb(void); 84 | 85 | extern void menu_submenu(menu_func_t submenu); 86 | extern void menu_submenu_no_reset(menu_func_t submenu); 87 | 88 | extern uint8_t menu_item_ret(void); 89 | 90 | //extern int menu_draw_item_printf_P(char type_char, const char* format, ...); 91 | 92 | 93 | //int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, ); 94 | 95 | #define MENU_ITEM_DUMMY() menu_item_dummy() 96 | extern void menu_item_dummy(void); 97 | 98 | #define MENU_ITEM_TEXT_P(str) do { if (menu_item_text_P(str)) return; } while (0) 99 | extern uint8_t menu_item_text_P(const char* str); 100 | 101 | #define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0) 102 | extern uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu); 103 | 104 | #define MENU_ITEM_SUBMENU_E(sheet, submenu) do { if (menu_item_submenu_E(sheet, submenu)) return; } while (0) 105 | extern uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu); 106 | 107 | #define MENU_ITEM_FUNCTION_E(sheet, submenu) do { if (menu_item_function_E(sheet, submenu)) return; } while (0) 108 | extern uint8_t menu_item_function_E(const Sheet &sheet, menu_func_t func); 109 | 110 | #define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0) 111 | extern uint8_t menu_item_back_P(const char* str); 112 | 113 | // leaving menu - this condition must be immediately before MENU_ITEM_BACK_P 114 | #define ON_MENU_LEAVE(func) do { if (menu_item_leave()){ func } } while (0) 115 | extern bool menu_item_leave(); 116 | 117 | #define MENU_ITEM_FUNCTION_P(str, func) do { if (menu_item_function_P(str, func)) return; } while (0) 118 | extern uint8_t menu_item_function_P(const char* str, menu_func_t func); 119 | 120 | #define MENU_ITEM_FUNCTION_NR_P(str, number, func, fn_par) do { if (menu_item_function_P(str, number, func, fn_par)) return; } while (0) 121 | extern uint8_t menu_item_function_P(const char* str, char number, void (*func)(uint8_t), uint8_t fn_par); 122 | 123 | #define MENU_ITEM_TOGGLE_P(str, toggle, func) do { if (menu_item_toggle_P(str, toggle, func, 0x02)) return; } while (0) 124 | #define MENU_ITEM_TOGGLE(str, toggle, func) do { if (menu_item_toggle_P(str, toggle, func, 0x00)) return; } while (0) 125 | extern uint8_t menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, const uint8_t settings); 126 | 127 | #define MENU_ITEM_GCODE_P(str, str_gcode) do { if (menu_item_gcode_P(str, str_gcode)) return; } while (0) 128 | extern uint8_t menu_item_gcode_P(const char* str, const char* str_gcode); 129 | 130 | 131 | extern const char menu_fmt_int3[]; 132 | 133 | extern const char menu_fmt_float31[]; 134 | extern const char menu_fmt_float13[]; 135 | 136 | extern void menu_draw_float31(const char* str, float val); 137 | 138 | extern void menu_draw_float13(const char* str, float val); 139 | 140 | struct SheetFormatBuffer 141 | { 142 | char c[19]; 143 | }; 144 | 145 | extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer); 146 | 147 | 148 | #define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_P(str, pval, minval, maxval)) return; } while (0) 149 | //#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) MENU_ITEM_EDIT(int3, str, pval, minval, maxval) 150 | template 151 | extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val); 152 | 153 | extern void menu_progressbar_init(uint16_t total, const char* title); 154 | extern void menu_progressbar_update(uint16_t newVal); 155 | extern void menu_progressbar_finish(void); 156 | 157 | #endif //_MENU_H 158 | -------------------------------------------------------------------------------- /src/Servo.h: -------------------------------------------------------------------------------- 1 | /* 2 | Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2 3 | Copyright (c) 2009 Michael Margolis. All right reserved. 4 | 5 | This library is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU Lesser General Public 7 | License as published by the Free Software Foundation; either 8 | version 2.1 of the License, or (at your option) any later version. 9 | 10 | This library is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | Lesser General Public License for more details. 14 | 15 | You should have received a copy of the GNU Lesser General Public 16 | License along with this library; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 | */ 19 | 20 | /* 21 | 22 | A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method. 23 | The servos are pulsed in the background using the value most recently written using the write() method 24 | 25 | Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached. 26 | Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four. 27 | The sequence used to seize timers is defined in timers.h 28 | 29 | The methods are: 30 | 31 | Servo - Class for manipulating servo motors connected to Arduino pins. 32 | 33 | attach(pin ) - Attaches a servo motor to an i/o pin. 34 | attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds 35 | default min is 544, max is 2400 36 | 37 | write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds) 38 | writeMicroseconds() - Sets the servo pulse width in microseconds 39 | read() - Gets the last written servo pulse width as an angle between 0 and 180. 40 | readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release) 41 | attached() - Returns true if there is a servo attached. 42 | detach() - Stops an attached servos from pulsing its i/o pin. 43 | */ 44 | 45 | #ifndef Servo_h 46 | #define Servo_h 47 | 48 | #include 49 | 50 | /* 51 | * Defines for 16 bit timers used with Servo library 52 | * 53 | * If _useTimerX is defined then TimerX is a 16 bit timer on the current board 54 | * timer16_Sequence_t enumerates the sequence that the timers should be allocated 55 | * _Nbr_16timers indicates how many 16 bit timers are available. 56 | * 57 | */ 58 | 59 | // Say which 16 bit timers can be used and in what order 60 | #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) 61 | #define _useTimer5 62 | //#define _useTimer1 63 | #define _useTimer3 64 | //#define _useTimer4 65 | //typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ; 66 | typedef enum { _timer5, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ; 67 | 68 | #elif defined(__AVR_ATmega32U4__) 69 | //#define _useTimer1 70 | #define _useTimer3 71 | //typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ; 72 | typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ; 73 | 74 | #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) 75 | #define _useTimer3 76 | //#define _useTimer1 77 | //typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ; 78 | typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ; 79 | 80 | #elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) ||defined(__AVR_ATmega2561__) 81 | #define _useTimer3 82 | //#define _useTimer1 83 | //typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ; 84 | typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ; 85 | 86 | #else // everything else 87 | //#define _useTimer1 88 | //typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ; 89 | typedef enum { _Nbr_16timers } timer16_Sequence_t ; 90 | #endif 91 | 92 | #define Servo_VERSION 2 // software version of this library 93 | 94 | #define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo 95 | #define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo 96 | #define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached 97 | #define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds 98 | 99 | #define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer 100 | #define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER) 101 | 102 | #define INVALID_SERVO 255 // flag indicating an invalid servo index 103 | 104 | typedef struct { 105 | uint8_t nbr :6 ; // a pin number from 0 to 63 106 | uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false 107 | } ServoPin_t ; 108 | 109 | typedef struct { 110 | ServoPin_t Pin; 111 | unsigned int ticks; 112 | } servo_t; 113 | 114 | class Servo 115 | { 116 | public: 117 | Servo(); 118 | uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure 119 | uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes. 120 | void detach(); 121 | void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds 122 | void writeMicroseconds(int value); // Write pulse width in microseconds 123 | int read(); // returns current pulse width as an angle between 0 and 180 degrees 124 | int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release) 125 | bool attached(); // return true if this servo is attached, otherwise false 126 | #if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0) 127 | int pin; // store the hardware pin of the servo 128 | #endif 129 | private: 130 | uint8_t servoIndex; // index into the channel data for this servo 131 | int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH 132 | int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH 133 | }; 134 | 135 | #endif -------------------------------------------------------------------------------- /src/eeprom.cpp: -------------------------------------------------------------------------------- 1 | //! @file 2 | //! @date Jun 20, 2019 3 | //! @author Marek Běl 4 | 5 | #include "eeprom.h" 6 | #include "Marlin.h" 7 | 8 | #include 9 | #include 10 | 11 | 12 | #include "language.h" 13 | 14 | #if 0 15 | template 16 | static T eeprom_read(T *address); 17 | 18 | template<> 19 | char eeprom_read(char *address) 20 | { 21 | return eeprom_read_byte(reinterpret_cast(address)); 22 | } 23 | #endif 24 | 25 | template 26 | static void eeprom_write(T *address, T value); 27 | 28 | template<> 29 | void eeprom_write(char *addres, char value) 30 | { 31 | eeprom_write_byte(reinterpret_cast(addres), static_cast(value)); 32 | } 33 | 34 | 35 | template 36 | static bool eeprom_is_uninitialized(T *address); 37 | 38 | template <> 39 | bool eeprom_is_uninitialized(char *address) 40 | { 41 | return (0xff == eeprom_read_byte(reinterpret_cast(address))); 42 | } 43 | 44 | bool eeprom_is_sheet_initialized(uint8_t sheet_num) 45 | { 46 | return (0xffff != eeprom_read_word(reinterpret_cast(&(EEPROM_Sheets_base-> 47 | s[sheet_num].z_offset)))); 48 | } 49 | 50 | void eeprom_init() 51 | { 52 | if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0); 53 | if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0); 54 | if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0); 55 | if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0); 56 | if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0); 57 | if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0); 58 | if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0); 59 | if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0); 60 | 61 | if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0); 62 | if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0); 63 | if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0); 64 | if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0); 65 | if (eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)) == EEPROM_EMPTY_VALUE) 66 | { 67 | eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), 0); 68 | // When upgrading from version older version (before multiple sheets were implemented in v3.8.0) 69 | // Sheet 1 uses the previous Live adjust Z (@EEPROM_BABYSTEP_Z) 70 | int last_babystep = eeprom_read_word((uint16_t *)EEPROM_BABYSTEP_Z); 71 | eeprom_update_word(reinterpret_cast(&(EEPROM_Sheets_base->s[0].z_offset)), last_babystep); 72 | } 73 | 74 | for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); ++i) 75 | { 76 | bool is_uninitialized = true; 77 | for (uint_least8_t j = 0; j < (sizeof(Sheet::name)/sizeof(Sheet::name[0])); ++j) 78 | { 79 | if (!eeprom_is_uninitialized(&(EEPROM_Sheets_base->s[i].name[j]))) is_uninitialized = false; 80 | } 81 | if(is_uninitialized) 82 | { 83 | SheetName sheetName; 84 | eeprom_default_sheet_name(i,sheetName); 85 | 86 | for (uint_least8_t a = 0; a < sizeof(Sheet::name); ++a){ 87 | eeprom_write(&(EEPROM_Sheets_base->s[i].name[a]), sheetName.c[a]); 88 | } 89 | } 90 | } 91 | if(!eeprom_is_sheet_initialized(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))) 92 | { 93 | eeprom_switch_to_next_sheet(); 94 | } 95 | check_babystep(); 96 | 97 | #ifdef PINDA_TEMP_COMP 98 | if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_PINDA_TEMP_COMPENSATION, 0); 99 | #endif //PINDA_TEMP_COMP 100 | 101 | if (eeprom_read_dword((uint32_t*)EEPROM_JOB_ID) == EEPROM_EMPTY_VALUE32) 102 | eeprom_update_dword((uint32_t*)EEPROM_JOB_ID, 0); 103 | } 104 | 105 | //! @brief Get default sheet name for index 106 | //! 107 | //! | index | sheetName | 108 | //! | ----- | --------- | 109 | //! | 0 | Smooth1 | 110 | //! | 1 | Smooth2 | 111 | //! | 2 | Textur1 | 112 | //! | 3 | Textur2 | 113 | //! | 4 | Satin 1 | 114 | //! | 5 | Satin 2 | 115 | //! | 6 | Custom1 | 116 | //! | 7 | Custom2 | 117 | //! 118 | //! @param[in] index 119 | //! @param[out] sheetName 120 | void eeprom_default_sheet_name(uint8_t index, SheetName &sheetName) 121 | { 122 | static_assert(8 == sizeof(SheetName),"Default sheet name needs to be adjusted."); 123 | 124 | if (index < 2) 125 | { 126 | strcpy_P(sheetName.c, PSTR("Smooth")); 127 | } 128 | else if (index < 4) 129 | { 130 | strcpy_P(sheetName.c, PSTR("Textur")); 131 | } 132 | else if (index < 6) 133 | { 134 | strcpy_P(sheetName.c, PSTR("Satin ")); 135 | } 136 | else 137 | { 138 | strcpy_P(sheetName.c, PSTR("Custom")); 139 | } 140 | 141 | sheetName.c[6] = '0' + ((index % 2)+1); 142 | sheetName.c[7] = '\0'; 143 | } 144 | 145 | //! @brief Get next initialized sheet 146 | //! 147 | //! If current sheet is the only sheet initialized, current sheet is returned. 148 | //! 149 | //! @param sheet Current sheet 150 | //! @return next initialized sheet 151 | //! @retval -1 no sheet is initialized 152 | int8_t eeprom_next_initialized_sheet(int8_t sheet) 153 | { 154 | for (int8_t i = 0; i < static_cast(sizeof(Sheets::s)/sizeof(Sheet)); ++i) 155 | { 156 | ++sheet; 157 | if (sheet >= static_cast(sizeof(Sheets::s)/sizeof(Sheet))) sheet = 0; 158 | if (eeprom_is_sheet_initialized(sheet)) return sheet; 159 | } 160 | return -1; 161 | } 162 | 163 | void eeprom_switch_to_next_sheet() 164 | { 165 | int8_t sheet = eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)); 166 | 167 | sheet = eeprom_next_initialized_sheet(sheet); 168 | if (sheet >= 0) eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), sheet); 169 | } 170 | -------------------------------------------------------------------------------- /src/pins_Einsy_1_0.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * EINSY Rambo 1.0a Pin Assignments 3 | ******************************************************************/ 4 | 5 | #define ELECTRONICS "EINSy_10a" 6 | 7 | #define KNOWN_BOARD 8 | #ifndef __AVR_ATmega2560__ 9 | #error Oops! Make sure you have 'Arduino Mega 2560 or Rambo' selected from the 'Tools -> Boards' menu. 10 | #endif 11 | 12 | #define TMC2130 13 | #define UVLO_SUPPORT 14 | 15 | #define AMBIENT_THERMISTOR 16 | #define PINDA_THERMISTOR 17 | 18 | #define XFLASH // external 256kB flash 19 | #define BOOTAPP // bootloader support 20 | 21 | #define XFLASH_PIN_CS 32 22 | 23 | #define X_TMC2130_CS 41 24 | #define X_TMC2130_DIAG 64 // !!! changed from 40 (EINY03) 25 | #define X_STEP_PIN 37 26 | #define X_DIR_PIN 49 27 | #define X_MIN_PIN 12 28 | //#define X_MAX_PIN 30 29 | //#define X_MIN_PIN X_TMC2130_DIAG 30 | #define X_MAX_PIN X_TMC2130_DIAG 31 | #define X_ENABLE_PIN 29 32 | #define X_MS1_PIN -1 33 | #define X_MS2_PIN -1 34 | 35 | #define Y_TMC2130_CS 39 36 | #define Y_TMC2130_DIAG 69 37 | #define Y_STEP_PIN 36 38 | #define Y_DIR_PIN 48 39 | #define Y_MIN_PIN 11 40 | //#define Y_MAX_PIN 24 41 | //#define Y_MIN_PIN Y_TMC2130_DIAG 42 | #define Y_MAX_PIN Y_TMC2130_DIAG 43 | #define Y_ENABLE_PIN 28 44 | #define Y_MS1_PIN -1 45 | #define Y_MS2_PIN -1 46 | 47 | #define Z_TMC2130_CS 67 48 | #define Z_TMC2130_DIAG 68 49 | #define Z_STEP_PIN 35 50 | #define Z_DIR_PIN 47 51 | #define Z_MIN_PIN 10 52 | #define Z_MAX_PIN 23 53 | //#define Z_MAX_PIN Z_TMC2130_DIAG 54 | #define Z_ENABLE_PIN 27 55 | #define Z_MS1_PIN -1 56 | #define Z_MS2_PIN -1 57 | 58 | #define HEATER_BED_PIN 4 //PG5 59 | #define TEMP_BED_PIN 2 //A2 60 | 61 | #define HEATER_0_PIN 3 //PE5 62 | #define TEMP_0_PIN 0 //A0 63 | 64 | #define HEATER_1_PIN -1 65 | #define TEMP_1_PIN 1 //A1 66 | 67 | #define HEATER_2_PIN -1 68 | #define TEMP_2_PIN -1 69 | 70 | #define TEMP_AMBIENT_PIN 6 //A6 71 | 72 | #define TEMP_PINDA_PIN 3 //A3 73 | 74 | // BLTOUCH PINS ON J19 Connector 75 | #define SERVO0_PIN 53 //PB0 76 | #define Z_MIN_PIN_BLT 19 //PD2 77 | 78 | #define VOLT_PWR_PIN 4 //A4 79 | #define VOLT_BED_PIN 9 //A9 80 | #define VOLT_IR_PIN 8 //A8 81 | 82 | 83 | #define E0_TMC2130_CS 66 84 | #define E0_TMC2130_DIAG 65 85 | #define E0_STEP_PIN 34 86 | #define E0_DIR_PIN 43 87 | #define E0_ENABLE_PIN 26 88 | #define E0_MS1_PIN -1 89 | #define E0_MS2_PIN -1 90 | 91 | #define SDPOWER -1 92 | #define SDSS 77 93 | #define LED_PIN 13 94 | #define FAN_PIN 6 95 | #define FAN_1_PIN -1 96 | #define PS_ON_PIN -1 97 | #define KILL_PIN -1 // 80 with Smart Controller LCD 98 | #define SUICIDE_PIN -1 // PIN that has to be turned on right after start, to keep power flowing. 99 | 100 | 101 | //#define KILL_PIN 32 102 | 103 | #define LCD_BL_PIN 5 //backlight control pin 104 | #define BEEPER 84 // Beeper on AUX-4 105 | #define LCD_PINS_RS 82 106 | #define LCD_PINS_ENABLE 61 // !!! changed from 18 (EINY03) 107 | #define LCD_PINS_D4 59 // !!! changed from 19 (EINY03) 108 | #define LCD_PINS_D5 70 109 | #define LCD_PINS_D6 85 110 | #define LCD_PINS_D7 71 111 | 112 | //buttons are directly attached using AUX-2 113 | #define BTN_EN1 72 114 | #define BTN_EN2 14 115 | #define BTN_ENC 9 // the click 116 | 117 | #define SDCARDDETECT 15 118 | 119 | #define TACH_0 79 // !!! changed from 81 (EINY03) 120 | #define TACH_1 80 121 | 122 | #define IR_SENSOR_PIN 62 //idler sensor @PK0 (digital pin 62/A8) 123 | 124 | #define MMU_RST_PIN 76 125 | 126 | // Support for an 8 bit logic analyzer, for example the Saleae. 127 | // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop. 128 | #define LOGIC_ANALYZER_CH0 X_MIN_PIN // PB6 129 | #define LOGIC_ANALYZER_CH1 Y_MIN_PIN // PB5 130 | #define LOGIC_ANALYZER_CH2 53 // PB0 (PROC_nCS) 131 | // Channels 3-7 are slow, they could generate 132 | // 0.889Mhz waveform with a software loop and interrupt locking, 133 | // 1.333MHz waveform without interrupt locking. 134 | #define LOGIC_ANALYZER_CH3 73 // PJ3 135 | // PK0 has no Arduino digital pin assigned, so we set it directly. 136 | #define WRITE_LOGIC_ANALYZER_CH4(value) if (value) PORTK |= (1 << 0); else PORTK &= ~(1 << 0) // PK0 137 | #define LOGIC_ANALYZER_CH5 16 // PH0 (RXD2) 138 | #define LOGIC_ANALYZER_CH6 17 // PH1 (TXD2) 139 | #define LOGIC_ANALYZER_CH7 76 // PJ5 140 | 141 | #define LOGIC_ANALYZER_CH0_ENABLE do { SET_OUTPUT(LOGIC_ANALYZER_CH0); WRITE(LOGIC_ANALYZER_CH0, false); } while (0) 142 | #define LOGIC_ANALYZER_CH1_ENABLE do { SET_OUTPUT(LOGIC_ANALYZER_CH1); WRITE(LOGIC_ANALYZER_CH1, false); } while (0) 143 | #define LOGIC_ANALYZER_CH2_ENABLE do { SET_OUTPUT(LOGIC_ANALYZER_CH2); WRITE(LOGIC_ANALYZER_CH2, false); } while (0) 144 | #define LOGIC_ANALYZER_CH3_ENABLE do { SET_OUTPUT(LOGIC_ANALYZER_CH3); WRITE(LOGIC_ANALYZER_CH3, false); } while (0) 145 | #define LOGIC_ANALYZER_CH4_ENABLE do { DDRK |= 1 << 0; WRITE_LOGIC_ANALYZER_CH4(false); } while (0) 146 | #define LOGIC_ANALYZER_CH5_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH5); WRITE(LOGIC_ANALYZER_CH5, false); } while (0) 147 | #define LOGIC_ANALYZER_CH6_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH6); WRITE(LOGIC_ANALYZER_CH6, false); } while (0) 148 | #define LOGIC_ANALYZER_CH7_ENABLE do { SET_OUTPUT(LOGIC_ANALYZER_CH7); WRITE(LOGIC_ANALYZER_CH7, false); } while (0) 149 | 150 | // Async output on channel 5 of the logical analyzer. 151 | // Baud rate 2MBit, 9 bits, 1 stop bit. 152 | #define LOGIC_ANALYZER_SERIAL_TX_ENABLE do { UBRR2H = 0; UBRR2L = 0; UCSR2B = (1 << TXEN2) | (1 << UCSZ02); UCSR2C = 0x06; } while (0) 153 | // Non-checked (quicker) variant. Use it if you are sure that the transmit buffer is already empty. 154 | #define LOGIC_ANALYZER_SERIAL_TX_WRITE_NC(C) do { if (C & 0x100) UCSR2B |= 1; else UCSR2B &= ~1; UDR2 = C; } while (0) 155 | #define LOGIC_ANALYZER_SERIAL_TX_WRITE(C) do { \ 156 | /* Wait for empty transmit buffer */ \ 157 | while (!(UCSR2A & (1<