├── .drone.yml ├── .editorconfig ├── .gitattributes ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── enhancement.md │ ├── feature_request.md │ └── question.md ├── .gitignore ├── .travis.yml ├── CMakeLists.txt ├── Catch2 └── catch.hpp ├── Firmware ├── AutoDeplete.cpp ├── AutoDeplete.h ├── BlinkM.cpp ├── BlinkM.h ├── Configuration.cpp ├── Configuration.h ├── ConfigurationStore.cpp ├── ConfigurationStore.h ├── Configuration_adv.h ├── Dcodes.cpp ├── Dcodes.h ├── Firmware.ino ├── Marlin.h ├── MarlinSerial.cpp ├── MarlinSerial.h ├── Marlin_main.cpp ├── Sd2Card.cpp ├── Sd2Card.h ├── Sd2PinMap.h ├── SdBaseFile.cpp ├── SdBaseFile.h ├── SdFatConfig.h ├── SdFatStructs.h ├── SdFatUtil.cpp ├── SdFatUtil.h ├── SdFile.cpp ├── SdFile.h ├── SdInfo.h ├── SdVolume.cpp ├── SdVolume.h ├── Servo.cpp ├── Servo.h ├── Timer.cpp ├── Timer.h ├── TimerRemaining.h ├── adc.c ├── adc.h ├── backlight.cpp ├── backlight.h ├── boards.h ├── bootapp.c ├── bootapp.h ├── cardreader.cpp ├── cardreader.h ├── cmdqueue.cpp ├── cmdqueue.h ├── config.h ├── conv2str.cpp ├── conv2str.h ├── doxyfile ├── eeprom.cpp ├── eeprom.h ├── fastio.h ├── first_lay_cal.cpp ├── first_lay_cal.h ├── fsensor.cpp ├── fsensor.h ├── heatbed_pwm.cpp ├── io_atmega2560.h ├── la10compat.cpp ├── la10compat.h ├── language.c ├── language.h ├── lcd.cpp ├── lcd.h ├── le.sh ├── menu.cpp ├── menu.h ├── mesh_bed_calibration.cpp ├── mesh_bed_calibration.h ├── mesh_bed_leveling.cpp ├── mesh_bed_leveling.h ├── messages.c ├── messages.h ├── mmu.cpp ├── mmu.h ├── motion_control.cpp ├── motion_control.h ├── optiboot_w25x20cl.cpp ├── optiboot_w25x20cl.h ├── pat9125.c ├── pat9125.h ├── pins.h ├── pins_Einsy_1_0.h ├── pins_Rambo_1_0.h ├── pins_Rambo_1_3.h ├── planner.cpp ├── planner.h ├── printers.h ├── qr_solve.cpp ├── qr_solve.h ├── rbuf.c ├── rbuf.h ├── sm4.c ├── sm4.h ├── sound.cpp ├── sound.h ├── speed_lookuptable.cpp ├── speed_lookuptable.h ├── spi.c ├── spi.h ├── static_assert.h ├── stepper.cpp ├── stepper.h ├── stk500.h ├── swi2c.c ├── swi2c.h ├── swspi.cpp ├── swspi.h ├── system_timer.h ├── temperature.cpp ├── temperature.h ├── thermistortables.h ├── timer02.c ├── timer02.h ├── tmc2130.cpp ├── tmc2130.h ├── uart2.c ├── uart2.h ├── ultralcd.cpp ├── ultralcd.h ├── uni_avr_rpi.h ├── util.cpp ├── util.h ├── variants │ ├── 1_75mm_MK2-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK2-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25-BEAR-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25-BEAR-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25-Bondtech-16-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25-Bondtech-16-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-BEAR-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-BEAR-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-BMG-16-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-BMG-16-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-BMG-8-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-BMG-8-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-Bondtech-16-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-Bondtech-16-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-Bondtech-16-SliceHT-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-Bondtech-16-SliceHT-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK25S-RAMBo10a-E3Dv6full.h │ ├── 1_75mm_MK25S-RAMBo13a-E3Dv6full.h │ ├── 1_75mm_MK3-320Z-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3-BEAR-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3-BMG-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3-Bondtech-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3-Bondtech-320Z-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-320Z-BMG-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-320Z-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-BEAR-320Z-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-BEAR-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-BEAR-SilverPSU-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-16-SilverPSU-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-16-SliceHT-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-16-SliceHT-SilverPSU-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-320Z-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-Mosquito-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-Mosquito-16-SliceHT-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-MosquitoMagnum-16-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-Bondtech-MosquitoMagnum-16-SliceHT-EINSy10a-E3Dv6full.h │ ├── 1_75mm_MK3S-EINSy10a-E3Dv6full.h │ └── create_variants.sh ├── vector_3.cpp ├── vector_3.h ├── w25x20cl.c ├── w25x20cl.h ├── xyzcal.cpp └── xyzcal.h ├── LICENSE ├── PF-build.sh ├── README.md ├── README_cz.md ├── Tests ├── Arduino.h ├── AutoDeplete_test.cpp ├── Example_test.cpp ├── PrusaStatistics_test.cpp ├── Timer_test.cpp └── tests.cpp ├── build.sh ├── lang ├── config.sh ├── fw-build.sh ├── fw-clean.sh ├── iso639-1.txt ├── lang-add.sh ├── lang-build.sh ├── lang-check.py ├── lang-check.sh ├── lang-clean.sh ├── lang-export.sh ├── lang-import.sh ├── lang_en.txt ├── lang_en_cz.txt ├── lang_en_de.txt ├── lang_en_es.txt ├── lang_en_fr.txt ├── lang_en_it.txt ├── lang_en_pl.txt ├── po │ ├── Firmware.pot │ ├── Firmware_cs.po │ ├── Firmware_de.po │ ├── Firmware_es.po │ ├── Firmware_fr.po │ ├── Firmware_it.po │ ├── Firmware_pl.po │ └── new │ │ ├── cs.po │ │ ├── de.po │ │ ├── es.po │ │ ├── fr.po │ │ ├── it.po │ │ └── pl.po ├── progmem.sh ├── readme.txt ├── textaddr.sh ├── translations.md └── update_lang.sh ├── prepare_winbuild.ps1 └── test.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | #-*-mode:conf-*- 2 | # editorconfig file (see EditorConfig.org) 3 | 4 | root = true 5 | 6 | [*] 7 | end_of_line = lf 8 | insert_final_newline = true 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | indent_style = space 12 | indent_size = 4 13 | tab_width = 4 14 | max_line_length = 100 15 | 16 | [lang/po/*.po] 17 | end_of_line = crlf 18 | trim_trailing_whitespace = false 19 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | lang/po/*.po text eol=crlf 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please, before you create a new bug report, please make sure you searched in open and closed issues and couldn't find anything that matches. 11 | 12 | **Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2] 13 | **Printer firmware version**- [e.g. 3.8.1, 3.8.1-RC1, ...] 14 | 15 | **MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1] 16 | **MMU upgrade firmware version [e.g. 1.0.6, 1.0.6-RC2, ...] 17 | 18 | **SD card or USB/Octoprint** 19 | Please let us know if you print via SD card or USB/Octoprint 20 | 21 | **Describe the bug** 22 | A clear and concise description of what the bug is. 23 | 24 | **To Reproduce** 25 | Please describe steps to reproduce the behavior. 26 | 27 | **Expected behavior** 28 | A clear and concise description of what you expected to happen. 29 | 30 | **G-code** 31 | Please attach a G-code. This will make it easier for us to replicate the error. 32 | 33 | **Video** 34 | Please attach a video. It usually helps to solve the problem. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement 3 | about: Suggest an idea for this project 4 | title: " [ENHANCEMENT]" 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches. 11 | 12 | Enter what type of printer or upgrade the enhancement applies to. 13 | **Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2] 14 | **MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1] 15 | 16 | **Is your enhancement related to a problem? Please describe.** 17 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 18 | 19 | **Describe the solution you'd like** 20 | A clear and concise description of what you want to happen. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE REQUEST]" 5 | labels: feature request 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches. 11 | 12 | If it makes sense, enter what type of printer or upgrade the feature request applies to. 13 | **Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2] 14 | **MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1] 15 | 16 | **Is your feature request related to a problem? Please describe.** 17 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 18 | 19 | **Describe the solution you'd like** 20 | A clear and concise description of what you want to happen. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: What do you want to know? 4 | title: "[QUESTION]" 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | 10 | Please, before you create a new question, please make sure you searched in open and closed issues and couldn't find anything that matches. 11 | 12 | **What is your question?** 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .settings 3 | .project 4 | .cproject 5 | Debug 6 | Firmware/Configuration_prusa.h 7 | Firmware/Doc 8 | /Firmware/.vs/Firmware/v14 9 | /Firmware/__vm 10 | /Firmware/Firmware.sln 11 | /Firmware/Firmware.vcxproj 12 | /Firmware/Firmware.vcxproj.filters 13 | /Firmware/Firmware - Shortcut.lnk 14 | /Firmware/variants/1_75mm_MK3-MMU-EINSy10a-E3Dv6full.h.bak 15 | /Firmware/Marlin_main.cpp~RF12cfae7.TMP 16 | /Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h.bak 17 | /html 18 | /latex 19 | /Doxyfile 20 | /Firmware/builds/1_75mm_MK3-EINY04-E3Dv6full 21 | /Firmware/Configuration_prusa.h.bak 22 | /Firmware/Configuration_prusa_backup.h 23 | /Firmware/ultralcd_implementation_hitachi_HD44780.h.bak 24 | /Firmware/ultralcd.cpp.bak 25 | /Firmware/temperature.cpp.bak 26 | /Firmware/pins.h.bak 27 | /Firmware/Marlin_main.cpp.bak 28 | /Firmware/language_pl.h.bak 29 | /Firmware/language_it.h.bak 30 | /Firmware/language_es.h.bak 31 | /Firmware/language_en.h.bak 32 | /Firmware/language_de.h.bak 33 | /Firmware/language_cz.h.bak 34 | /Firmware/variants/1_75mm_MK2-MultiMaterial-RAMBo13a-E3Dv6full.h 35 | /Firmware/variants/1_75mm_MK2-MultiMaterial-RAMBo10a-E3Dv6full.h 36 | /Firmware/variants/1_75mm_MK2-EINY01-E3Dv6full.h.bak 37 | /Firmware/variants/1_75mm_MK1-RAMBo13a-E3Dv6full.h 38 | /Firmware/variants/1_75mm_MK1-RAMBo10a-E3Dv6full.h 39 | /lang/*.bin 40 | /lang/*.hex 41 | /lang/*.dat 42 | /lang/*.tmp 43 | /lang/*.out 44 | /lang/not_tran*.txt 45 | /lang/not_used*.txt 46 | /lang/progmem1.chr 47 | /lang/progmem1.lss 48 | /lang/progmem1.txt 49 | /lang/progmem1.var 50 | /lang/text.sym 51 | /lang/textaddr.txt 52 | /build-env/ 53 | /Firmware/Firmware.vcxproj 54 | /Firmware/Configuration_prusa_bckp.h 55 | /Firmware/variants/printers.h 56 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | before_install: 3 | - sudo apt-get install -y ninja-build 4 | # Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off 5 | - sudo iptables -P INPUT DROP 6 | - sudo iptables -P FORWARD DROP 7 | - sudo iptables -P OUTPUT ACCEPT 8 | - sudo iptables -A INPUT -i lo -j ACCEPT 9 | - sudo iptables -A OUTPUT -o lo -j ACCEPT 10 | - sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 11 | script: 12 | - bash -x test.sh 13 | - cp Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h 14 | - bash -x build.sh || { echo "1_75mm_MK3S-EINSy10a-E3Dv6full variant failed" && false; } 15 | - rm Firmware/Configuration_prusa.h 16 | - cp Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h 17 | - bash -x build.sh || { echo "1_75mm_MK3-EINSy10a-E3Dv6full variant failed" && false; } 18 | - rm Firmware/Configuration_prusa.h 19 | - cp Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h 20 | - bash -x build.sh || { echo "1_75mm_MK25S-RAMBo13a-E3Dv6full variant failed" && false; } 21 | - rm Firmware/Configuration_prusa.h 22 | - cp Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h 23 | - bash -x build.sh || { echo "1_75mm_MK25S-RAMBo10a-E3Dv6full variant failed" && false; } 24 | - rm Firmware/Configuration_prusa.h 25 | - cp Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h 26 | - bash -x build.sh || { echo "1_75mm_MK25-RAMBo13a-E3Dv6full variant failed" && false; } 27 | - rm Firmware/Configuration_prusa.h 28 | - cp Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h 29 | - bash -x build.sh || { echo "1_75mm_MK25-RAMBo10a-E3Dv6full variant failed" && false; } 30 | - rm Firmware/Configuration_prusa.h 31 | - cp Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h 32 | - bash -x build.sh || { echo "1_75mm_MK2-RAMBo13a-E3Dv6full variant failed" && false; } 33 | - rm Firmware/Configuration_prusa.h 34 | - cp Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h 35 | - bash -x build.sh || { echo "1_75mm_MK2-RAMBo10a-E3Dv6full variant failed" && false; } -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set (CMAKE_CXX_STANDARD 11) 4 | 5 | project(cmake_test) 6 | 7 | # Prepare "Catch" library for other executables 8 | set(CATCH_INCLUDE_DIR Catch2) 9 | add_library(Catch INTERFACE) 10 | target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR}) 11 | 12 | # Make test executable 13 | set(TEST_SOURCES 14 | Tests/tests.cpp 15 | Tests/Example_test.cpp 16 | Tests/Timer_test.cpp 17 | Tests/AutoDeplete_test.cpp 18 | Tests/PrusaStatistics_test.cpp 19 | Firmware/Timer.cpp 20 | Firmware/AutoDeplete.cpp 21 | ) 22 | add_executable(tests ${TEST_SOURCES}) 23 | target_include_directories(tests PRIVATE Tests) 24 | target_link_libraries(tests Catch) 25 | -------------------------------------------------------------------------------- /Firmware/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 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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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; -------------------------------------------------------------------------------- /Firmware/ConfigurationStore.h: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_STORE_H 2 | #define CONFIG_STORE_H 3 | #define EEPROM_SETTINGS 4 | 5 | #include "Configuration.h" 6 | #include 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 | } M500_conf; 42 | 43 | extern M500_conf cs; 44 | 45 | void Config_ResetDefault(); 46 | 47 | #ifndef DISABLE_M503 48 | void Config_PrintSettings(uint8_t level = 0); 49 | #else 50 | FORCE_INLINE void Config_PrintSettings() {} 51 | #endif 52 | 53 | #ifdef EEPROM_SETTINGS 54 | void Config_StoreSettings(); 55 | bool Config_RetrieveSettings(); 56 | #else 57 | FORCE_INLINE void Config_StoreSettings() {} 58 | FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_PrintSettings(); } 59 | #endif 60 | 61 | inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); } 62 | inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); } 63 | inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); } 64 | 65 | #endif//CONFIG_STORE_H 66 | -------------------------------------------------------------------------------- /Firmware/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 | extern void dcode_2(); //D2 - Read/Write RAM 8 | 9 | #if defined DEBUG_DCODE3 || defined DEBUG_DCODES 10 | extern void dcode_3(); //D3 - Read/Write EEPROM 11 | #endif //DEBUG_DCODE3 12 | 13 | extern void dcode_4(); //D4 - Read/Write PIN 14 | 15 | #if defined DEBUG_DCODE5 || defined DEBUG_DCODES 16 | extern void dcode_5(); //D5 - Read/Write FLASH 17 | #endif //DEBUG_DCODE5 18 | 19 | extern void dcode_6(); //D6 - Read/Write external FLASH 20 | extern void dcode_7(); //D7 - Read/Write Bootloader 21 | extern void dcode_8(); //D8 - Read/Write PINDA 22 | extern void dcode_9(); //D9 - Read/Write ADC (Write=enable simulated, Read=disable simulated) 23 | extern void dcode_10(); //D10 - XYZ calibration = OK 24 | extern void dcode_12(); //D12 - Log time. Writes the current time in the log file. 25 | 26 | #ifdef HEATBED_ANALYSIS 27 | extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt". 28 | extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt". 29 | #endif //HEATBED_ANALYSIS 30 | 31 | extern void dcode_106(); //D106 - Print measured fan speed for different pwm values 32 | 33 | #ifdef TMC2130 34 | extern void dcode_2130(); //D2130 - TMC2130 35 | #endif //TMC2130 36 | 37 | #ifdef PAT9125 38 | extern void dcode_9125(); //D9125 - PAT9125 39 | #endif //PAT9125 40 | 41 | 42 | #endif //DCODES_H 43 | -------------------------------------------------------------------------------- /Firmware/Firmware.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 | 36 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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; 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; 58 | return (*stack_guard == STACK_GUARD_TEST_VALUE); 59 | } 60 | 61 | uint32_t SdFatUtil::get_stack_guard_test_value() 62 | { 63 | uint32_t* stack_guard; 64 | uint32_t output; 65 | stack_guard = (uint32_t*)&__bss_end; 66 | output = *stack_guard; 67 | return(output); 68 | } 69 | //------------------------------------------------------------------------------ 70 | /** %Print a string in flash memory. 71 | * 72 | * \param[in] pr Print object for output. 73 | * \param[in] str Pointer to string stored in flash memory. 74 | */ 75 | void SdFatUtil::print_P( PGM_P str) { 76 | for (uint8_t c; (c = pgm_read_byte(str)); str++) MYSERIAL.write(c); 77 | } 78 | //------------------------------------------------------------------------------ 79 | /** %Print a string in flash memory followed by a CR/LF. 80 | * 81 | * \param[in] pr Print object for output. 82 | * \param[in] str Pointer to string stored in flash memory. 83 | */ 84 | void SdFatUtil::println_P( PGM_P str) { 85 | print_P( str); 86 | MYSERIAL.println(); 87 | } 88 | //------------------------------------------------------------------------------ 89 | /** %Print a string in flash memory to Serial. 90 | * 91 | * \param[in] str Pointer to string stored in flash memory. 92 | */ 93 | void SdFatUtil::SerialPrint_P(PGM_P str) { 94 | print_P(str); 95 | } 96 | //------------------------------------------------------------------------------ 97 | /** %Print a string in flash memory to Serial followed by a CR/LF. 98 | * 99 | * \param[in] str Pointer to string stored in flash memory. 100 | */ 101 | void SdFatUtil::SerialPrintln_P(PGM_P str) { 102 | println_P( str); 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /Firmware/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 | uint32_t get_stack_guard_test_value(); 45 | } 46 | 47 | using namespace SdFatUtil; // NOLINT 48 | #endif // #define SdFatUtil_h 49 | 50 | 51 | #endif -------------------------------------------------------------------------------- /Firmware/SdFile.cpp: -------------------------------------------------------------------------------- 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 | #include "Marlin.h" 21 | 22 | #ifdef SDSUPPORT 23 | #include "SdFile.h" 24 | /** Create a file object and open it in the current working directory. 25 | * 26 | * \param[in] path A path with a valid 8.3 DOS name for a file to be opened. 27 | * 28 | * \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive 29 | * OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t). 30 | */ 31 | SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { 32 | } 33 | //------------------------------------------------------------------------------ 34 | /** Write data to an open file. 35 | * 36 | * \note Data is moved to the cache but may not be written to the 37 | * storage device until sync() is called. 38 | * 39 | * \param[in] buf Pointer to the location of the data to be written. 40 | * 41 | * \param[in] nbyte Number of bytes to write. 42 | * 43 | * \return For success write() returns the number of bytes written, always 44 | * \a nbyte. If an error occurs, write() returns -1. Possible errors 45 | * include write() is called before a file has been opened, write is called 46 | * for a read-only file, device is full, a corrupt file system or an I/O error. 47 | * 48 | */ 49 | int16_t SdFile::write(const void* buf, uint16_t nbyte) { 50 | return SdBaseFile::write(buf, nbyte); 51 | } 52 | //------------------------------------------------------------------------------ 53 | /** Write a byte to a file. Required by the Arduino Print class. 54 | * \param[in] b the byte to be written. 55 | * Use writeError to check for errors. 56 | */ 57 | #if ARDUINO >= 100 58 | size_t SdFile::write(uint8_t b) 59 | { 60 | return SdBaseFile::write(&b, 1); 61 | } 62 | #else 63 | void SdFile::write(uint8_t b) 64 | { 65 | SdBaseFile::write(&b, 1); 66 | } 67 | #endif 68 | //------------------------------------------------------------------------------ 69 | /** Write a string to a file. Used by the Arduino Print class. 70 | * \param[in] str Pointer to the string. 71 | * Use writeError to check for errors. 72 | */ 73 | void SdFile::write(const char* str) { 74 | SdBaseFile::write(str, strlen(str)); 75 | } 76 | //------------------------------------------------------------------------------ 77 | /** Write a PROGMEM string to a file. 78 | * \param[in] str Pointer to the PROGMEM string. 79 | * Use writeError to check for errors. 80 | */ 81 | void SdFile::write_P(PGM_P str) { 82 | for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c); 83 | } 84 | //------------------------------------------------------------------------------ 85 | /** Write a PROGMEM string followed by CR/LF to a file. 86 | * \param[in] str Pointer to the PROGMEM string. 87 | * Use writeError to check for errors. 88 | */ 89 | void SdFile::writeln_P(PGM_P str) { 90 | write_P(str); 91 | write_P(PSTR("\r\n")); 92 | } 93 | 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /Firmware/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 | public: 38 | SdFile() {} 39 | SdFile(const char* name, uint8_t oflag); 40 | #if ARDUINO >= 100 41 | size_t write(uint8_t b); 42 | #else 43 | void write(uint8_t b); 44 | #endif 45 | 46 | int16_t write(const void* buf, uint16_t nbyte); 47 | void write(const char* str); 48 | void write_P(PGM_P str); 49 | void writeln_P(PGM_P str); 50 | }; 51 | #endif // SdFile_h 52 | 53 | 54 | #endif -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/Timer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Marek Bel 4 | */ 5 | 6 | #ifndef TIMER_H 7 | #define TIMER_H 8 | 9 | /** 10 | * @brief simple timer 11 | * 12 | * Simple and memory saving implementation. Should handle timer register wrap around well. 13 | * Resolution is one millisecond. To save memory, doesn't store timer period. 14 | * If you wish timer which is storing period, derive from this. 15 | */ 16 | template 17 | class Timer 18 | { 19 | public: 20 | Timer(); 21 | void start(); 22 | void stop(){m_isRunning = false;} 23 | bool running(){return m_isRunning;} 24 | bool expired(T msPeriod); 25 | protected: 26 | T started(){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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | printf_P(PSTR("adc_init\n")); 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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/backlight.cpp: -------------------------------------------------------------------------------- 1 | //backlight.cpp 2 | 3 | #include "backlight.h" 4 | #include 5 | #include 6 | #include "eeprom.h" 7 | #include "Marlin.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(__attribute__((unused)) bool section_start) {} 115 | void backlight_update() {} 116 | void backlight_init() {} 117 | void backlight_save() {} 118 | void backlight_wake(__attribute__((unused)) const uint8_t flashNo) {} 119 | 120 | #endif //LCD_BL_PIN -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | void bootapp_print_vars(void) 13 | { 14 | fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr); 15 | fprintf_P(uartout, PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr); 16 | fprintf_P(uartout, PSTR("boot_copy_size =0x%04x\n"), boot_copy_size); 17 | fprintf_P(uartout, PSTR("boot_reserved =0x%02x\n"), boot_reserved); 18 | fprintf_P(uartout, PSTR("boot_app_flags =0x%02x\n"), boot_app_flags); 19 | fprintf_P(uartout, PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic); 20 | } 21 | 22 | 23 | void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size) 24 | { 25 | cli(); 26 | boot_app_magic = BOOT_APP_MAGIC; 27 | boot_app_flags |= BOOT_APP_FLG_COPY; 28 | boot_app_flags |= BOOT_APP_FLG_ERASE; 29 | /* uint16_t ui; for (ui = 0; ui < size; ui++) 30 | { 31 | uint8_t uc = ram_array[ui+rptr]; 32 | if (pgm_read_byte(ui+fptr) & uc != uc) 33 | { 34 | boot_app_flags |= BOOT_APP_FLG_ERASE; 35 | break; 36 | } 37 | }*/ 38 | boot_copy_size = (uint16_t)size; 39 | boot_src_addr = (uint32_t)rptr; 40 | boot_dst_addr = (uint32_t)fptr; 41 | bootapp_print_vars(); 42 | wdt_enable(WDTO_15MS); 43 | while(1); 44 | } 45 | 46 | void bootapp_reboot_user0(uint8_t reserved) 47 | { 48 | cli(); 49 | boot_app_magic = BOOT_APP_MAGIC; 50 | boot_app_flags = BOOT_APP_FLG_USER0; 51 | boot_reserved = reserved; 52 | bootapp_print_vars(); 53 | wdt_enable(WDTO_15MS); 54 | while(1); 55 | } 56 | -------------------------------------------------------------------------------- /Firmware/bootapp.h: -------------------------------------------------------------------------------- 1 | //language.h 2 | #ifndef BOOTAPP_H 3 | #define BOOTAPP_H 4 | 5 | #include "config.h" 6 | #include 7 | 8 | 9 | #define RAMSIZE 0x2000 10 | #define ram_array ((uint8_t*)(0)) 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 | -------------------------------------------------------------------------------- /Firmware/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 | 39 | // Type of a command, which is to be executed right now. 40 | #define CMDBUFFER_CURRENT_TYPE (cmdbuffer[bufindr]) 41 | // String of a command, which is to be executed right now. 42 | #define CMDBUFFER_CURRENT_STRING (cmdbuffer+bufindr+CMDHDRSIZE) 43 | 44 | // Enable debugging of the command buffer. 45 | // Debugging information will be sent to serial line. 46 | //#define CMDBUFFER_DEBUG 47 | 48 | extern uint32_t sdpos_atomic; 49 | 50 | extern int serial_count; 51 | extern boolean comment_mode; 52 | extern char *strchr_pointer; 53 | 54 | extern unsigned long TimeSent; 55 | extern unsigned long TimeNow; 56 | 57 | extern long gcode_N; 58 | extern long gcode_LastN; 59 | extern long Stopped_gcode_LastN; 60 | 61 | extern bool cmdqueue_pop_front(); 62 | extern void cmdqueue_reset(); 63 | #ifdef CMDBUFFER_DEBUG 64 | extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p); 65 | extern void cmdqueue_dump_to_serial(); 66 | #endif /* CMDBUFFER_DEBUG */ 67 | extern bool cmd_buffer_empty(); 68 | extern void enquecommand(const char *cmd, bool from_progmem); 69 | extern void enquecommand_front(const char *cmd, bool from_progmem); 70 | extern void repeatcommand_front(); 71 | extern bool is_buffer_empty(); 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(const char *code) { return (strchr_pointer = strstr(CMDBUFFER_CURRENT_STRING, code)) != 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 | -------------------------------------------------------------------------------- /Firmware/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 27 | //#define SWI2C_SDA 20 //SDA on P3 28 | //#define SWI2C_SCL 21 //SCL on P3 29 | #define SWI2C_A8 30 | #define SWI2C_DEL 20 //2us clock delay 31 | #define SWI2C_TMO 2048 //2048 cycles timeout 32 | 33 | //PAT9125 configuration 34 | #define PAT9125_SWI2C 35 | #define PAT9125_I2C_ADDR 0x75 //ID=LO 36 | //#define PAT9125_I2C_ADDR 0x79 //ID=HI 37 | //#define PAT9125_I2C_ADDR 0x73 //ID=NC 38 | #define PAT9125_XRES 0 39 | #define PAT9125_YRES 240 // maximum resolution (5*X cpi) 40 | #define PAT9124_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm 41 | 42 | //SM4 configuration 43 | #define SM4_DEFDELAY 500 //default step delay [us] 44 | 45 | //TMC2130 - Trinamic stepper driver 46 | //pinout - hardcoded 47 | //spi: 48 | #define TMC2130_SPI_RATE 0 // fosc/4 = 4MHz 49 | #define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0) 50 | #define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE) 51 | 52 | //W25X20CL configuration 53 | //pinout: 54 | #define W25X20CL_PIN_CS 32 55 | //spi: 56 | #define W25X20CL_SPI_RATE 0 // fosc/4 = 4MHz 57 | #define W25X20CL_SPCR SPI_SPCR(W25X20CL_SPI_RATE, 1, 1, 1, 0) 58 | #define W25X20CL_SPSR SPI_SPSR(W25X20CL_SPI_RATE) 59 | 60 | //LANG - Multi-language support 61 | //#define LANG_MODE 0 // primary language only 62 | #define LANG_MODE 1 // sec. language support 63 | 64 | #define LANG_SIZE_RESERVED 0x3000 // reserved space for secondary language (12288 bytes) 65 | 66 | 67 | #endif //_CONFIG_H 68 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | 87 | #ifdef IR_SENSOR_ANALOG 88 | #define IR_SENSOR_STEADY 10 // [ms] 89 | 90 | enum class ClFsensorPCB:uint_least8_t 91 | { 92 | _Old=0, 93 | _Rev04=1, 94 | _Undef=EEPROM_EMPTY_VALUE 95 | }; 96 | 97 | enum class ClFsensorActionNA:uint_least8_t 98 | { 99 | _Continue=0, 100 | _Pause=1, 101 | _Undef=EEPROM_EMPTY_VALUE 102 | }; 103 | 104 | extern ClFsensorPCB oFsensorPCB; 105 | extern ClFsensorActionNA oFsensorActionNA; 106 | 107 | extern bool fsensor_IR_check(); 108 | #endif //IR_SENSOR_ANALOG 109 | 110 | #endif //FSENSOR_H 111 | -------------------------------------------------------------------------------- /Firmware/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.004 - 0.05; 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 (1-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 < 1.0? j * 3.625: 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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/language.h: -------------------------------------------------------------------------------- 1 | /** @file */ 2 | //language.h 3 | #ifndef LANGUAGE_H 4 | #define LANGUAGE_H 5 | 6 | 7 | #include "config.h" 8 | #include 9 | #ifdef DEBUG_SEC_LANG 10 | #include 11 | #endif //DEBUG_SEC_LANG 12 | 13 | #define PROTOCOL_VERSION "1.0" 14 | 15 | #ifndef CUSTOM_MENDEL_NAME 16 | #define MACHINE_NAME "Mendel" 17 | #endif 18 | 19 | #ifndef MACHINE_UUID 20 | #define MACHINE_UUID "00000000-0000-0000-0000-000000000000" 21 | #endif 22 | 23 | #define MSG_FW_VERSION "Firmware" 24 | 25 | #define STRINGIFY_(n) #n 26 | #define STRINGIFY(n) STRINGIFY_(n) 27 | 28 | #if (LANG_MODE == 0) //primary language only 29 | #define PROGMEM_I2 __attribute__((section(".progmem0"))) 30 | #define PROGMEM_I1 __attribute__((section(".progmem1"))) 31 | #define PROGMEM_N1 __attribute__((section(".progmem2"))) 32 | #define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = s; &__c[0];})) 33 | #define ISTR(s) s 34 | #define _i(s) _I(s) 35 | #define _T(s) s 36 | #else //(LANG_MODE == 0) 37 | // section .loc_sec (originaly .progmem0) will be used for localized translated strings 38 | #define PROGMEM_I2 __attribute__((section(".loc_sec"))) 39 | // section .loc_pri (originaly .progmem1) will be used for localized strings in english 40 | #define PROGMEM_I1 __attribute__((section(".loc_pri"))) 41 | // section .noloc (originaly progmem2) will be used for not localized strings in english 42 | #define PROGMEM_N1 __attribute__((section(".noloc"))) 43 | #define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = "\xff\xff" s; &__c[0];})) 44 | #define ISTR(s) "\xff\xff" s 45 | #define _i(s) lang_get_translation(_I(s)) 46 | #define _T(s) lang_get_translation(s) 47 | #endif //(LANG_MODE == 0) 48 | #define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];})) 49 | #define _n(s) _N(s) 50 | 51 | /** @brief lang_table_header_t structure - (size= 16byte) */ 52 | typedef struct 53 | { 54 | uint32_t magic; //+0 55 | uint16_t size; //+4 56 | uint16_t count; //+6 57 | uint16_t checksum; //+8 58 | uint16_t code; //+10 59 | uint32_t signature; //+12 60 | } lang_table_header_t; 61 | 62 | /** @brief lang_table_t structure - (size= 16byte + 2*count) */ 63 | typedef struct 64 | { 65 | lang_table_header_t header; 66 | uint16_t table[]; 67 | } lang_table_t; 68 | 69 | /** @name Language indices into their particular symbol tables.*/ 70 | ///@{ 71 | #define LANG_ID_PRI 0 72 | #define LANG_ID_SEC 1 73 | ///@} 74 | 75 | /** @def LANG_ID_FORCE_SELECTION 76 | * @brief Language is not defined and it shall be selected from the menu.*/ 77 | #define LANG_ID_FORCE_SELECTION 254 78 | 79 | /** @def LANG_ID_UNDEFINED 80 | * @brief Language is not defined on a virgin RAMBo board. */ 81 | #define LANG_ID_UNDEFINED 255 82 | 83 | /** @def LANG_ID_DEFAULT 84 | * @brief Default language ID, if no language is selected. */ 85 | #define LANG_ID_DEFAULT LANG_ID_PRI 86 | 87 | /** @def LANG_MAGIC 88 | * @brief Magic number at begin of lang table. */ 89 | #define LANG_MAGIC 0x4bb45aa5 90 | 91 | /** @name Language codes (ISO639-1)*/ 92 | ///@{ 93 | #define LANG_CODE_XX 0x3f3f //!<'??' 94 | #define LANG_CODE_EN 0x656e //!<'en' 95 | #define LANG_CODE_CZ 0x6373 //!<'cs' 96 | #define LANG_CODE_DE 0x6465 //!<'de' 97 | #define LANG_CODE_ES 0x6573 //!<'es' 98 | #define LANG_CODE_FR 0x6672 //!<'fr' 99 | #define LANG_CODE_IT 0x6974 //!<'it' 100 | #define LANG_CODE_PL 0x706c //!<'pl' 101 | ///@} 102 | 103 | #if defined(__cplusplus) 104 | extern "C" { 105 | #endif //defined(__cplusplus) 106 | 107 | /** @brief Currectly active language selection.*/ 108 | extern uint8_t lang_selected; 109 | 110 | #if (LANG_MODE != 0) 111 | extern const char _SEC_LANG[LANG_SIZE_RESERVED]; 112 | extern const char* lang_get_translation(const char* s); 113 | /** @def _SEC_LANG_TABLE 114 | * @brief Align table to start of 256 byte page */ 115 | #define _SEC_LANG_TABLE ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00) 116 | #endif //(LANG_MODE != 0) 117 | 118 | /** @brief selects language, eeprom is updated in case of success */ 119 | extern uint8_t lang_select(uint8_t lang); 120 | /** @brief performs checksum test of secondary language data */ 121 | extern uint8_t lang_check(uint16_t addr); 122 | /** @return total number of languages (primary + all in xflash) */ 123 | extern uint8_t lang_get_count(void); 124 | /** @brief reads lang table header and offset in xflash or progmem */ 125 | extern uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset); 126 | /** @brief reads lang code from xflash or progmem */ 127 | extern uint16_t lang_get_code(uint8_t lang); 128 | /** @return localized language name (text for menu item) */ 129 | extern const char* lang_get_name_by_code(uint16_t code); 130 | /** @brief reset language to "LANG_ID_FORCE_SELECTION", epprom is updated */ 131 | extern void lang_reset(void); 132 | /** @retval 1 language is selected */ 133 | extern uint8_t lang_is_selected(void); 134 | 135 | #ifdef DEBUG_SEC_LANG 136 | extern const char* lang_get_sec_lang_str_by_id(uint16_t id); 137 | extern uint16_t lang_print_sec_lang(FILE* out); 138 | #endif //DEBUG_SEC_LANG 139 | 140 | extern void lang_boot_update_start(uint8_t lang); 141 | 142 | #if defined(__cplusplus) 143 | } 144 | #endif //defined(__cplusplus) 145 | 146 | #define CAT2(_s1, _s2) _s1 147 | #define CAT4(_s1, _s2, _s3, _s4) _s1 148 | 149 | #include "messages.h" 150 | 151 | 152 | #endif //LANGUAGE_H 153 | 154 | -------------------------------------------------------------------------------- /Firmware/le.sh: -------------------------------------------------------------------------------- 1 | # line ending management script 2 | # CRLF - windows default ('\r\n') 3 | # LF - unix default ('\n') 4 | # arguments: 5 | # ?crlf - print all .cpp and .h files with CRLF line endings 6 | # ?lf - print all .cpp and .h files with LF line endings 7 | # crlf - replace line endings in all .cpp and .h files to CRLF 8 | # lf - replace line endings in all .cpp and .h files to LF 9 | 10 | if [ "$1" == "?crlf" ] || [ $# -eq 0 ]; then 11 | echo 'cpp and h files with CRLF line endings:' 12 | find {*.cpp,*.h} -not -type d -exec file "{}" ";" | grep CRLF | sed 's/:.*//g' 13 | elif [ "$1" == "?lf" ]; then 14 | echo 'cpp and h files with LF line endings:' 15 | find {*.cpp,*.h} -not -type d -exec file "{}" ";" | grep -v CRLF | sed 's/:.*//g' 16 | fi 17 | if [ "$1" == "crlf" ]; then 18 | echo 'replacing LF with CRLF in all cpp and h files:' 19 | find {*.cpp,*.h} -not -type d -exec file "{}" ";" | grep -v CRLF | sed 's/:.*//g' | while read fn; do 20 | echo "$fn" 21 | sed -i 's/$/\r/g' $fn 22 | done 23 | elif [ "$1" == "lf" ]; then 24 | echo 'replacing CRLF with LF in all cpp and h files:' 25 | find {*.cpp,*.h} -not -type d -exec file "{}" ";" | grep CRLF | sed 's/:.*//g' | while read fn; do 26 | echo "$fn" 27 | sed -i 's/\r\n/\n/g' $fn 28 | done 29 | fi 30 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/mmu.h: -------------------------------------------------------------------------------- 1 | //! @file 2 | 3 | #ifndef MMU_H 4 | #define MMU_H 5 | 6 | #include 7 | 8 | 9 | extern bool mmu_enabled; 10 | extern bool mmu_fil_loaded; 11 | 12 | extern uint8_t mmu_extruder; 13 | 14 | extern uint8_t tmp_extruder; 15 | 16 | extern int8_t mmu_finda; 17 | extern uint32_t mmu_last_finda_response; 18 | extern bool ir_sensor_detected; 19 | 20 | extern int16_t mmu_version; 21 | extern int16_t mmu_buildnr; 22 | 23 | extern uint16_t mmu_power_failures; 24 | 25 | #define MMU_FILAMENT_UNKNOWN 255 26 | 27 | #define MMU_NO_MOVE 0 28 | #define MMU_UNLOAD_MOVE 1 29 | #define MMU_LOAD_MOVE 2 30 | #define MMU_TCODE_MOVE 3 31 | 32 | #define MMU_LOAD_FEEDRATE 19.02f //mm/s 33 | #define MMU_LOAD_TIME_MS 2000 //should be fine tuned to load time for shortest allowed PTFE tubing and maximum loading speed 34 | 35 | enum class MmuCmd : uint_least8_t 36 | { 37 | None, 38 | T0, 39 | T1, 40 | T2, 41 | T3, 42 | T4, 43 | L0, 44 | L1, 45 | L2, 46 | L3, 47 | L4, 48 | C0, 49 | U0, 50 | E0, 51 | E1, 52 | E2, 53 | E3, 54 | E4, 55 | K0, 56 | K1, 57 | K2, 58 | K3, 59 | K4, 60 | R0, 61 | S3, 62 | W0, //!< Wait and signal load error 63 | }; 64 | 65 | inline MmuCmd operator+ (MmuCmd cmd, uint8_t filament) 66 | { 67 | return static_cast(static_cast(cmd) + filament ); 68 | } 69 | 70 | inline uint8_t operator- (MmuCmd cmda, MmuCmd cmdb) 71 | { 72 | return (static_cast(cmda) - static_cast(cmdb)); 73 | } 74 | 75 | extern int mmu_puts_P(const char* str); 76 | 77 | extern int mmu_printf_P(const char* format, ...); 78 | 79 | extern int8_t mmu_rx_ok(void); 80 | 81 | extern bool check_for_ir_sensor(); 82 | 83 | extern void mmu_init(void); 84 | 85 | extern void mmu_loop(void); 86 | 87 | 88 | extern void mmu_reset(void); 89 | 90 | extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament); 91 | 92 | extern void mmu_command(MmuCmd cmd); 93 | 94 | extern bool mmu_get_response(uint8_t move = 0); 95 | 96 | extern void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move = MMU_NO_MOVE); 97 | 98 | extern void mmu_load_to_nozzle(); 99 | 100 | extern void mmu_M600_load_filament(bool automatic, float nozzle_temp); 101 | extern void mmu_M600_wait_and_beep(); 102 | 103 | extern void extr_mov(float shift, float feed_rate); 104 | extern void change_extr(int extr); 105 | extern int get_ext_nr(); 106 | extern void display_loading(); 107 | extern void extr_adj(uint8_t extruder); 108 | extern void extr_unload(); 109 | 110 | extern void extr_adj_0(); 111 | extern void extr_adj_1(); 112 | extern void extr_adj_2(); 113 | extern void extr_adj_3(); 114 | extern void extr_adj_4(); 115 | extern void load_all(); 116 | extern void extr_change_0(); 117 | extern void extr_change_1(); 118 | extern void extr_change_2(); 119 | extern void extr_change_3(); 120 | #ifdef SNMM 121 | extern void extr_unload_all(); 122 | extern void extr_unload_used(); 123 | #endif //SNMM 124 | extern void extr_unload_0(); 125 | extern void extr_unload_1(); 126 | extern void extr_unload_2(); 127 | extern void extr_unload_3(); 128 | extern void extr_unload_4(); 129 | 130 | extern bool mmu_check_version(); 131 | extern void mmu_show_warning(); 132 | extern void lcd_mmu_load_to_nozzle(uint8_t filament_nr); 133 | extern void mmu_eject_filament(uint8_t filament, bool recover); 134 | #ifdef MMU_HAS_CUTTER 135 | extern void mmu_cut_filament(uint8_t filament_nr); 136 | #endif //MMU_HAS_CUTTER 137 | extern void mmu_continue_loading(bool blocking); 138 | extern void mmu_filament_ramming(); 139 | extern void mmu_wait_for_heater_blocking(); 140 | extern void mmu_load_step(bool synchronize = true); 141 | 142 | #endif //MMU_H 143 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/optiboot_w25x20cl.h: -------------------------------------------------------------------------------- 1 | #ifndef OPTIBOOT_W25X20CL_H 2 | #define OPTIBOOT_W25X20CL_H 3 | 4 | extern void optiboot_w25x20cl_enter(); 5 | 6 | #endif /* OPTIBOOT_W25X20CL_H */ 7 | -------------------------------------------------------------------------------- /Firmware/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_init(void); 22 | extern uint8_t pat9125_update(void); // update all sensor data 23 | extern uint8_t pat9125_update_y(void); // update _y only 24 | extern uint8_t pat9125_update_bs(void); // update _b/_s only 25 | 26 | 27 | #if defined(__cplusplus) 28 | } 29 | #endif //defined(__cplusplus) 30 | 31 | #endif //PAT9125_H 32 | -------------------------------------------------------------------------------- /Firmware/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 | //List of pins which to ignore when asked to change by gcode, 0 and 1 are RX and TX, do not mess with those! 29 | #define _E0_PINS E0_STEP_PIN, E0_DIR_PIN, E0_ENABLE_PIN, HEATER_0_PIN, 30 | #if EXTRUDERS > 1 31 | #define _E1_PINS E1_STEP_PIN, E1_DIR_PIN, E1_ENABLE_PIN, HEATER_1_PIN, 32 | #else 33 | #define _E1_PINS 34 | #endif 35 | #if EXTRUDERS > 2 36 | #define _E2_PINS E2_STEP_PIN, E2_DIR_PIN, E2_ENABLE_PIN, HEATER_2_PIN, 37 | #else 38 | #define _E2_PINS 39 | #endif 40 | 41 | #ifdef X_STOP_PIN 42 | #if X_HOME_DIR < 0 43 | #define X_MIN_PIN X_STOP_PIN 44 | #define X_MAX_PIN -1 45 | #else 46 | #define X_MIN_PIN -1 47 | #define X_MAX_PIN X_STOP_PIN 48 | #endif 49 | #endif 50 | 51 | #ifdef Y_STOP_PIN 52 | #if Y_HOME_DIR < 0 53 | #define Y_MIN_PIN Y_STOP_PIN 54 | #define Y_MAX_PIN -1 55 | #else 56 | #define Y_MIN_PIN -1 57 | #define Y_MAX_PIN Y_STOP_PIN 58 | #endif 59 | #endif 60 | 61 | #ifdef Z_STOP_PIN 62 | #if Z_HOME_DIR < 0 63 | #define Z_MIN_PIN Z_STOP_PIN 64 | #define Z_MAX_PIN -1 65 | #else 66 | #define Z_MIN_PIN -1 67 | #define Z_MAX_PIN Z_STOP_PIN 68 | #endif 69 | #endif 70 | 71 | #ifdef DISABLE_MAX_ENDSTOPS 72 | #define X_MAX_PIN -1 73 | #define Y_MAX_PIN -1 74 | #define Z_MAX_PIN -1 75 | #endif 76 | 77 | #ifdef DISABLE_MIN_ENDSTOPS 78 | #define X_MIN_PIN -1 79 | #define Y_MIN_PIN -1 80 | #define Z_MIN_PIN -1 81 | #endif 82 | 83 | #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, \ 84 | HEATER_BED_PIN, FAN_PIN, \ 85 | _E0_PINS _E1_PINS _E2_PINS \ 86 | analogInputToDigitalPin(TEMP_0_PIN), analogInputToDigitalPin(TEMP_1_PIN), analogInputToDigitalPin(TEMP_2_PIN), analogInputToDigitalPin(TEMP_BED_PIN) } 87 | 88 | #endif //__PINS_H 89 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | #define SWI2C_SDA 20 //SDA on P3 15 | #define SWI2C_SCL 21 //SCL on P3 16 | 17 | #ifdef MICROMETER_LOGGING 18 | #define D_DATACLOCK 24 //Y_MAX (green) 19 | #define D_DATA 30 //X_MAX (blue) 20 | #define D_REQUIRE 23 //Z_MAX (white) 21 | #endif //MICROMETER_LOGGING 22 | 23 | 24 | 25 | #define X_STEP_PIN 37 26 | #define X_DIR_PIN 48 27 | #define X_MIN_PIN 12 28 | #define X_MAX_PIN -1 29 | #define X_ENABLE_PIN 29 30 | #define X_MS1_PIN 40 31 | #define X_MS2_PIN 41 32 | 33 | #define Y_STEP_PIN 36 34 | #define Y_DIR_PIN 49 35 | #define Y_MIN_PIN 11 36 | #define Y_MAX_PIN -1 37 | #define Y_ENABLE_PIN 28 38 | #define Y_MS1_PIN 69 39 | #define Y_MS2_PIN 39 40 | 41 | #define Z_STEP_PIN 35 42 | #define Z_DIR_PIN 47 43 | #define Z_MIN_PIN 10 44 | #define Z_MAX_PIN 23 45 | #define Z_ENABLE_PIN 27 46 | #define Z_MS1_PIN 68 47 | #define Z_MS2_PIN 67 48 | 49 | #define HEATER_BED_PIN 4 //PG5 50 | #define TEMP_BED_PIN 2 //A2 51 | 52 | #define HEATER_0_PIN 3 //PE5 53 | #define TEMP_0_PIN 0 //A0 54 | 55 | #define HEATER_1_PIN -1 56 | #define TEMP_1_PIN -1 //A1 57 | 58 | #define HEATER_2_PIN -1 59 | #define TEMP_2_PIN -1 60 | 61 | #define TEMP_AMBIENT_PIN 6 //A6 62 | 63 | #define TEMP_PINDA_PIN 1 //A1 64 | 65 | 66 | 67 | #define E0_STEP_PIN 34 68 | #define E0_DIR_PIN 43 69 | #define E0_ENABLE_PIN 26 70 | #define E0_MS1_PIN 65 71 | #define E0_MS2_PIN 66 72 | 73 | #ifdef SNMM 74 | #define E_MUX0_PIN 17 75 | #define E_MUX1_PIN 16 76 | #endif 77 | 78 | 79 | #define MOTOR_CURRENT_PWM_XY_PIN 46 80 | #define MOTOR_CURRENT_PWM_Z_PIN 45 81 | #define MOTOR_CURRENT_PWM_E_PIN 44 82 | #define SDPOWER -1 83 | #define SDSS 53 84 | #define LED_PIN 13 85 | #define FAN_PIN 6 86 | #define FAN_1_PIN -1 87 | #define PS_ON_PIN -1 88 | #define KILL_PIN -1 // 80 with Smart Controller LCD 89 | #define SUICIDE_PIN -1 // PIN that has to be turned on right after start, to keep power flowing. 90 | #define TACH_0 30 // noctua extruder fan 91 | 92 | 93 | //#define KILL_PIN 32 94 | 95 | 96 | #define BEEPER 84 // Beeper on AUX-4 97 | #define LCD_PINS_RS 82 98 | #define LCD_PINS_ENABLE 18 99 | #define LCD_PINS_D4 19 100 | #define LCD_PINS_D5 70 101 | #define LCD_PINS_D6 85 102 | #define LCD_PINS_D7 71 103 | 104 | //buttons are directly attached using AUX-2 105 | #define BTN_EN1 72 106 | #define BTN_EN2 14 107 | #define BTN_ENC 9 // the click 108 | 109 | #define SDCARDDETECT 15 110 | 111 | #define IR_SENSOR_PIN 20 //idler sensor 112 | 113 | // Support for an 8 bit logic analyzer, for example the Saleae. 114 | // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop. 115 | #define LOGIC_ANALYZER_CH0 X_MIN_PIN // PB6 116 | #define LOGIC_ANALYZER_CH1 Y_MIN_PIN // PB5 117 | #define LOGIC_ANALYZER_CH2 53 // PB0 (PROC_nCS) 118 | // Channels 3-7 are slow, they could generate 119 | // 0.889Mhz waveform with a software loop and interrupt locking, 120 | // 1.333MHz waveform without interrupt locking. 121 | #define LOGIC_ANALYZER_CH3 73 // PJ3 122 | // PK0 has no Arduino digital pin assigned, so we set it directly. 123 | #define WRITE_LOGIC_ANALYZER_CH4(value) if (value) PORTK |= (1 << 0); else PORTK &= ~(1 << 0) // PK0 124 | #define LOGIC_ANALYZER_CH5 16 // PH0 (RXD2) 125 | #define LOGIC_ANALYZER_CH6 17 // PH1 (TXD2) 126 | #define LOGIC_ANALYZER_CH7 76 // PJ5 127 | 128 | #define LOGIC_ANALYZER_CH0_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH0) 129 | #define LOGIC_ANALYZER_CH1_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH1) 130 | #define LOGIC_ANALYZER_CH2_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH2) 131 | #define LOGIC_ANALYZER_CH3_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH3) 132 | #define LOGIC_ANALYZER_CH4_ENABLE do { DDRK |= 1 << 0; } while (0) 133 | #define LOGIC_ANALYZER_CH5_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH5); } while (0) 134 | #define LOGIC_ANALYZER_CH6_ENABLE do { cbi(UCSR2B, TXEN2); cbi(UCSR2B, RXEN2); cbi(UCSR2B, RXCIE2); SET_OUTPUT(LOGIC_ANALYZER_CH6); } while (0) 135 | #define LOGIC_ANALYZER_CH7_ENABLE SET_OUTPUT(LOGIC_ANALYZER_CH7) 136 | 137 | -------------------------------------------------------------------------------- /Firmware/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 ??? is same as "MK2" ??? 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 | // *** MK3 30 | #define PRINTER_MK3 300 31 | #define PRINTER_MK3_NAME "MK3" 32 | #define PRINTER_MK3_MMU2 20300 33 | #define PRINTER_MK3_MMU2_NAME "MK3MMU2" 34 | // *** MK3S 35 | #define PRINTER_MK3S 302 36 | #define PRINTER_MK3S_NAME "MK3S" 37 | #define PRINTER_MK3S_MMU2 20302 38 | #define PRINTER_MK3S_MMU2_NAME "MK3SMMU2S" 39 | 40 | #endif //PRINTERS_H 41 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | } -------------------------------------------------------------------------------- /Firmware/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 -------------------------------------------------------------------------------- /Firmware/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 | 52 | 53 | #if defined(__cplusplus) 54 | } 55 | #endif //defined(__cplusplus) 56 | #endif //_SM4_H 57 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | // NOTE: currently not implemented 84 | void MultiU16X8toH16(unsigned short& intRes, unsigned char& charIn1, unsigned short& intIn2); 85 | void MultiU24X24toH16(uint16_t& intRes, int32_t& longIn1, long& longIn2); 86 | 87 | #endif //_NO_ASM 88 | 89 | 90 | FORCE_INLINE unsigned short calc_timer(uint16_t step_rate, uint8_t& step_loops) { 91 | unsigned short timer; 92 | if(step_rate > MAX_STEP_FREQUENCY) step_rate = MAX_STEP_FREQUENCY; 93 | 94 | if(step_rate > 20000) { // If steprate > 20kHz >> step 4 times 95 | step_rate = (step_rate >> 2)&0x3fff; 96 | step_loops = 4; 97 | } 98 | else if(step_rate > 10000) { // If steprate > 10kHz >> step 2 times 99 | step_rate = (step_rate >> 1)&0x7fff; 100 | step_loops = 2; 101 | } 102 | else { 103 | step_loops = 1; 104 | } 105 | 106 | if(step_rate < (F_CPU/500000)) step_rate = (F_CPU/500000); 107 | step_rate -= (F_CPU/500000); // Correct for minimal speed 108 | if(step_rate >= (8*256)){ // higher step rate 109 | unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate>>8)][0]; 110 | unsigned char tmp_step_rate = (step_rate & 0x00ff); 111 | unsigned short gain = (unsigned short)pgm_read_word_near(table_address+2); 112 | MultiU16X8toH16(timer, tmp_step_rate, gain); 113 | timer = (unsigned short)pgm_read_word_near(table_address) - timer; 114 | } 115 | else { // lower step rates 116 | unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0]; 117 | table_address += ((step_rate)>>1) & 0xfffc; 118 | timer = (unsigned short)pgm_read_word_near(table_address); 119 | timer -= (((unsigned short)pgm_read_word_near(table_address+2) * (unsigned char)(step_rate & 0x0007))>>3); 120 | } 121 | if(timer < 100) { timer = 100; }//(20kHz this should never happen)////MSG_STEPPER_TOO_HIGH c=0 r=0 122 | return timer; 123 | } 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /Firmware/spi.c: -------------------------------------------------------------------------------- 1 | //spi.c - hardware SPI 2 | //#ifdef __SPI 3 | 4 | #include "spi.h" 5 | #include 6 | 7 | 8 | //#endif //__SPI 9 | -------------------------------------------------------------------------------- /Firmware/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<. 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 81 | void digitalPotWrite(int address, int value); 82 | #endif //defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1 83 | void microstep_ms(uint8_t driver, int8_t ms1, int8_t ms2); 84 | void microstep_mode(uint8_t driver, uint8_t stepping); 85 | void st_current_init(); 86 | void st_current_set(uint8_t driver, int current); 87 | void microstep_init(); 88 | void microstep_readings(); 89 | 90 | #ifdef BABYSTEPPING 91 | void babystep(const uint8_t axis,const bool direction); // perform a short step with a single stepper motor, outside of any convention 92 | #endif 93 | 94 | #if defined(FILAMENT_SENSOR) && defined(PAT9125) 95 | // reset the internal filament sensor state 96 | void st_reset_fsensor(); 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/swi2c.c: -------------------------------------------------------------------------------- 1 | //swi2c.c 2 | #include "swi2c.h" 3 | #include 4 | #include 5 | #include 6 | #include "Configuration_prusa.h" 7 | #include "pins.h" 8 | #include "io_atmega2560.h" 9 | 10 | 11 | #define SWI2C_RMSK 0x01 //read mask (bit0 = 1) 12 | #define SWI2C_WMSK 0x00 //write mask (bit0 = 0) 13 | #define SWI2C_ASHF 0x01 //address shift (<< 1) 14 | #define SWI2C_DMSK 0x7f //device address mask 15 | 16 | 17 | void __delay(void) 18 | { 19 | _delay_us(1.5); 20 | } 21 | 22 | void swi2c_init(void) 23 | { 24 | PIN_OUT(SWI2C_SDA); 25 | PIN_OUT(SWI2C_SCL); 26 | PIN_SET(SWI2C_SDA); 27 | PIN_SET(SWI2C_SCL); 28 | uint8_t i; for (i = 0; i < 100; i++) 29 | __delay(); 30 | } 31 | 32 | void swi2c_start(void) 33 | { 34 | PIN_CLR(SWI2C_SDA); 35 | __delay(); 36 | PIN_CLR(SWI2C_SCL); 37 | __delay(); 38 | } 39 | 40 | void swi2c_stop(void) 41 | { 42 | PIN_SET(SWI2C_SCL); 43 | __delay(); 44 | PIN_SET(SWI2C_SDA); 45 | __delay(); 46 | } 47 | 48 | void swi2c_ack(void) 49 | { 50 | PIN_CLR(SWI2C_SDA); 51 | __delay(); 52 | PIN_SET(SWI2C_SCL); 53 | __delay(); 54 | PIN_CLR(SWI2C_SCL); 55 | __delay(); 56 | } 57 | 58 | uint8_t swi2c_wait_ack() 59 | { 60 | PIN_INP(SWI2C_SDA); 61 | __delay(); 62 | // PIN_SET(SWI2C_SDA); 63 | __delay(); 64 | PIN_SET(SWI2C_SCL); 65 | // __delay(); 66 | uint8_t ack = 0; 67 | uint16_t ackto = SWI2C_TMO; 68 | while (!(ack = (PIN_GET(SWI2C_SDA)?0:1)) && ackto--) __delay(); 69 | PIN_CLR(SWI2C_SCL); 70 | __delay(); 71 | PIN_OUT(SWI2C_SDA); 72 | __delay(); 73 | PIN_CLR(SWI2C_SDA); 74 | __delay(); 75 | return ack; 76 | } 77 | 78 | uint8_t swi2c_read(void) 79 | { 80 | PIN_SET(SWI2C_SDA); 81 | __delay(); 82 | PIN_INP(SWI2C_SDA); 83 | uint8_t data = 0; 84 | int8_t bit; for (bit = 7; bit >= 0; bit--) 85 | { 86 | PIN_SET(SWI2C_SCL); 87 | __delay(); 88 | data |= (PIN_GET(SWI2C_SDA)?1:0) << bit; 89 | PIN_CLR(SWI2C_SCL); 90 | __delay(); 91 | } 92 | PIN_OUT(SWI2C_SDA); 93 | return data; 94 | } 95 | 96 | void swi2c_write(uint8_t data) 97 | { 98 | int8_t bit; for (bit = 7; bit >= 0; bit--) 99 | { 100 | if (data & (1 << bit)) PIN_SET(SWI2C_SDA); 101 | else PIN_CLR(SWI2C_SDA); 102 | __delay(); 103 | PIN_SET(SWI2C_SCL); 104 | __delay(); 105 | PIN_CLR(SWI2C_SCL); 106 | __delay(); 107 | } 108 | } 109 | 110 | uint8_t swi2c_check(uint8_t dev_addr) 111 | { 112 | swi2c_start(); 113 | swi2c_write((dev_addr & SWI2C_DMSK) << SWI2C_ASHF); 114 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 115 | swi2c_stop(); 116 | return 1; 117 | } 118 | 119 | #ifdef SWI2C_A8 //8bit address 120 | 121 | uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte) 122 | { 123 | swi2c_start(); 124 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 125 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 126 | swi2c_write(addr & 0xff); 127 | if (!swi2c_wait_ack()) return 0; 128 | swi2c_stop(); 129 | swi2c_start(); 130 | swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 131 | if (!swi2c_wait_ack()) return 0; 132 | uint8_t byte = swi2c_read(); 133 | swi2c_stop(); 134 | if (pbyte) *pbyte = byte; 135 | return 1; 136 | } 137 | 138 | uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte) 139 | { 140 | swi2c_start(); 141 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 142 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 143 | swi2c_write(addr & 0xff); 144 | if (!swi2c_wait_ack()) return 0; 145 | swi2c_write(*pbyte); 146 | if (!swi2c_wait_ack()) return 0; 147 | swi2c_stop(); 148 | return 1; 149 | } 150 | 151 | #endif //SWI2C_A8 152 | 153 | #ifdef SWI2C_A16 //16bit address 154 | 155 | uint8_t swi2c_readByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte) 156 | { 157 | swi2c_start(); 158 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 159 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 160 | swi2c_write(addr >> 8); 161 | if (!swi2c_wait_ack()) return 0; 162 | swi2c_write(addr & 0xff); 163 | if (!swi2c_wait_ack()) return 0; 164 | swi2c_stop(); 165 | swi2c_start(); 166 | swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 167 | if (!swi2c_wait_ack()) return 0; 168 | uint8_t byte = swi2c_read(); 169 | swi2c_stop(); 170 | if (pbyte) *pbyte = byte; 171 | return 1; 172 | } 173 | 174 | uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte) 175 | { 176 | swi2c_start(); 177 | swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF)); 178 | if (!swi2c_wait_ack()) { swi2c_stop(); return 0; } 179 | swi2c_write(addr >> 8); 180 | if (!swi2c_wait_ack()) return 0; 181 | swi2c_write(addr & 0xff); 182 | if (!swi2c_wait_ack()) return 0; 183 | swi2c_write(*pbyte); 184 | if (!swi2c_wait_ack()) return 0; 185 | swi2c_stop(); 186 | return 1; 187 | } 188 | 189 | #endif //SWI2C_A16 190 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/swspi.cpp: -------------------------------------------------------------------------------- 1 | #include "uni_avr_rpi.h" 2 | 3 | #ifdef __SWSPI 4 | #include "swspi.h" 5 | 6 | #ifdef __RPI 7 | //#define swspi_miso 9 8 | #define swspi_miso 10 9 | #define swspi_mosi 10 10 | #define swspi_sck 11 11 | #define SWSPI_CS 7 12 | #endif //__RPI 13 | 14 | 15 | #define SWSPI_DEL 0x0f //delay mask (0-3. bit, delay = 1 << DEL [us]) 16 | #define SWSPI_POL 0x10 //polarity mask (4. bit, 1=inverted) 17 | #define SWSPI_PHA 0x20 //phase mask (5. bit) 18 | #define SWSPI_DOR 0x40 //data order mask (6. bit, 0=MSB first, 1=LSB first) 19 | 20 | #define SWSPI_SCK_UP if (swspi_cfg & SWSPI_POL) GPIO_CLR(swspi_sck); else GPIO_SET(swspi_sck); 21 | #define SWSPI_SCK_DN if (swspi_cfg & SWSPI_POL) GPIO_SET(swspi_sck); else GPIO_CLR(swspi_sck); 22 | 23 | unsigned char swspi_miso = 0; 24 | unsigned char swspi_mosi = 0; 25 | unsigned char swspi_sck = 0; 26 | unsigned char swspi_cfg = 0; 27 | 28 | void swspi_init(unsigned char miso, unsigned char mosi, unsigned char sck, unsigned char cfg) 29 | { 30 | swspi_miso = miso; 31 | swspi_mosi = mosi; 32 | swspi_sck = sck; 33 | swspi_cfg = cfg; 34 | GPIO_INP(swspi_miso); 35 | GPIO_OUT(swspi_mosi); 36 | GPIO_OUT(swspi_sck); 37 | GPIO_CLR(swspi_mosi); 38 | SWSPI_SCK_DN; 39 | } 40 | 41 | void swspi_tx(unsigned char tx) 42 | { 43 | int delay = 1 << (swspi_cfg & SWSPI_DEL)); 44 | if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi); 45 | unsigned char i = 0; for (; i < 8; i++) 46 | { 47 | if (tx & 0x80) GPIO_SET(swspi_mosi); 48 | else GPIO_CLR(swspi_mosi); 49 | DELAY(delay); 50 | SWSPI_SCK_UP; 51 | DELAY(delay); 52 | SWSPI_SCK_DN; 53 | tx <<= 1; 54 | } 55 | } 56 | 57 | unsigned char swspi_rx() 58 | { 59 | int delay = 1 << (swspi_cfg & SWSPI_DEL)); 60 | if (swspi_miso == swspi_mosi) GPIO_OUT(swspi_mosi); 61 | unsigned char rx = 0; 62 | unsigned char i = 0; for (; i < 8; i++) 63 | { 64 | rx <<= 1; 65 | DELAY(delay); 66 | SWSPI_SCK_UP; 67 | DELAY(delay); 68 | rx |= GPIO_GET(swspi_miso)?1:0; 69 | SWSPI_SCK_DN; 70 | } 71 | return rx; 72 | } 73 | 74 | unsigned char swspi_txrx(unsigned char tx) 75 | { 76 | int delay = 1 << (swspi_cfg & SWSPI_DEL)); 77 | unsigned char rx = 0; 78 | unsigned char i = 0; for (; i < 8; i++) 79 | { 80 | rx <<= 1; 81 | if (tx & 0x80) GPIO_SET(swspi_mosi); 82 | else GPIO_CLR(swspi_mosi); 83 | DELAY(delay); 84 | SWSPI_SCK_UP; 85 | DELAY(delay); 86 | rx |= GPIO_GET(swspi_miso)?1:0; 87 | SWSPI_SCK_DN; 88 | tx <<= 1; 89 | } 90 | return rx; 91 | } 92 | 93 | #endif //__SWSPI 94 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | #define _millis millis2 12 | #define _micros micros2 13 | #define _delay delay2 14 | #define _tone tone 15 | #define _noTone noTone 16 | 17 | #define timer02_set_pwm0(pwm0) 18 | 19 | #else //SYSTEM_TIMER_2 20 | #define _millis millis 21 | #define _micros micros 22 | #define _delay delay 23 | #define _tone tone 24 | #define _noTone noTone 25 | #define timer02_set_pwm0(pwm0) 26 | #endif //SYSTEM_TIMER_2 27 | 28 | #endif /* FIRMWARE_SYSTEM_TIMER_H_ */ 29 | -------------------------------------------------------------------------------- /Firmware/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 "io_atmega2560.h" 13 | 14 | #define BEEPER 84 15 | 16 | void timer0_init(void) 17 | { 18 | //save sreg 19 | uint8_t _sreg = SREG; 20 | //disable interrupts for sure 21 | cli(); 22 | 23 | TCNT0 = 0; 24 | // Fast PWM duty (0-255). 25 | // Due to invert mode (following rows) the duty is set to 255, which means zero all the time (bed not heating) 26 | OCR0B = 255; 27 | // Set fast PWM mode and inverting mode. 28 | TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B1) | (1 << COM0B0); 29 | TCCR0B = (1 << CS01); // CLK/8 prescaling 30 | TIMSK0 |= (1 << TOIE0); // enable timer overflow interrupt 31 | 32 | // Everything, that used to be on timer0 was moved to timer2 (delay, beeping, millis etc.) 33 | //setup timer2 34 | TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00 35 | TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011 36 | //mask timer2 interrupts - enable OVF, disable others 37 | TIMSK2 |= (1<> 3) 63 | #define FRACT_MAX (1000 >> 3) 64 | 65 | volatile unsigned long timer2_overflow_count; 66 | volatile unsigned long timer2_millis; 67 | unsigned char timer2_fract = 0; 68 | 69 | ISR(TIMER2_OVF_vect) 70 | { 71 | // copy these to local variables so they can be stored in registers 72 | // (volatile variables must be read from memory on every access) 73 | unsigned long m = timer2_millis; 74 | unsigned char f = timer2_fract; 75 | m += MILLIS_INC; 76 | f += FRACT_INC; 77 | if (f >= FRACT_MAX) 78 | { 79 | f -= FRACT_MAX; 80 | m += 1; 81 | } 82 | timer2_fract = f; 83 | timer2_millis = m; 84 | timer2_overflow_count++; 85 | } 86 | 87 | unsigned long millis2(void) 88 | { 89 | unsigned long m; 90 | uint8_t oldSREG = SREG; 91 | 92 | // disable interrupts while we read timer0_millis or we might get an 93 | // inconsistent value (e.g. in the middle of a write to timer0_millis) 94 | cli(); 95 | m = timer2_millis; 96 | SREG = oldSREG; 97 | 98 | return m; 99 | } 100 | 101 | unsigned long micros2(void) 102 | { 103 | unsigned long m; 104 | uint8_t oldSREG = SREG, t; 105 | cli(); 106 | m = timer2_overflow_count; 107 | #if defined(TCNT2) 108 | t = TCNT2; 109 | #elif defined(TCNT2L) 110 | t = TCNT2L; 111 | #else 112 | #error TIMER 2 not defined 113 | #endif 114 | #ifdef TIFR2 115 | if ((TIFR2 & _BV(TOV2)) && (t < 255)) 116 | m++; 117 | #else 118 | if ((TIFR & _BV(TOV2)) && (t < 255)) 119 | m++; 120 | #endif 121 | SREG = oldSREG; 122 | return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond()); 123 | } 124 | 125 | void delay2(unsigned long ms) 126 | { 127 | uint32_t start = micros2(); 128 | while (ms > 0) 129 | { 130 | yield(); 131 | while ( ms > 0 && (micros2() - start) >= 1000) 132 | { 133 | ms--; 134 | start += 1000; 135 | } 136 | } 137 | } 138 | 139 | #endif //SYSTEM_TIMER_2 140 | -------------------------------------------------------------------------------- /Firmware/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 | ///! Reimplemented original millis() using timer2 18 | extern unsigned long millis2(void); 19 | 20 | ///! Reimplemented original micros() using timer2 21 | extern unsigned long micros2(void); 22 | 23 | ///! Reimplemented original delay() using timer2 24 | extern void delay2(unsigned long ms); 25 | 26 | #if defined(__cplusplus) 27 | } 28 | #endif //defined(__cplusplus) 29 | 30 | #endif //TIMER02_H 31 | -------------------------------------------------------------------------------- /Firmware/tmc2130.h: -------------------------------------------------------------------------------- 1 | #ifndef TMC2130_H 2 | #define TMC2130_H 3 | 4 | 5 | //mode 6 | extern uint8_t tmc2130_mode; 7 | //holding and running currents 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 | #define TMC2130_MODE_NORMAL 0 26 | #define TMC2130_MODE_SILENT 1 27 | 28 | #define TMC2130_WAVE_FAC1000_MIN 30 29 | #define TMC2130_WAVE_FAC1000_MAX 200 30 | #define TMC2130_WAVE_FAC1000_STP 1 31 | 32 | extern uint8_t tmc2130_home_enabled; 33 | extern uint8_t tmc2130_home_origin[2]; 34 | extern uint8_t tmc2130_home_bsteps[2]; 35 | extern uint8_t tmc2130_home_fsteps[2]; 36 | 37 | extern uint8_t tmc2130_wave_fac[4]; 38 | 39 | #pragma pack(push) 40 | #pragma pack(1) 41 | typedef struct 42 | { 43 | uint8_t toff:4; 44 | uint8_t hstr:3; 45 | uint8_t hend:4; 46 | uint8_t tbl:2; 47 | uint8_t res:3; 48 | } tmc2130_chopper_config_t; 49 | #pragma pack(pop) 50 | 51 | extern tmc2130_chopper_config_t tmc2130_chopper_config[4]; 52 | 53 | //initialize tmc2130 54 | #ifdef PSU_Delta 55 | extern void tmc2130_init(bool bSupressFlag=false); 56 | #else 57 | extern void tmc2130_init(); 58 | #endif 59 | //check diag pins (called from stepper isr) 60 | extern void tmc2130_st_isr(); 61 | //update stall guard (called from st_synchronize inside the loop) 62 | extern bool tmc2130_update_sg(); 63 | //temperature watching (called from ) 64 | extern void tmc2130_check_overtemp(); 65 | //enter homing (called from homeaxis before homing starts) 66 | extern void tmc2130_home_enter(uint8_t axes_mask); 67 | //exit homing (called from homeaxis after homing ends) 68 | extern void tmc2130_home_exit(); 69 | 70 | //start stallguard meassuring for single axis 71 | extern void tmc2130_sg_meassure_start(uint8_t axis); 72 | //stop current stallguard meassuring and report result 73 | extern uint16_t tmc2130_sg_meassure_stop(); 74 | 75 | extern void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r); 76 | 77 | //set holding current for any axis (M911) 78 | extern void tmc2130_set_current_h(uint8_t axis, uint8_t current); 79 | //set running current for any axis (M912) 80 | extern void tmc2130_set_current_r(uint8_t axis, uint8_t current); 81 | //print currents (M913) 82 | extern void tmc2130_print_currents(); 83 | 84 | //set PWM_AMPL for any axis (M917) 85 | extern void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl); 86 | //set PWM_GRAD for any axis (M918) 87 | extern void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_ampl); 88 | 89 | 90 | extern uint16_t tmc2130_rd_MSCNT(uint8_t axis); 91 | extern uint32_t tmc2130_rd_MSCURACT(uint8_t axis); 92 | 93 | extern uint8_t tmc2130_usteps2mres(uint16_t usteps); 94 | #define tmc2130_mres2usteps(mres) ((uint16_t)256 >> mres) 95 | 96 | extern bool tmc2130_wait_standstill_xy(int timeout); 97 | 98 | extern uint16_t tmc2130_get_res(uint8_t axis); 99 | extern void tmc2130_set_res(uint8_t axis, uint16_t res); 100 | extern uint8_t tmc2130_get_pwr(uint8_t axis); 101 | extern void tmc2130_set_pwr(uint8_t axis, uint8_t pwr); 102 | extern uint8_t tmc2130_get_inv(uint8_t axis); 103 | extern uint8_t tmc2130_get_dir(uint8_t axis); 104 | extern void tmc2130_set_dir(uint8_t axis, uint8_t dir); 105 | extern void tmc2130_do_step(uint8_t axis); 106 | extern void tmc2130_do_steps(uint8_t axis, uint16_t steps, uint8_t dir, uint16_t delay_us); 107 | extern void tmc2130_goto_step(uint8_t axis, uint8_t step, uint8_t dir, uint16_t delay_us, uint16_t microstep_resolution); 108 | extern void tmc2130_get_wave(uint8_t axis, uint8_t* data, FILE* stream); 109 | extern void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000); 110 | 111 | extern bool tmc2130_home_calibrate(uint8_t axis); 112 | 113 | extern uint8_t tmc2130_cur2val(float cur); 114 | extern float tmc2130_val2cur(uint8_t val); 115 | 116 | #endif //TMC2130_H 117 | -------------------------------------------------------------------------------- /Firmware/uart2.c: -------------------------------------------------------------------------------- 1 | //uart2.c 2 | #include "uart2.h" 3 | #include 4 | #include 5 | #include 6 | #include "rbuf.h" 7 | 8 | #define UART2_BAUD 115200 9 | #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5) 10 | #define uart2_rxcomplete (UCSR2A & (1 << RXC2)) 11 | #define uart2_txcomplete (UCSR2A & (1 << TXC2)) 12 | #define uart2_txready (UCSR2A & (1 << UDRE2)) 13 | 14 | uint8_t uart2_ibuf[14] = {0, 0}; 15 | 16 | FILE _uart2io = {0}; 17 | 18 | 19 | int uart2_putchar(char c, FILE *stream __attribute__((unused))) 20 | { 21 | while (!uart2_txready); 22 | UDR2 = c; // transmit byte 23 | // while (!uart2_txcomplete); // wait until byte sent 24 | // UCSR2A |= (1 << TXC2); // delete TXCflag 25 | return 0; 26 | } 27 | 28 | int uart2_getchar(FILE *stream __attribute__((unused))) 29 | { 30 | if (rbuf_empty(uart2_ibuf)) return -1; 31 | return rbuf_get(uart2_ibuf); 32 | } 33 | 34 | //uart init (io + FILE stream) 35 | void uart2_init(void) 36 | { 37 | DDRH &= ~0x01; 38 | PORTH |= 0x01; 39 | rbuf_ini(uart2_ibuf, sizeof(uart2_ibuf) - 4); 40 | UCSR2A |= (1 << U2X2); // baudrate multiplier 41 | UBRR2L = UART_BAUD_SELECT(UART2_BAUD, F_CPU); // select baudrate 42 | UCSR2B = (1 << RXEN2) | (1 << TXEN2); // enable receiver and transmitter 43 | UCSR2B |= (1 << RXCIE2); // enable rx interrupt 44 | fdev_setup_stream(uart2io, uart2_putchar, uart2_getchar, _FDEV_SETUP_WRITE | _FDEV_SETUP_READ); //setup uart2 i/o stream 45 | } 46 | 47 | //returns 1 if chars in input buffer match to str 48 | //returns -1 if chars does not match and 0 for empty buffer 49 | int8_t uart2_rx_str_P(const char* str) 50 | { 51 | uint8_t r = rbuf_r(uart2_ibuf); //get read index 52 | uint8_t w = rbuf_w(uart2_ibuf); //get write index 53 | // printf_P(PSTR("uart2_rx_str_P r=%d w=%d\n"), r, w); 54 | uint8_t e = rbuf_l(uart2_ibuf) - 1; //get end index 55 | uint8_t len = strlen_P(str); //get string length 56 | str += len; //last char will be compared first 57 | // printf_P(PSTR(" len=%d\n"), len); 58 | while (len--) //loop over all chars 59 | { 60 | if (w == r) return 0; //empty buffer - return 0 61 | if ((--w) == 255) w = e; //decrement index 62 | char c0 = pgm_read_byte(--str); //read char from str 63 | char c1 = uart2_ibuf[4 + w]; //read char from input buffer 64 | // printf_P(PSTR(" uart2_rx_str_P w=%d l=%d c0=%02x c1=%02x\n"), w, len, c0, c1); 65 | if (c0 == c1) continue; //if match, continue with next char 66 | if ((c0 == '\r') && (c1 == '\n')) //match cr as lf 67 | continue; 68 | if ((c0 == '\n') && (c1 == '\r')) //match lf as cr 69 | continue; 70 | return -1; //no match - return -1 71 | } 72 | return 1; //all characters match - return 1 73 | } 74 | 75 | ISR(USART2_RX_vect) 76 | { 77 | //printf_P(PSTR("USART2_RX_vect \n") ); 78 | if (rbuf_put(uart2_ibuf, UDR2) < 0) // put received byte to buffer 79 | { //rx buffer full 80 | //uart2_rx_clr(); //for sure, clear input buffer 81 | printf_P(PSTR("USART2 rx Full!!!\n")); 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /Firmware/uart2.h: -------------------------------------------------------------------------------- 1 | //uart2.h 2 | #ifndef _UART2_H 3 | #define _UART2_H 4 | 5 | #include 6 | #include 7 | 8 | 9 | #if defined(__cplusplus) 10 | extern "C" { 11 | #endif //defined(__cplusplus) 12 | 13 | 14 | extern FILE _uart2io; 15 | #define uart2io (&_uart2io) 16 | 17 | 18 | extern void uart2_init(void); 19 | 20 | extern int8_t uart2_rx_str_P(const char* str); 21 | 22 | 23 | #if defined(__cplusplus) 24 | } 25 | #endif //defined(__cplusplus) 26 | #endif //_UART2_H 27 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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_Undef=EEPROM_EMPTY_VALUE 55 | }; 56 | 57 | enum class ClCheckMode:uint_least8_t 58 | { 59 | _None, 60 | _Warn, 61 | _Strict, 62 | _Undef=EEPROM_EMPTY_VALUE 63 | }; 64 | 65 | enum class ClCheckModel:uint_least8_t 66 | { 67 | _None, 68 | _Warn, 69 | _Strict, 70 | _Undef=EEPROM_EMPTY_VALUE 71 | }; 72 | 73 | enum class ClCheckVersion:uint_least8_t 74 | { 75 | _None, 76 | _Warn, 77 | _Strict, 78 | _Undef=EEPROM_EMPTY_VALUE 79 | }; 80 | 81 | enum class ClCheckGcode:uint_least8_t 82 | { 83 | _None, 84 | _Warn, 85 | _Strict, 86 | _Undef=EEPROM_EMPTY_VALUE 87 | }; 88 | 89 | #define COMPARE_VALUE_EQUAL (((uint8_t)ClCompareValue::_Equal<<6)+((uint8_t)ClCompareValue::_Equal<<4)+((uint8_t)ClCompareValue::_Equal<<2)+((uint8_t)ClCompareValue::_Equal)) 90 | enum class ClCompareValue:uint_least8_t 91 | { 92 | _Less=0, 93 | _Equal=1, 94 | _Greater=2 95 | }; 96 | 97 | extern ClNozzleDiameter oNozzleDiameter; 98 | extern ClCheckMode oCheckMode; 99 | extern ClCheckModel oCheckModel; 100 | extern ClCheckVersion oCheckVersion; 101 | extern ClCheckGcode oCheckGcode; 102 | 103 | void fCheckModeInit(); 104 | void nozzle_diameter_check(uint16_t nDiameter); 105 | void printer_model_check(uint16_t nPrinterModel); 106 | void printer_smodel_check(char* pStrPos); 107 | void fw_version_check(const char *pVersion); 108 | void gcode_level_check(uint16_t nGcodeLevel); 109 | 110 | void fSetMmuMode(bool bMMu); 111 | 112 | #endif /* UTIL_H */ 113 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/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 | -------------------------------------------------------------------------------- /Firmware/w25x20cl.c: -------------------------------------------------------------------------------- 1 | //w25x20cl.c 2 | 3 | #include "w25x20cl.h" 4 | #include 5 | #include 6 | #include "io_atmega2560.h" 7 | #include "spi.h" 8 | 9 | #define _MFRID 0xEF 10 | #define _DEVID 0x11 11 | 12 | #define _CMD_ENABLE_WR 0x06 13 | #define _CMD_ENABLE_WR_VSR 0x50 14 | #define _CMD_DISABLE_WR 0x04 15 | #define _CMD_RD_STATUS_REG 0x05 16 | #define _CMD_WR_STATUS_REG 0x01 17 | #define _CMD_RD_DATA 0x03 18 | #define _CMD_RD_FAST 0x0b 19 | #define _CMD_RD_FAST_D_O 0x3b 20 | #define _CMD_RD_FAST_D_IO 0xbb 21 | #define _CMD_PAGE_PROGRAM 0x02 22 | #define _CMD_SECTOR_ERASE 0x20 23 | #define _CMD_BLOCK32_ERASE 0x52 24 | #define _CMD_BLOCK64_ERASE 0xd8 25 | #define _CMD_CHIP_ERASE 0xc7 26 | #define _CMD_CHIP_ERASE2 0x60 27 | #define _CMD_PWR_DOWN 0xb9 28 | #define _CMD_PWR_DOWN_REL 0xab 29 | #define _CMD_MFRID_DEVID 0x90 30 | #define _CMD_MFRID_DEVID_D 0x92 31 | #define _CMD_JEDEC_ID 0x9f 32 | #define _CMD_RD_UID 0x4b 33 | 34 | #define _CS_LOW() PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS) 35 | #define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS) 36 | 37 | //#define _SPI_TX swspi_tx 38 | //#define _SPI_RX swspi_rx 39 | #define _SPI_TX(b) spi_txrx(b) 40 | #define _SPI_RX() spi_txrx(0xff) 41 | 42 | 43 | int w25x20cl_mfrid_devid(void); 44 | 45 | 46 | int8_t w25x20cl_init(void) 47 | { 48 | PIN_OUT(W25X20CL_PIN_CS); 49 | _CS_HIGH(); 50 | W25X20CL_SPI_ENTER(); 51 | if (!w25x20cl_mfrid_devid()) return 0; 52 | return 1; 53 | } 54 | 55 | void w25x20cl_enable_wr(void) 56 | { 57 | _CS_LOW(); 58 | _SPI_TX(_CMD_ENABLE_WR); // send command 0x06 59 | _CS_HIGH(); 60 | } 61 | 62 | void w25x20cl_disable_wr(void) 63 | { 64 | _CS_LOW(); 65 | _SPI_TX(_CMD_DISABLE_WR); // send command 0x04 66 | _CS_HIGH(); 67 | } 68 | 69 | uint8_t w25x20cl_rd_status_reg(void) 70 | { 71 | _CS_LOW(); 72 | _SPI_TX(_CMD_RD_STATUS_REG); // send command 0x90 73 | uint8_t val = _SPI_RX(); // receive value 74 | _CS_HIGH(); 75 | return val; 76 | } 77 | 78 | void w25x20cl_wr_status_reg(uint8_t val) 79 | { 80 | _CS_LOW(); 81 | _SPI_TX(_CMD_WR_STATUS_REG); // send command 0x90 82 | _SPI_TX(val); // send value 83 | _CS_HIGH(); 84 | } 85 | 86 | void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt) 87 | { 88 | _CS_LOW(); 89 | _SPI_TX(_CMD_RD_DATA); // send command 0x03 90 | _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 91 | _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 92 | _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 93 | while (cnt--) // receive data 94 | *(data++) = _SPI_RX(); 95 | _CS_HIGH(); 96 | } 97 | 98 | void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt) 99 | { 100 | _CS_LOW(); 101 | _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 102 | _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 103 | _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 104 | _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 105 | while (cnt--) // send data 106 | _SPI_TX(*(data++)); 107 | _CS_HIGH(); 108 | } 109 | 110 | void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt) 111 | { 112 | _CS_LOW(); 113 | _SPI_TX(_CMD_PAGE_PROGRAM); // send command 0x02 114 | _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 115 | _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 116 | _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 117 | while (cnt--) // send data 118 | _SPI_TX(pgm_read_byte(data++)); 119 | _CS_HIGH(); 120 | } 121 | 122 | void w25x20cl_erase(uint8_t cmd, uint32_t addr) 123 | { 124 | _CS_LOW(); 125 | _SPI_TX(cmd); // send command 0x20 126 | _SPI_TX(((uint8_t*)&addr)[2]); // send addr bits 16..23 127 | _SPI_TX(((uint8_t*)&addr)[1]); // send addr bits 8..15 128 | _SPI_TX(((uint8_t*)&addr)[0]); // send addr bits 0..7 129 | _CS_HIGH(); 130 | } 131 | 132 | void w25x20cl_sector_erase(uint32_t addr) 133 | { 134 | return w25x20cl_erase(_CMD_SECTOR_ERASE, addr); 135 | } 136 | 137 | void w25x20cl_block32_erase(uint32_t addr) 138 | { 139 | return w25x20cl_erase(_CMD_BLOCK32_ERASE, addr); 140 | } 141 | 142 | void w25x20cl_block64_erase(uint32_t addr) 143 | { 144 | return w25x20cl_erase(_CMD_BLOCK64_ERASE, addr); 145 | } 146 | 147 | void w25x20cl_chip_erase(void) 148 | { 149 | _CS_LOW(); 150 | _SPI_TX(_CMD_CHIP_ERASE); // send command 0xc7 151 | _CS_HIGH(); 152 | } 153 | 154 | 155 | void w25x20cl_rd_uid(uint8_t* uid) 156 | { 157 | _CS_LOW(); 158 | _SPI_TX(_CMD_RD_UID); // send command 0x4b 159 | uint8_t cnt = 4; // 4 dummy bytes 160 | while (cnt--) // receive dummy bytes 161 | _SPI_RX(); 162 | cnt = 8; // 8 bytes UID 163 | while (cnt--) // receive UID 164 | uid[7 - cnt] = _SPI_RX(); 165 | _CS_HIGH(); 166 | } 167 | 168 | int w25x20cl_mfrid_devid(void) 169 | { 170 | _CS_LOW(); 171 | _SPI_TX(_CMD_MFRID_DEVID); // send command 0x90 172 | uint8_t cnt = 3; // 3 address bytes 173 | while (cnt--) // send address bytes 174 | _SPI_TX(0x00); 175 | uint8_t w25x20cl_mfrid = _SPI_RX(); // receive mfrid 176 | uint8_t w25x20cl_devid = _SPI_RX(); // receive devid 177 | _CS_HIGH(); 178 | return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID)); 179 | } 180 | 181 | void w25x20cl_wait_busy(void) 182 | { 183 | while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ; 184 | } 185 | -------------------------------------------------------------------------------- /Firmware/w25x20cl.h: -------------------------------------------------------------------------------- 1 | //w25x20cl.h 2 | #ifndef _W25X20CL_H 3 | #define _W25X20CL_H 4 | 5 | #include 6 | #include "config.h" 7 | #include "spi.h" 8 | 9 | 10 | 11 | #define W25X20CL_STATUS_BUSY 0x01 12 | #define W25X20CL_STATUS_WEL 0x02 13 | #define W25X20CL_STATUS_BP0 0x04 14 | #define W25X20CL_STATUS_BP1 0x08 15 | #define W25X20CL_STATUS_TB 0x20 16 | #define W25X20CL_STATUS_SRP 0x80 17 | 18 | #define W25X20CL_SPI_ENTER() spi_setup(W25X20CL_SPCR, W25X20CL_SPSR) 19 | 20 | #if defined(__cplusplus) 21 | extern "C" { 22 | #endif //defined(__cplusplus) 23 | 24 | 25 | extern int8_t w25x20cl_init(void); 26 | extern void w25x20cl_enable_wr(void); 27 | extern void w25x20cl_disable_wr(void); 28 | extern uint8_t w25x20cl_rd_status_reg(void); 29 | extern void w25x20cl_wr_status_reg(uint8_t val); 30 | extern void w25x20cl_rd_data(uint32_t addr, uint8_t* data, uint16_t cnt); 31 | extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); 32 | extern void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt); 33 | extern void w25x20cl_sector_erase(uint32_t addr); 34 | extern void w25x20cl_block32_erase(uint32_t addr); 35 | extern void w25x20cl_block64_erase(uint32_t addr); 36 | extern void w25x20cl_chip_erase(void); 37 | extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt); 38 | extern void w25x20cl_rd_uid(uint8_t* uid); 39 | extern void w25x20cl_wait_busy(void); 40 | 41 | #if defined(__cplusplus) 42 | } 43 | #endif //defined(__cplusplus) 44 | #endif //_W25X20CL_H 45 | -------------------------------------------------------------------------------- /Firmware/xyzcal.h: -------------------------------------------------------------------------------- 1 | //xyzcal.h - xyz calibration with image processing 2 | #ifndef _XYZCAL_H 3 | #define _XYZCAL_H 4 | 5 | #include 6 | 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 void xyzcal_scan_pixels_32x32(int16_t cx, int16_t cy, int16_t min_z, int16_t max_z, uint16_t delay_us, uint8_t* pixels); 21 | 22 | extern void xyzcal_histo_pixels_32x32(uint8_t* pixels, uint16_t* histo); 23 | 24 | extern void xyzcal_adjust_pixels(uint8_t* pixels, uint16_t* histo); 25 | 26 | extern int16_t xyzcal_match_pattern_12x12_in_32x32(uint16_t* pattern, uint8_t* pixels, uint8_t x, uint8_t y); 27 | 28 | extern int16_t xyzcal_find_pattern_12x12_in_32x32(uint8_t* pixels, uint16_t* pattern, uint8_t* pc, uint8_t* pr); 29 | 30 | extern int8_t xyzcal_find_point_center2(uint16_t delay_us); 31 | 32 | //extern int8_t xyzcal_find_point_center(int16_t x0, int16_t y0, int16_t z0, int16_t min_z, int16_t max_z, uint16_t delay_us, uint8_t turns); 33 | 34 | extern bool xyzcal_searchZ(void); 35 | 36 | extern bool xyzcal_scan_and_process(void); 37 | 38 | extern bool xyzcal_find_bed_induction_sensor_point_xy(void); 39 | 40 | 41 | #endif //_XYZCAL_H 42 | -------------------------------------------------------------------------------- /README_cz.md: -------------------------------------------------------------------------------- 1 | # 1. Příprava vývojového prostředí 2 | 3 | 1. nainstalujte vývojové prostředí `"Arduino Software IDE"` pro operační prostředí, které jste zvyklí používat 4 | `https://www.arduino.cc -> Software->Downloads` 5 | doporučujeme použít starší verzi `"1.6.9"`, kterou používáme na našem build serveru pro překlad oficiálních buildů 6 | _pozn.: v případě přetrvávajících potíží s překladem zkontrolujte verzi aktuálně použitého překladače jazyka C/C++ (GCC) - měla by být `4.8.1`; verzi ověříte zadáním příkazu 7 | `avr-gcc --version` 8 | pokud si nejste jisti umístěním souboru (závisí na způsobu, jakým bylo `"Arduino Software IDE"` nainstalováno), použijte funkci vyhledání v rámci systému souborů_ 9 | _pozn.: konflikt názvů knihoven / modulů `"LiquidCrystal"` známý v předchozích verzích již není aktuální (původní knihovnu tudíž není nutné mazat ani přejmenovat)_ 10 | 11 | 2. do nabídky podporovaných cílových desek Arduino přidejte desku (`UltiMachine`) `RAMBo` 12 | `File->Preferences->Settings` 13 | do pole `"Additional Boards Manager URLs"` 14 | vložte adresu / text 15 | `"https://raw.githubusercontent.com/ultimachine/ArduinoAddons/master/package_ultimachine_index.json"` 16 | ev. je možno 'ručně upravit' položku 17 | `"boardsmanager.additional.urls=....."` 18 | v souboru `"preferences.txt"` (parametr umožňuje zápis seznamu adres oddělených čárkami) 19 | _pozn.: konkrétní umístění tohoto souboru na Vašem disku lze zjistit následujícím způsobem: 20 | `File->Preferences->Settings` (`"More preferences can be edited in file ..."`)_ 21 | následně proveďte 22 | `Tools->Board->BoardsManager` 23 | ze zobrazeného seznamu vyberte položku `"RAMBo"` (pravděpodobně bude označena jako `"RepRap Arduino-compatible Mother Board (RAMBo) by UltiMachine"` 24 | _pozn.: tuto položku zvolte pro všechny varianty desek použitých v tiskárnách `'Prusa i3 MKx'`, tzn. pro `RAMBo-mini x.y` i `EINSy x.y`_ 25 | 'kliknutím' na položku se zobrazí tlačítko pro instalaci; ve výběrovém seznamu zvolte verzi `"1.0.1"` (poslední známá verze k datu vydání tohoto dokumentu) 26 | _(po provedení instalace je položka označena poznámkou `"INSTALLED"` a lze ji následně použít při výběru cílové desky)_ 27 | 28 | 3. modify platform.txt to enable float printf support: 29 | add "-Wl,-u,vfprintf -lprintf_flt -lm" to "compiler.c.elf.flags=" before existing flag "-Wl,--gc-sections" 30 | example: 31 | `"compiler.c.elf.flags=-w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections"` 32 | 33 | # 2. Překlad zdrojoveho kódu 34 | 35 | do zvoleného adresáře umístěte zdrojové kódy odpovídající modelu Vaší tiskárny získané z repozitáře 36 | `https://github.com/prusa3d/Prusa-Firmware/` 37 | v podadresáři `"Firmware/variants/"` vyberte konfigurační soubor (`.h`) odpovídající modelu Vaší tiskárny, vytvořte kopii s názvem `"Configuration_prusa.h"` (popř. proveďte prosté přejmenování) a překopírujte do adresáře `"Firmware/"` 38 | 39 | spusťte vývojové prostředí `"Arduino IDE"`; v adresáři, kam jste umístili zdrojové kódy, vyberte z podadresáře `"Firmware/"` soubor `"Firmware.ino"` 40 | `File->Open` 41 | proveďte požadované úpravy kódu; **veškeré změny ovšem provádíte na svou vlastní odpovědnost!** 42 | 43 | jako cílovou desku pro překlad vyberte `"RAMBo"` 44 | `Tools->Board->RAMBo` 45 | _pozn.: nelze použít žádnou z variant `"Arduino Mega …"`, přestože se jedná o shodný MCU_ 46 | 47 | spusťte překlad 48 | `Sketch->Verify/Compile` 49 | 50 | výsledný kód nahrajte do připojené tiskárny 51 | `Sketch->Upload` 52 | 53 | přeložený kód můžete také nechat uložit do souboru (v tzv. `HEX`-formátu) `"Firmware.ino.rambo.hex"`: 54 | `Sketch->ExportCompiledBinary` 55 | a do tiskárny ho následně nahrát pomocí programu `"FirmwareUpdater"` 56 | _pozn.: soubor je vytvořen v adresáři `"Firmware/"`_ 57 | -------------------------------------------------------------------------------- /Tests/Arduino.h: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @brief Mock file to allow test compilation. 4 | * @author Marek Bel 5 | */ 6 | 7 | #ifndef TESTS_ARDUINO_H_ 8 | #define TESTS_ARDUINO_H_ 9 | 10 | extern unsigned long millis(); 11 | 12 | #endif /* TESTS_ARDUINO_H_ */ 13 | -------------------------------------------------------------------------------- /Tests/AutoDeplete_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Marek Bel 4 | */ 5 | 6 | #include "catch.hpp" 7 | 8 | #include "../Firmware/AutoDeplete.h" 9 | 10 | TEST_CASE( "AutoDeplete test.", "[AutoDeplete]" ) 11 | { 12 | CHECK(ad_allDepleted() == false); 13 | 14 | CHECK(ad_getAlternative(0) == 0); 15 | CHECK(ad_getAlternative(1) == 1); 16 | CHECK(ad_getAlternative(2) == 2); 17 | CHECK(ad_getAlternative(3) == 3); 18 | CHECK(ad_getAlternative(4) == 4); 19 | 20 | ad_markDepleted(1); 21 | 22 | CHECK(ad_getAlternative(0) == 0); 23 | CHECK(ad_getAlternative(1) == 2); 24 | CHECK(ad_getAlternative(2) == 2); 25 | CHECK(ad_getAlternative(3) == 3); 26 | CHECK(ad_getAlternative(4) == 4); 27 | CHECK(ad_allDepleted() == false); 28 | 29 | ad_markDepleted(3); 30 | 31 | CHECK(ad_getAlternative(0) == 0); 32 | CHECK(ad_getAlternative(1) == 2); 33 | CHECK(ad_getAlternative(2) == 2); 34 | CHECK(ad_getAlternative(3) == 4); 35 | CHECK(ad_getAlternative(4) == 4); 36 | CHECK(ad_allDepleted() == false); 37 | 38 | ad_markDepleted(4); 39 | 40 | CHECK(ad_getAlternative(0) == 0); 41 | CHECK(ad_getAlternative(1) == 2); 42 | CHECK(ad_getAlternative(2) == 2); 43 | CHECK(ad_getAlternative(3) == 0); 44 | CHECK(ad_getAlternative(4) == 0); 45 | CHECK(ad_allDepleted() == false); 46 | 47 | ad_markDepleted(4); 48 | 49 | CHECK(ad_getAlternative(0) == 0); 50 | CHECK(ad_getAlternative(1) == 2); 51 | CHECK(ad_getAlternative(2) == 2); 52 | CHECK(ad_getAlternative(3) == 0); 53 | CHECK(ad_getAlternative(4) == 0); 54 | CHECK(ad_allDepleted() == false); 55 | 56 | ad_markDepleted(0); 57 | 58 | CHECK(ad_getAlternative(0) == 2); 59 | CHECK(ad_getAlternative(1) == 2); 60 | CHECK(ad_getAlternative(2) == 2); 61 | CHECK(ad_getAlternative(3) == 2); 62 | CHECK(ad_getAlternative(4) == 2); 63 | CHECK(ad_allDepleted() == false); 64 | 65 | ad_markDepleted(2); 66 | 67 | CHECK(ad_getAlternative(0) == 0); 68 | CHECK(ad_getAlternative(1) == 1); 69 | CHECK(ad_getAlternative(2) == 2); 70 | CHECK(ad_getAlternative(3) == 3); 71 | CHECK(ad_getAlternative(4) == 4); 72 | CHECK(ad_allDepleted() == true); 73 | 74 | ad_markDepleted(2); 75 | 76 | CHECK(ad_getAlternative(0) == 0); 77 | CHECK(ad_getAlternative(1) == 1); 78 | CHECK(ad_getAlternative(2) == 2); 79 | CHECK(ad_getAlternative(3) == 3); 80 | CHECK(ad_getAlternative(4) == 4); 81 | CHECK(ad_allDepleted() == true); 82 | 83 | ad_markLoaded(4); 84 | 85 | CHECK(ad_getAlternative(0) == 4); 86 | CHECK(ad_getAlternative(1) == 4); 87 | CHECK(ad_getAlternative(2) == 4); 88 | CHECK(ad_getAlternative(3) == 4); 89 | CHECK(ad_getAlternative(4) == 4); 90 | CHECK(ad_allDepleted() == false); 91 | 92 | ad_markLoaded(0); 93 | 94 | CHECK(ad_getAlternative(0) == 0); 95 | CHECK(ad_getAlternative(1) == 4); 96 | CHECK(ad_getAlternative(2) == 4); 97 | CHECK(ad_getAlternative(3) == 4); 98 | CHECK(ad_getAlternative(4) == 4); 99 | CHECK(ad_allDepleted() == false); 100 | 101 | ad_markLoaded(3); 102 | 103 | CHECK(ad_getAlternative(0) == 0); 104 | CHECK(ad_getAlternative(1) == 3); 105 | CHECK(ad_getAlternative(2) == 3); 106 | CHECK(ad_getAlternative(3) == 3); 107 | CHECK(ad_getAlternative(4) == 4); 108 | CHECK(ad_allDepleted() == false); 109 | 110 | ad_markLoaded(3); 111 | 112 | CHECK(ad_getAlternative(0) == 0); 113 | CHECK(ad_getAlternative(1) == 3); 114 | CHECK(ad_getAlternative(2) == 3); 115 | CHECK(ad_getAlternative(3) == 3); 116 | CHECK(ad_getAlternative(4) == 4); 117 | CHECK(ad_allDepleted() == false); 118 | 119 | ad_markLoaded(2); 120 | 121 | CHECK(ad_getAlternative(0) == 0); 122 | CHECK(ad_getAlternative(1) == 2); 123 | CHECK(ad_getAlternative(2) == 2); 124 | CHECK(ad_getAlternative(3) == 3); 125 | CHECK(ad_getAlternative(4) == 4); 126 | CHECK(ad_allDepleted() == false); 127 | 128 | ad_markLoaded(1); 129 | 130 | CHECK(ad_getAlternative(0) == 0); 131 | CHECK(ad_getAlternative(1) == 1); 132 | CHECK(ad_getAlternative(2) == 2); 133 | CHECK(ad_getAlternative(3) == 3); 134 | CHECK(ad_getAlternative(4) == 4); 135 | CHECK(ad_allDepleted() == false); 136 | 137 | ad_markLoaded(1); 138 | 139 | CHECK(ad_getAlternative(0) == 0); 140 | CHECK(ad_getAlternative(1) == 1); 141 | CHECK(ad_getAlternative(2) == 2); 142 | CHECK(ad_getAlternative(3) == 3); 143 | CHECK(ad_getAlternative(4) == 4); 144 | CHECK(ad_allDepleted() == false); 145 | 146 | } 147 | -------------------------------------------------------------------------------- /Tests/Example_test.cpp: -------------------------------------------------------------------------------- 1 | #include "catch.hpp" 2 | 3 | unsigned int Factorial( unsigned int number ) { 4 | return number <= 1 ? number : Factorial(number-1)*number; 5 | } 6 | 7 | TEST_CASE( "Factorials are computed", "[factorial]" ) { 8 | REQUIRE( Factorial(1) == 1 ); 9 | REQUIRE( Factorial(2) == 2 ); 10 | REQUIRE( Factorial(3) == 6 ); 11 | REQUIRE( Factorial(10) == 3628800 ); 12 | } 13 | -------------------------------------------------------------------------------- /Tests/Timer_test.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @author Marek Bel 4 | */ 5 | 6 | 7 | #include "catch.hpp" 8 | #include "../Firmware/Timer.h" 9 | #include "../Firmware/TimerRemaining.h" 10 | 11 | static unsigned long now = 0; 12 | 13 | unsigned long millis() 14 | { 15 | return now; 16 | } 17 | 18 | unsigned long millis2() 19 | { 20 | return now; 21 | } 22 | 23 | static void basicTimer() 24 | { 25 | LongTimer timer; 26 | CHECK( timer.running() == false); 27 | 28 | timer.start(); 29 | CHECK( timer.running() == true); 30 | 31 | timer.stop(); 32 | CHECK( timer.running() == false); 33 | 34 | timer.start(); 35 | CHECK( timer.expired(0) == true); 36 | CHECK( timer.expired(0) == false); 37 | CHECK( timer.running() == false); 38 | 39 | timer.start(); 40 | CHECK( timer.expired(1) == false); 41 | CHECK( timer.running() == true); 42 | ++now; 43 | CHECK( timer.expired(1) == true); 44 | CHECK( timer.running() == false); 45 | --now; 46 | 47 | timer.start(); 48 | CHECK( timer.expired(ULONG_MAX - 1) == false); 49 | now+= ULONG_MAX - 2; 50 | CHECK( timer.expired(ULONG_MAX - 1) == false); 51 | now++; 52 | CHECK( timer.expired(ULONG_MAX - 1) == true); 53 | CHECK( timer.running() == false); 54 | now-= ULONG_MAX - 1; 55 | 56 | timer.start(); 57 | CHECK( timer.expired(ULONG_MAX) == false); 58 | now+= ULONG_MAX - 1; 59 | CHECK( timer.expired(ULONG_MAX) == false); 60 | now++; 61 | CHECK( timer.expired(ULONG_MAX) == true); 62 | CHECK( timer.running() == false); 63 | now-= ULONG_MAX; 64 | 65 | timer.start(); 66 | CHECK( timer.running() == true); 67 | CHECK( timer.expired(12*3600000ul + 38*60000ul + 15000) == false); 68 | now+= 12*3600000ul + 38*60000ul + 14999; 69 | CHECK( timer.expired(12*3600000ul + 38*60000ul + 15000) == false); 70 | ++now; 71 | CHECK( timer.expired(12*3600000ul + 38*60000ul + 15000) == true); 72 | CHECK( timer.running() == false); 73 | now-= 12*3600000ul + 38*60000ul + 15000; 74 | 75 | } 76 | 77 | TEST_CASE( "LongTimer test.", "[timer]" ) 78 | { 79 | now = 0; 80 | basicTimer(); 81 | now = 1; 82 | basicTimer(); 83 | now = ULONG_MAX; 84 | basicTimer(); 85 | now = ULONG_MAX - 1; 86 | basicTimer(); 87 | now = 12*3600000ul + 38*60000ul + 15000; 88 | basicTimer(); 89 | } 90 | 91 | static void basicRemaining() 92 | { 93 | TimerRemaining timer; 94 | CHECK( timer.running() == false); 95 | CHECK( timer.remaining() == 0); 96 | 97 | timer.start(100); 98 | CHECK( timer.running() == true); 99 | CHECK( timer.remaining() == 100); 100 | now += 99; 101 | CHECK( timer.running() == true); 102 | CHECK( timer.remaining() == 1); 103 | 104 | ++now; 105 | CHECK( timer.running() == true); 106 | CHECK( timer.remaining() == 0); 107 | CHECK( timer.running() == false); 108 | now -=100; 109 | 110 | timer.start(1); 111 | timer.stop(); 112 | CHECK( timer.remaining() == 0); 113 | CHECK( timer.running() == false); 114 | 115 | timer.start(0); 116 | CHECK( timer.remaining() == 0); 117 | CHECK( timer.running() == false); 118 | 119 | timer.start(1); 120 | CHECK( timer.remaining() == 1); 121 | CHECK( timer.running() == true); 122 | 123 | ++now; 124 | CHECK( timer.running() == true); 125 | CHECK( timer.remaining() == 0); 126 | CHECK( timer.running() == false); 127 | --now; 128 | 129 | timer.start(ULONG_MAX - 1); 130 | CHECK( timer.running() == true); 131 | CHECK( timer.remaining() == ULONG_MAX - 1); 132 | now+= ULONG_MAX - 2; 133 | CHECK( timer.running() == true); 134 | CHECK( timer.remaining() == 1); 135 | CHECK( timer.running() == true); 136 | ++now; 137 | CHECK( timer.remaining() == 0); 138 | CHECK( timer.running() == false); 139 | now-= ULONG_MAX - 1; 140 | 141 | timer.start(ULONG_MAX); 142 | CHECK( timer.running() == true); 143 | CHECK( timer.remaining() == ULONG_MAX); 144 | now+= ULONG_MAX - 1; 145 | CHECK( timer.remaining() == 1); 146 | CHECK( timer.running() == true); 147 | ++now; 148 | CHECK( timer.remaining() == 0); 149 | CHECK( timer.running() == false); 150 | 151 | timer.start(12*3600000ul + 38*60000ul + 15000); 152 | CHECK( timer.running() == true); 153 | CHECK( timer.remaining() == 12*3600000ul + 38*60000ul + 15000); 154 | now+= 12*3600000ul + 38*60000ul + 14999; 155 | CHECK( timer.remaining() == 1); 156 | ++now; 157 | CHECK( timer.remaining() == 0); 158 | CHECK( timer.running() == false); 159 | now-= 12*3600000ul + 38*60000ul + 15000; 160 | } 161 | 162 | TEST_CASE( "TimerRemaining test.", "[timer]" ) 163 | { 164 | now = 0; 165 | basicRemaining(); 166 | now = 1; 167 | basicRemaining(); 168 | now = ULONG_MAX; 169 | basicRemaining(); 170 | now = ULONG_MAX - 1; 171 | basicRemaining(); 172 | 173 | now = 12*3600000ul + 38*60000ul + 15000; 174 | basicRemaining(); 175 | 176 | } 177 | -------------------------------------------------------------------------------- /Tests/tests.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" 3 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | BUILD_ENV="1.0.6.1" 3 | SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )" 4 | 5 | if [ ! -d "build-env" ]; then 6 | mkdir build-env || exit 1 7 | fi 8 | cd build-env || exit 2 9 | 10 | if [ ! -f "PF-build-env-Linux64-$BUILD_ENV.zip" ]; then 11 | #wget https://github.com/3d-gussner/PF-build-env-1/releases/download/$BUILD_ENV-Linux64/PF-build-env-Linux64-$BUILD_ENV.zip || exit 3 12 | wget https://github.com/prusa3d/PF-build-env/releases/download/$BUILD_ENV-Linux64/PF-build-env-Linux64-$BUILD_ENV.zip || exit 3 13 | fi 14 | 15 | if [ ! -d "../../PF-build-env-$BUILD_ENV" ]; then 16 | unzip -q PF-build-env-Linux64-$BUILD_ENV.zip -d ../../PF-build-env-$BUILD_ENV || exit 4 17 | fi 18 | 19 | cd ../../PF-build-env-$BUILD_ENV || exit 5 20 | BUILD_ENV_PATH="$( pwd -P )" 21 | 22 | cd .. 23 | 24 | if [ ! -d "Prusa-Firmware-build" ]; then 25 | mkdir Prusa-Firmware-build || exit 6 26 | fi 27 | 28 | cd Prusa-Firmware-build || exit 7 29 | BUILD_PATH="$( pwd -P )" 30 | 31 | if [ ! -f "$SCRIPT_PATH/Firmware/Configuration_prusa.h" ]; then 32 | cp $SCRIPT_PATH/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 8 33 | fi 34 | 35 | $BUILD_ENV_PATH/arduino $SCRIPT_PATH/Firmware/Firmware.ino --verify --board PrusaResearchRambo:avr:rambo --pref build.path=$BUILD_PATH --pref compiler.warning_level=all || exit 9 36 | 37 | export ARDUINO=$BUILD_ENV_PATH 38 | 39 | cd $SCRIPT_PATH/lang 40 | ./lang-build.sh || exit 10 41 | ./fw-build.sh || exit 11 42 | -------------------------------------------------------------------------------- /lang/config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # config.sh - multi-language support configuration script 4 | # Definition of absolute paths etc. 5 | # This file is 'included' in all scripts. 6 | # 7 | # Arduino main folder: 8 | if [ -z "$ARDUINO" ]; then 9 | export ARDUINO=C:/arduino-1.8.5 10 | fi 11 | # 12 | # Arduino builder: 13 | export BUILDER=$ARDUINO/arduino-builder 14 | # 15 | # AVR gcc tools: 16 | export OBJCOPY=$ARDUINO/hardware/tools/avr/bin/avr-objcopy 17 | export OBJDUMP=$ARDUINO/hardware/tools/avr/bin/avr-objdump 18 | # 19 | # Output folder: 20 | export OUTDIR="../../Prusa-Firmware-build" 21 | # 22 | # Objects folder: 23 | export OBJDIR="$OUTDIR/sketch" 24 | # 25 | # Generated elf file: 26 | export INOELF="$OUTDIR/Firmware.ino.elf" 27 | # 28 | # Generated hex file: 29 | export INOHEX="$OUTDIR/Firmware.ino.hex" 30 | 31 | 32 | echo "config.sh started" >&2 33 | 34 | _err=0 35 | 36 | echo -n " Arduino main folder: " >&2 37 | if [ -e $ARDUINO ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=1; fi 38 | 39 | echo -n " Arduino builder: " >&2 40 | if [ -e $BUILDER ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=2; fi 41 | 42 | echo " AVR gcc tools:" >&2 43 | echo -n " objcopy " >&2 44 | if [ -e $OBJCOPY ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=3; fi 45 | echo -n " objdump " >&2 46 | if [ -e $OBJDUMP ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=4; fi 47 | 48 | echo -n " Output folder: " >&2 49 | if [ -e $OUTDIR ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=5; fi 50 | 51 | echo -n " Objects folder: " >&2 52 | if [ -e $OBJDIR ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=6; fi 53 | 54 | echo -n " Generated elf file: " >&2 55 | if [ -e $INOELF ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=7; fi 56 | 57 | echo -n " Generated hex file: " >&2 58 | if [ -e $INOHEX ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=8; fi 59 | 60 | if [ $_err -eq 0 ]; then 61 | echo "config.sh finished with success" >&2 62 | export CONFIG_OK=1 63 | else 64 | echo "config.sh finished with errors!" >&2 65 | export CONFIG_OK=0 66 | fi 67 | -------------------------------------------------------------------------------- /lang/fw-clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # fw-clean.sh - multi-language support script 4 | # Remove all firmware output files from lang folder. 5 | # 6 | 7 | result=0 8 | 9 | rm_if_exists() 10 | { 11 | if [ -e $1 ]; then 12 | echo -n " removing '$1'..." >&2 13 | if rm $1; then 14 | echo "OK" >&2 15 | else 16 | echo "NG!" >&2 17 | result=1 18 | fi 19 | fi 20 | } 21 | 22 | echo "fw-clean.sh started" >&2 23 | 24 | rm_if_exists text.sym 25 | rm_if_exists progmem1.sym 26 | rm_if_exists progmem1.lss 27 | rm_if_exists progmem1.hex 28 | rm_if_exists progmem1.chr 29 | rm_if_exists progmem1.var 30 | rm_if_exists progmem1.txt 31 | rm_if_exists textaddr.txt 32 | rm_if_exists firmware.bin 33 | rm_if_exists firmware.hex 34 | rm_if_exists firmware_cz.hex 35 | rm_if_exists firmware_de.hex 36 | rm_if_exists firmware_es.hex 37 | rm_if_exists firmware_fr.hex 38 | rm_if_exists firmware_it.hex 39 | rm_if_exists firmware_pl.hex 40 | rm_if_exists progmem.out 41 | rm_if_exists textaddr.out 42 | rm_if_exists update_lang.out 43 | rm_if_exists update_lang_cz.out 44 | rm_if_exists update_lang_de.out 45 | rm_if_exists update_lang_es.out 46 | rm_if_exists update_lang_fr.out 47 | rm_if_exists update_lang_it.out 48 | rm_if_exists update_lang_pl.out 49 | rm_if_exists lang.bin 50 | rm_if_exists lang.hex 51 | 52 | echo -n "fw-clean.sh finished" >&2 53 | if [ $result -eq 0 ]; then 54 | echo " with success" >&2 55 | else 56 | echo " with errors!" >&2 57 | fi 58 | 59 | case "$-" in 60 | *i*) echo "press enter key"; read ;; 61 | esac 62 | 63 | exit $result 64 | -------------------------------------------------------------------------------- /lang/iso639-1.txt: -------------------------------------------------------------------------------- 1 | #language codes ISO639-1 2 | # iso english localized 3 | #----------------------- 4 | # en English English 5 | # de German Deutsch 6 | # cs Czech Cestina 7 | # es Spanish Espanol 8 | # fr French Francais 9 | # it Italian Italiano 10 | # pl Polish Polski 11 | -------------------------------------------------------------------------------- /lang/lang-add.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # lang-add.sh - multi-language support script 4 | # add new texts from list (lang_add.txt) to all dictionary files 5 | # 6 | # Input files: 7 | # lang_add.txt 8 | # Updated files: 9 | # lang_en.txt and all lang_en_xx.txt 10 | # 11 | 12 | 13 | # insert single text to english dictionary 14 | # $1 - text to insert 15 | insert_en() 16 | { 17 | #replace '[' and ']' in string with '\[' and '\]' 18 | str=$(echo "$1" | sed "s/\[/\\\[/g;s/\]/\\\]/g") 19 | # extract english texts, merge new text, grep line number 20 | ln=$((cat lang_en.txt; echo "$1") | sed "/^$/d;/^#/d" | sort | grep -n "$str" | sed "s/:.*//") 21 | # calculate position for insertion 22 | ln=$((3*(ln-2)+1)) 23 | # insert new text 24 | sed -i "$ln"'i\\' lang_en.txt 25 | sed -i "$ln"'i\'"$1"'\' lang_en.txt 26 | sed -i "$ln"'i\#\' lang_en.txt 27 | } 28 | 29 | # insert single text to translated dictionary 30 | # $1 - text to insert 31 | # $2 - sufix 32 | insert_xx() 33 | { 34 | #replace '[' and ']' in string with '\[' and '\]' 35 | str=$(echo "$1" | sed "s/\[/\\\[/g;s/\]/\\\]/g") 36 | # extract english texts, merge new text, grep line number 37 | ln=$((cat lang_en_$2.txt; echo "$1") | sed "/^$/d;/^#/d" | sed -n 'p;n' | sort | grep -n "$str" | sed "s/:.*//") 38 | # calculate position for insertion 39 | ln=$((4*(ln-2)+1)) 40 | # insert new text 41 | sed -i "$ln"'i\\' lang_en_$2.txt 42 | sed -i "$ln"'i\"\x00"\' lang_en_$2.txt 43 | sed -i "$ln"'i\'"$1"'\' lang_en_$2.txt 44 | sed -i "$ln"'i\#\' lang_en_$2.txt 45 | } 46 | 47 | # check if input file exists 48 | if ! [ -e lang_add.txt ]; then 49 | echo "file lang_add.txt not found" 50 | exit 1 51 | fi 52 | 53 | cat lang_add.txt | sed 's/^/"/;s/$/"/' | while read new_s; do 54 | if grep "$new_s" lang_en.txt >/dev/null; then 55 | echo "text already exist:" 56 | echo "$new_s" 57 | echo 58 | else 59 | echo "adding text:" 60 | echo "$new_s" 61 | echo 62 | insert_en "$new_s" 63 | insert_xx "$new_s" 'cz' 64 | insert_xx "$new_s" 'de' 65 | insert_xx "$new_s" 'es' 66 | insert_xx "$new_s" 'fr' 67 | insert_xx "$new_s" 'it' 68 | insert_xx "$new_s" 'pl' 69 | fi 70 | done 71 | 72 | read -t 5 73 | exit 0 -------------------------------------------------------------------------------- /lang/lang-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # lang-build.sh - multi-language support script 4 | # generate lang_xx.bin (language binary file) 5 | # 6 | # Input files: 7 | # lang_en.txt or lang_en_xx.txt 8 | # 9 | # Output files: 10 | # lang_xx.bin 11 | # 12 | # Temporary files: 13 | # lang_xx.tmp 14 | # lang_xx.dat 15 | # 16 | 17 | #awk code to format ui16 variables for dd 18 | awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }' 19 | 20 | #startup message 21 | echo "lang-build.sh started" >&2 22 | 23 | #exiting function 24 | finish() 25 | { 26 | if [ $1 -eq 0 ]; then 27 | echo "lang-build.sh finished with success" >&2 28 | else 29 | echo "lang-build.sh finished with errors!" >&2 30 | fi 31 | exit $1 32 | } 33 | 34 | #returns hexadecial data for lang code 35 | lang_code_hex_data() 36 | # $1 - language code ('en', 'cz'...) 37 | { 38 | case "$1" in 39 | *en*) echo '\x6e\x65' ;; 40 | *cz*) echo '\x73\x63' ;; 41 | *de*) echo '\x65\x64' ;; 42 | *es*) echo '\x73\x65' ;; 43 | *fr*) echo '\x72\x66' ;; 44 | *it*) echo '\x74\x69' ;; 45 | *pl*) echo '\x6c\x70' ;; 46 | esac 47 | echo '??' 48 | } 49 | 50 | write_header() 51 | # $1 - lang 52 | # $2 - size 53 | # $3 - count 54 | # $4 - checksum 55 | # $5 - signature 56 | { 57 | /bin/echo -n -e "\xa5\x5a\xb4\x4b" |\ 58 | dd of=lang_$1.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null 59 | /bin/echo -n -e $(echo -n "$(($2))" | awk "$awk_ui16") |\ 60 | dd of=lang_$1.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null 61 | /bin/echo -n -e $(echo -n "$(($3))" | awk "$awk_ui16") |\ 62 | dd of=lang_$1.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null 63 | /bin/echo -n -e $(echo -n "$(($4))" | awk "$awk_ui16") |\ 64 | dd of=lang_$1.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null 65 | /bin/echo -n -e "$(lang_code_hex_data $1)" |\ 66 | dd of=lang_$1.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null 67 | sig_h=$(($5 / 65536)) 68 | /bin/echo -n -e $(echo -n "$sig_h" | awk "$awk_ui16") |\ 69 | dd of=lang_$1.bin bs=1 count=2 seek=14 conv=notrunc 2>/dev/null 70 | sig_l=$(($5 - $sig_h * 65536)) 71 | /bin/echo -n -e $(echo -n "$sig_l" | awk "$awk_ui16") |\ 72 | dd of=lang_$1.bin bs=1 count=2 seek=12 conv=notrunc 2>/dev/null 73 | } 74 | 75 | generate_binary() 76 | # $1 - language code ('en', 'cz'...) 77 | { 78 | echo "lang="$1 >&2 79 | #remove output and temporary files 80 | rm -f lang_$1.bin 81 | rm -f lang_$1.tmp 82 | rm -f lang_$1.dat 83 | LNG=$1 84 | #check lang dictionary 85 | /usr/bin/env python lang-check.py $1 --no-warning 86 | #create lang_xx.tmp - different processing for 'en' language 87 | if [ "$1" = "en" ]; then 88 | #remove comments and empty lines 89 | cat lang_en.txt | sed '/^$/d;/^#/d' 90 | else 91 | #remove comments and empty lines, print lines with translated text only 92 | cat lang_en_$1.txt | sed '/^$/d;/^#/d' | sed -n 'n;p' 93 | fi | sed 's/^\"\\x00\"$/\"\"/' > lang_$1.tmp 94 | #create lang_xx.dat (binary text data file) 95 | # cat lang_$1.tmp | sed 's/^\"/\/bin\/echo -e \"/;s/"$/\\x00\"/' > lang_$1.shx 96 | cat lang_$1.tmp | sed 's/^\"/\/bin\/echo -e -n \"/;s/"$/\\x00\"/' | sh >lang_$1.dat 97 | #calculate number of strings 98 | count=$(grep -c '^"' lang_$1.tmp) 99 | echo "count="$count >&2 100 | #calculate text data offset 101 | offs=$((16 + 2 * $count)) 102 | echo "offs="$offs >&2 103 | #calculate text data size 104 | size=$(($offs + $(wc -c lang_$1.dat | cut -f1 -d' '))) 105 | echo "size="$size >&2 106 | #write header with empty signature and checksum 107 | write_header $1 $size $count 0x0000 0x00000000 108 | #write offset table 109 | offs_hex=$(cat lang_$1.tmp | sed 's/^\"//;s/\"$//' |\ 110 | sed 's/\\x[0-9a-f][0-9a-f]/\./g;s/\\[0-7][0-7][0-7]/\./g;s/\ /\./g' |\ 111 | awk 'BEGIN { o='$offs';} { h=int(o/256); printf("\\x%02x\\x%02x",int(o-256*h), h); o+=(length($0)+1); }') 112 | /bin/echo -n -e "$offs_hex" | dd of=./lang_$1.bin bs=1 seek=16 conv=notrunc 2>/dev/null 113 | #write binary text data 114 | dd if=./lang_$1.dat of=./lang_$1.bin bs=1 seek=$offs conv=notrunc 2>/dev/null 115 | #write signature 116 | if [ "$1" != "en" ]; then 117 | dd if=lang_en.bin of=lang_$1.bin bs=1 count=4 skip=6 seek=12 conv=notrunc 2>/dev/null 118 | fi 119 | #calculate and update checksum 120 | chsum=$(cat lang_$1.bin | xxd | cut -c11-49 | tr ' ' "\n" | sed '/^$/d' | awk 'BEGIN { sum = 0; } { sum += strtonum("0x"$1); if (sum > 0xffff) sum -= 0x10000; } END { printf("%x\n", sum); }') 121 | /bin/echo -n -e $(echo -n $((0x$chsum)) | awk "$awk_ui16") |\ 122 | dd of=lang_$1.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null 123 | #remove temporary files 124 | # rm -f lang_$1.tmp 125 | # rm -f lang_$1.dat 126 | } 127 | 128 | if [ -z "$1" ]; then set 'all'; fi 129 | 130 | if [ "$1" = "all" ]; then 131 | generate_binary 'en' 132 | generate_binary 'cz' 133 | generate_binary 'de' 134 | generate_binary 'es' 135 | generate_binary 'fr' 136 | generate_binary 'it' 137 | generate_binary 'pl' 138 | else 139 | generate_binary $1 140 | fi 141 | 142 | finish 0 143 | -------------------------------------------------------------------------------- /lang/lang-check.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Check lang files.""" 3 | from argparse import ArgumentParser 4 | from traceback import print_exc 5 | from sys import stderr 6 | 7 | 8 | def parse_txt(lang, no_warning): 9 | """Parse txt file and check strings to display definition.""" 10 | if lang == "en": 11 | file_path = "lang_en.txt" 12 | else: 13 | file_path = "lang_en_%s.txt" % lang 14 | 15 | lines = 1 16 | with open(file_path) as src: 17 | while True: 18 | comment = src.readline().split(' ') 19 | src.readline() # source 20 | translation = src.readline()[:-1] 21 | 22 | cols = None 23 | rows = None 24 | for item in comment[1:]: 25 | key, val = item.split('=') 26 | if key == 'c': 27 | cols = int(val) 28 | elif key == 'r': 29 | rows = int(val) 30 | else: 31 | raise RuntimeError( 32 | "Unknown display definition %s on line %d" % 33 | (' '.join(comment), lines)) 34 | if cols is None and rows is None: 35 | if not no_warning: 36 | print("[W]: No display definition on line %d" % lines) 37 | cols = len(translation) # propably fullscreen 38 | if rows is None: 39 | rows = 1 40 | 41 | if len(translation)-2 > cols*rows: 42 | stderr.write( 43 | "[E]: Text %s is longer then definiton on line %d\n" % 44 | (translation, lines)) 45 | stderr.flush() 46 | 47 | if len(src.readline()) != 1: # empty line 48 | break 49 | lines += 4 50 | 51 | 52 | def main(): 53 | """Main function.""" 54 | parser = ArgumentParser( 55 | description=__doc__, 56 | usage="$(prog)s lang") 57 | parser.add_argument( 58 | "lang", nargs='?', default="en", type=str, 59 | help="Check lang file (en|cs|de|es|fr|it|pl)") 60 | parser.add_argument( 61 | "--no-warning", action="store_true", 62 | help="Disable warnings") 63 | 64 | args = parser.parse_args() 65 | try: 66 | parse_txt(args.lang, args.no_warning) 67 | return 0 68 | except Exception as exc: 69 | print_exc() 70 | parser.error("%s" % exc) 71 | return 1 72 | 73 | 74 | if __name__ == "__main__": 75 | exit(main()) 76 | -------------------------------------------------------------------------------- /lang/lang-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # lang_check.sh - multi-language support script 4 | # check lang_xx.bin (language binary file) 5 | # 6 | # Input files: 7 | # lang_$1.bin 8 | # lang_en.txt or lang_en_$1.txt 9 | # 10 | # 11 | 12 | #set 'cz' 13 | 14 | #dictionary txt file 15 | fn_t=lang_en_$1.txt 16 | if [ "$1" = "en" ]; then fn_t=lang_en.txt; fi 17 | #binary file to check 18 | fn_b=lang_$1.bin 19 | 20 | #check txt dictionary file 21 | echo -n "dictionary file: $fn_t" 22 | if [ -e $fn_t ]; then echo " - OK"; else echo " - Not found!"; exit 1; fi 23 | 24 | #create lang_xx.tmp - different processing for 'en' language 25 | if [ "$1" = "en" ]; then 26 | #remove comments and empty lines 27 | cat lang_en.txt | sed '/^$/d;/^#/d' 28 | else 29 | #remove comments and empty lines, print lines with translated text only 30 | cat lang_en_$1.txt | sed '/^$/d;/^#/d' | sed -n 'n;p' 31 | fi | sed 's/^\"\\x00\"$/\"\"/' > lang_$1.tmp 32 | 33 | count_txt=$(grep -c '^"' lang_$1.tmp) 34 | 35 | echo -n "language bin file: $fn_b" 36 | if [ -e $fn_b ]; then echo " - OK"; else echo " - Not found!"; exit 1; fi 37 | 38 | #read header and convert to hex 39 | header=$(dd if=$fn_b bs=1 count=16 2>/dev/null | xxd | cut -c11-49 | sed 's/\([0-9a-f][0-9a-f]\)[\ ]*/\1 /g') 40 | echo "header='$header'" 41 | magic=0x$(echo $header | tr -d ' ' | cut -c1-8) 42 | echo "magic='$magic'" 43 | size=$(echo $header | tr -d ' ' | cut -c9-12) 44 | size=0x${size:2:2}${size:0:2} 45 | echo "size='$size' ($(($size)))" 46 | count=$(echo $header | tr -d ' ' | cut -c13-16) 47 | count=0x${count:2:2}${count:0:2} 48 | echo "count='$count' ($(($count)))" 49 | o=0 50 | l=0 51 | #create lang_xx_1.tmp (temporary text file from binary data) 52 | (dd if=$fn_b bs=1 count=$((2*$count)) skip=16 2>/dev/null | xxd | cut -c11-49 | tr ' ' "\n" |\ 53 | sed 's/\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)/\2\1 /g;/^$/d'; printf "%04x\n" $(($size)) ) |\ 54 | while read offs; do 55 | if [ $o -ne 0 ]; then 56 | l=$((0x$offs - $o)) 57 | echo -n '"' 58 | dd if=$fn_b bs=1 count=$((l-1)) skip=$o 2>/dev/null 59 | echo '"' 60 | fi 61 | o=$((0x$offs)) 62 | done > lang_$1_1.tmp 63 | #create lang_xx_2.tmp (temporary text file from dictionary) 64 | cat lang_$1.tmp | sed 's/^\"/printf \"\\x22/;s/"$/\\x22\\x0a\"/' | sh >lang_$1_2.tmp 65 | #compare temporary files 66 | diff -a lang_$1_1.tmp lang_$1_2.tmp >lang_$1_check.dif 67 | dif=$(cat lang_$1_check.dif) 68 | if [ -z "$dif" ]; then 69 | echo 'binary data OK' 70 | else 71 | echo 'binary data NG!' 72 | fi 73 | 74 | read -t 5 75 | exit 76 | -------------------------------------------------------------------------------- /lang/lang-clean.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # clean.sh - multi-language support script 4 | # Remove all language output files from lang folder. 5 | # 6 | 7 | result=0 8 | 9 | rm_if_exists() 10 | { 11 | if [ -e $1 ]; then 12 | echo -n " removing '$1'..." >&2 13 | if rm $1; then 14 | echo "OK" >&2 15 | else 16 | echo "NG!" >&2 17 | result=1 18 | fi 19 | fi 20 | } 21 | 22 | clean_lang() 23 | { 24 | if [ "$1" = "en" ]; then 25 | rm_if_exists lang_$1.tmp 26 | else 27 | rm_if_exists lang_$1.tmp 28 | rm_if_exists lang_en_$1.tmp 29 | rm_if_exists lang_en_$1.dif 30 | rm_if_exists lang_$1.ofs 31 | rm_if_exists lang_$1.txt 32 | fi 33 | rm_if_exists lang_$1_check.dif 34 | rm_if_exists lang_$1.bin 35 | rm_if_exists lang_$1.dat 36 | rm_if_exists lang_$1_1.tmp 37 | rm_if_exists lang_$1_2.tmp 38 | } 39 | 40 | echo "lang-clean.sh started" >&2 41 | 42 | clean_lang en 43 | clean_lang cz 44 | clean_lang de 45 | clean_lang es 46 | clean_lang fr 47 | clean_lang it 48 | clean_lang pl 49 | 50 | echo -n "lang-clean.sh finished" >&2 51 | if [ $result -eq 0 ]; then 52 | echo " with success" >&2 53 | else 54 | echo " with errors!" >&2 55 | fi 56 | 57 | case "$-" in 58 | *i*) echo "press enter key" >&2; read ;; 59 | esac 60 | 61 | exit $result 62 | -------------------------------------------------------------------------------- /lang/lang-export.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # lang-export.sh - multi-language support script 4 | # for generating lang_xx.po 5 | # 6 | 7 | # relative path to source folder 8 | SRCDIR="../Firmware" 9 | 10 | # selected language is 1st argument (cz, de, ...) 11 | LNG=$1 12 | 13 | # if no arguments, 'all' is selected (all po and also pot will be generated) 14 | if [ -z "$LNG" ]; then LNG=all; fi 15 | 16 | # if 'all' is selected, script will generate all po files and also pot file 17 | if [ "$LNG" = "all" ]; then 18 | ./lang-export.sh en 19 | ./lang-export.sh cz 20 | ./lang-export.sh de 21 | ./lang-export.sh es 22 | ./lang-export.sh fr 23 | ./lang-export.sh it 24 | ./lang-export.sh pl 25 | exit 0 26 | fi 27 | 28 | # language code (iso639-1) is equal to LNG 29 | LNGISO=$LNG 30 | # exception for 'cz' (code='cs') 31 | if [ "$LNG" = "cz" ]; then LNGISO=cs; fi 32 | 33 | # po/pot creation/revision date 34 | DATE=$(date) 35 | 36 | # if 'en' is selected, generate pot instead of po 37 | if [ "$LNG" = "en" ]; then 38 | INFILE=lang_en.txt 39 | OUTFILE=po/Firmware.pot 40 | LNGNAME="English" 41 | else 42 | # language name in english 43 | LNGNAME=$(\ 44 | case "$LNG" in 45 | *cz*) echo "Czech" ;; 46 | *de*) echo "German" ;; 47 | *es*) echo "Spanish" ;; 48 | *fr*) echo "French" ;; 49 | *it*) echo "Italian" ;; 50 | *pl*) echo "Polish" ;; 51 | esac) 52 | # unknown language - error 53 | if [ -z "LNGNAME" ]; then 54 | echo "Invalid argument '$LNG'." 55 | exit 1 56 | fi 57 | INFILE=lang_en_$LNG.txt 58 | OUTFILE=po/Firmware_$LNGISO.po 59 | fi 60 | 61 | # remove output file if exists 62 | if [ -e $OUTFILE ]; then rm -f -v $OUTFILE; fi 63 | 64 | echo "lang-export.sh started" 65 | 66 | #total strings 67 | CNTTXT=$(grep '^#' -c $INFILE) 68 | #not translated strings 69 | CNTNT=$(grep '^\"\\x00\"' -c $INFILE) 70 | echo " $CNTTXT texts, $CNTNT not translated" 71 | 72 | # list .cpp, .c and .h files from source folder 73 | SRCFILES=$(ls "$SRCDIR"/*.cpp "$SRCDIR"/*.c "$SRCDIR"/*.h) 74 | 75 | echo " selected language=$LNGNAME" 76 | 77 | # write po/pot header 78 | ( 79 | echo "# Translation of Prusa-Firmware into $LNGNAME." 80 | echo "#" 81 | echo 'msgid ""' 82 | echo 'msgstr ""' 83 | echo '"MIME-Version: 1.0\n"' 84 | echo '"Content-Type: text/plain; charset=UTF-8\n"' 85 | echo '"Content-Transfer-Encoding: 8bit\n"' 86 | echo '"Language: '$LNGISO'\n"' 87 | echo '"Project-Id-Version: Prusa-Firmware\n"' 88 | echo '"POT-Creation-Date: '$DATE'\n"' 89 | echo '"PO-Revision-Date: '$DATE'\n"' 90 | echo '"Language-Team: \n"' 91 | echo '"X-Generator: Poedit 2.0.7\n"' 92 | echo '"X-Poedit-SourceCharset: UTF-8\n"' 93 | echo '"Last-Translator: \n"' 94 | echo '"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"' 95 | echo 96 | ) >$OUTFILE 97 | 98 | #loop over all messages 99 | s0='' 100 | s1='' 101 | s2='' 102 | num=1 103 | (cat $INFILE | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do 104 | if [ "$s" = "" ]; then 105 | echo " processing $num of $CNTTXT" >&2 106 | # write po/pot item 107 | ( 108 | if [ -z "$s2" ]; then s2=$s1; s1=$s0; s0='""'; fi 109 | search=$(/bin/echo -e "$s1") 110 | found=$(grep -m1 -n -F "$search" $SRCFILES | head -n1 | cut -f1-2 -d':' | sed "s/^.*\///") 111 | echo "$s2" | sed 's/ c=0//;s/ r=0//;s/^#/# /' 112 | echo "#: $found" 113 | /bin/echo -e "msgid $s1" 114 | if [ "$s0" = "\"\\\\x00\"" ]; then 115 | echo 'msgstr ""' 116 | else 117 | /bin/echo -e "msgstr $s0" 118 | fi 119 | echo 120 | ) 121 | num=$((num+1)) 122 | fi 123 | s2=$s1 124 | s1=$s0 125 | s0=$s 126 | done >>$OUTFILE) 2>&1 127 | 128 | #replace LF with CRLF 129 | sync 130 | sed -i 's/$/\r/' $OUTFILE 131 | 132 | echo "lang-export.sh finished" 133 | exit 0 134 | -------------------------------------------------------------------------------- /lang/lang-import.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # lang-import.sh - multi-language support script 4 | # for importing translated xx.po 5 | 6 | LNG=$1 7 | # if no arguments, 'all' is selected (all po and also pot will be generated) 8 | if [ -z "$LNG" ]; then LNG=all; fi 9 | 10 | # if 'all' is selected, script will generate all po files and also pot file 11 | if [ "$LNG" = "all" ]; then 12 | ./lang-import.sh cz 13 | ./lang-import.sh de 14 | ./lang-import.sh es 15 | ./lang-import.sh fr 16 | ./lang-import.sh it 17 | ./lang-import.sh pl 18 | exit 0 19 | fi 20 | 21 | # language code (iso639-1) is equal to LNG 22 | LNGISO=$LNG 23 | # exception for 'cz' (code='cs') 24 | if [ "$LNG" = "cz" ]; then LNGISO=cs; fi 25 | 26 | # cd to input folder 27 | cd po/new 28 | 29 | # check if input file exists 30 | if ! [ -e $LNGISO.po ]; then 31 | echo "Input file $LNGISO.po not found!" >&2 32 | exit -1 33 | fi 34 | 35 | #convert '\\e' sequencies to 'x1b' and '\\' to '\' 36 | cat $LNGISO.po | sed 's/\\e/\\x1b/g;s/\\\\/\\/g' > $LNG'_filtered.po' 37 | 38 | #replace '\n' with ' ' (single space) 39 | sed -i 's/ \\n/ /g;s/\\n/ /g' $LNG'_filtered.po' 40 | 41 | #replace in czech translation 42 | if [ "$LNG" = "cz" ]; then 43 | #replace 'ž' with 'z' 44 | sed -i 's/\xc5\xbe/z/g' $LNG'_filtered.po' 45 | #replace 'ì' with 'e' 46 | sed -i 's/\xc4\x9b/e/g' $LNG'_filtered.po' 47 | #replace 'í' with 'i' 48 | sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po' 49 | #replace 'ø' with 'r' 50 | sed -i 's/\xc5\x99/r/g' $LNG'_filtered.po' 51 | #replace 'è' with 'c' 52 | sed -i 's/\xc4\x8d/c/g' $LNG'_filtered.po' 53 | #replace 'á' with 'a' 54 | sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' 55 | #replace 'é' with 'e' 56 | sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' 57 | fi 58 | 59 | #replace in german translation https://en.wikipedia.org/wiki/German_orthography 60 | if [ "$LNG" = "de" ]; then 61 | #replace 'ä' with 'ae' 62 | sed -i 's/\xc3\xa4/ae/g' $LNG'_filtered.po' 63 | #replace 'Ä' with 'Ae' 64 | sed -i 's/\xc3\x84/Ae/g' $LNG'_filtered.po' 65 | #replace 'ü' with 'ue' 66 | sed -i 's/\xc3\xbc/ue/g' $LNG'_filtered.po' 67 | #replace 'Ü' with 'Ue' 68 | sed -i 's/\xc3\x9c/Ue/g' $LNG'_filtered.po' 69 | #replace 'ö' with 'oe' 70 | sed -i 's/\xc3\xb6/oe/g' $LNG'_filtered.po' 71 | #replace 'Ö' with 'Oe' 72 | sed -i 's/\xc3\x96/Oe/g' $LNG'_filtered.po' 73 | #replace 'ß' with 'ss' 74 | sed -i 's/\xc3\x9f/ss/g' $LNG'_filtered.po' 75 | fi 76 | 77 | #replace in spain translation 78 | if [ "$LNG" = "es" ]; then 79 | #replace 'á' with 'a' 80 | sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' 81 | #replace '¿' with '?' 82 | sed -i 's/\xc2\xbf/?/g' $LNG'_filtered.po' 83 | #replace 'ó' with 'o' 84 | sed -i 's/\xc3\xb3/o/g' $LNG'_filtered.po' 85 | #replace 'é' with 'e' 86 | sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' 87 | #replace 'í' with 'i' 88 | sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po' 89 | #replace '!' with '!' 90 | sed -i 's/\xc2\xa1/!/g' $LNG'_filtered.po' 91 | #replace 'n~' with 'n' 92 | sed -i 's/\xc3\xb1/n/g' $LNG'_filtered.po' 93 | fi 94 | 95 | #replace in french translation https://en.wikipedia.org/wiki/French_orthography 96 | if [ "$LNG" = "fr" ]; then 97 | #replace 'á' with 'a' (right) 98 | sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po' 99 | #replace 'Á' with 'A' (right) 100 | sed -i 's/\xc3\x81/A/g' $LNG'_filtered.po' 101 | #replace 'à' with 'a' (left) 102 | sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po' 103 | #replace 'À' with 'A' (left) 104 | sed -i 's/\xc3\x80/A/g' $LNG'_filtered.po' 105 | #replace 'é' with 'e' (right) 106 | sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' 107 | #replace 'É' with 'E' (right) 108 | sed -i 's/\xc3\x89/E/g' $LNG'_filtered.po' 109 | #replace 'è' with 'e' (left) 110 | sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po' 111 | #replace 'È' with 'E' (left) 112 | sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po' 113 | fi 114 | 115 | #replace in italian translation 116 | if [ "$LNG" = "it" ]; then 117 | #replace 'é' with 'e' (left) 118 | sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po' 119 | #replace 'á' with 'a' (left) 120 | sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po' 121 | #replace 'ó' with 'o' (left) 122 | sed -i 's/\xc3\xb2/o/g' $LNG'_filtered.po' 123 | #replace 'ú' with 'u' (left) 124 | sed -i 's/\xc3\xb9/u/g' $LNG'_filtered.po' 125 | #replace 'é' with 'e' 126 | sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po' 127 | #replace 'É' with 'E' (left) 128 | sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po' 129 | fi 130 | 131 | #replace in polish translation 132 | #if [ "$LNG" = "pl" ]; then 133 | #fi 134 | 135 | #check for nonasci characters 136 | if grep --color='auto' -P -n '[^\x00-\x7F]' $LNG'_filtered.po' >nonasci.txt; then 137 | exit 138 | fi 139 | 140 | #join lines with multi-line string constants 141 | cat $LNG'_filtered.po' | sed ':a;N;$!ba;s/\x22\n\x22//g' > $LNG'_new.po' 142 | 143 | #generate new dictionary 144 | cat ../../lang_en.txt | sed 's/\\/\\\\/g' | while read -r s; do 145 | /bin/echo -e "$s" 146 | if [ "${s:0:1}" = "\"" ]; then 147 | # /bin/echo -e "$s" 148 | s=$(/bin/echo -e "$s") 149 | s2=$(grep -F -A1 -B0 "$s" "$LNG"_new.po | tail -n1 | sed 's/^msgstr //') 150 | if [ -z "$s2" ]; then 151 | echo '"\x00"' 152 | else 153 | echo "$s2" 154 | fi 155 | # echo 156 | fi 157 | done > lang_en_$LNG.txt 158 | -------------------------------------------------------------------------------- /lang/progmem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # progmem.sh - multi-language support script 4 | # Examine content of progmem sections (default is progmem1). 5 | # 6 | # Input files: 7 | # $OUTDIR/Firmware.ino.elf 8 | # $OUTDIR/sketch/*.o (all object files) 9 | # 10 | # Output files: 11 | # text.sym - formated symbol listing of section '.text' 12 | # $PROGMEM.sym - formated symbol listing of section '.progmemX' 13 | # $PROGMEM.lss - disassembly listing file 14 | # $PROGMEM.hex - variables - hex 15 | # $PROGMEM.chr - variables - char escape 16 | # $PROGMEM.var - variables - strings 17 | # $PROGMEM.txt - text data only (not used) 18 | # 19 | # 20 | # Config: 21 | if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi 22 | if [ -z "$OUTDIR" ]; then echo 'variable OUTDIR not set!' >&2; exit 1; fi 23 | if [ -z "$OBJDIR" ]; then echo 'variable OBJDIR not set!' >&2; exit 1; fi 24 | if [ -z "$INOELF" ]; then echo 'variable INOELF not set!' >&2; exit 1; fi 25 | if [ -z "$OBJDUMP" ]; then echo 'variable OBJDUMP not set!' >&2; exit 1; fi 26 | if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi 27 | # 28 | # Program memory used 29 | PROGMEM=progmem$1 30 | if [ -z "$1" ]; then PROGMEM=progmem1; fi 31 | # 32 | # Description of process: 33 | # 0. check input files 34 | # 1. remove output files 35 | # 2. list symbol table of section '.text' from output elf file to text.sym (sorted by address) 36 | # 3. calculate start and stop address of section '.$PROGMEM' 37 | # 4. extract string data from elf file to $PROGMEM.hex 38 | # 5. prepare string data for character check and conversion (output to $PROGMEM.chr) 39 | # 6. perform character check and conversion (output to $PROGMEM.var and $PROGMEM.txt) 40 | # 41 | 42 | echo "progmem.sh started" >&2 43 | 44 | # (0) 45 | echo " progmem.sh (0) - checking input files" >&2 46 | if [ ! -e $OUTDIR ]; then echo "progmem.sh - file '$INOELF' not found!" >&2; exit 1; fi 47 | 48 | # (1) 49 | echo " progmem.sh (1) - removing output files" >&2 50 | #remove output files if exists 51 | if [ -e text.sym ]; then rm text.sym; fi 52 | if [ -e $PROGMEM.sym ]; then rm $PROGMEM.sym; fi 53 | if [ -e $PROGMEM.lss ]; then rm $PROGMEM.lss; fi 54 | if [ -e $PROGMEM.hex ]; then rm $PROGMEM.hex; fi 55 | if [ -e $PROGMEM.chr ]; then rm $PROGMEM.chr; fi 56 | if [ -e $PROGMEM.var ]; then rm $PROGMEM.var; fi 57 | if [ -e $PROGMEM.txt ]; then rm $PROGMEM.txt; fi 58 | 59 | # (2) 60 | echo " progmem.sh (2) - listing symbol table of section '.text'" >&2 61 | #list symbols from section '.text' into file text.sym (only address, size and name) 62 | #$OBJDUMP -t -j ".text" $INOELF | sort > text.sym 63 | $OBJDUMP -t -j ".text" $INOELF | tail -n +5 | grep -E "^[0-9a-f]{8} [gl] [O ]" | cut -c1-9,28-36,37- | sed "/^$/d" | sort > text.sym 64 | 65 | # (3) 66 | echo " progmem.sh (3) - calculating start and end address" >&2 67 | #calculate start addres of section ".$PROGMEM" 68 | PROGMEM_BEG=$(cat text.sym | grep "__loc_pri_start" | while read offs size name; do echo "0x"$offs; done) 69 | #calculate stop addres of section ".$PROGMEM" 70 | PROGMEM_END=$(cat text.sym | grep "__loc_pri_end" | while read offs size name; do echo "0x"$offs; done) 71 | echo " START address = "$PROGMEM_BEG >&2 72 | echo " STOP address = "$PROGMEM_END >&2 73 | 74 | # (4) 75 | echo " progmem.sh (4) - extracting string data from elf" >&2 76 | #dump $PROGMEM data in hex format, cut disassembly (keep hex data only) 77 | $OBJDUMP -D -j ".text" -w -z --start-address=$PROGMEM_BEG --stop-address=$PROGMEM_END $INOELF |\ 78 | tail -n +7 | sed "s/ \t.*$//" > $PROGMEM.lss 79 | #convert $PROGMEM.lss to $PROGMEM.hex: 80 | # replace empty lines with '|' (variables separated by empty lines) 81 | # remove address from multiline variables (keep address at first variable line only) 82 | # remove '<' and '>:', remove whitespace at end of lines 83 | # remove line-endings, replace separator with '\n' (join hex data lines - each line will contain single variable) 84 | cat $PROGMEM.lss | sed -E 's/^$/|/;s/^ ....:\t//;s/[ ]*$/ /' | tr -d '\n' | tr '|' '\n' |\ 85 | sed "s/^ //;s/:/ /;s/00 [1-9a-f][1-9a-f] $/00 /; s/ $//" > $PROGMEM.hex 86 | 87 | # (5) 88 | echo " progmem.sh (5) - preparing string data" >&2 89 | #convert $PROGMEM.hex to $PROGMEM.chr (prepare string data for character check and conversion) 90 | # replace first space with tab 91 | # replace second and third space with tab and space 92 | # replace all remaining spaces with '\x' 93 | # replace all tabs with spaces 94 | cat $PROGMEM.hex | sed 's/ /\t/;s/ /\t /;s/ /\\x/g;s/\t/ /g' > $PROGMEM.chr 95 | 96 | # (6) 97 | #convert $PROGMEM.chr to $PROGMEM.var (convert data to text) 98 | echo " progmem.sh (6) - converting string data" >&2 99 | (\ 100 | echo "/bin\/echo -e \\"; \ 101 | cat $PROGMEM.chr | \ 102 | sed 's/ \\xff\\xff/ /;' | \ 103 | sed 's/\\x22/\\\\\\x22/g;' | \ 104 | sed 's/\\x1b/\\\\\\x1b/g;' | \ 105 | sed 's/\\x01/\\\\\\x01/g;' | \ 106 | sed 's/\\xf8/\\\\\\xf8/g;' | \ 107 | sed 's/\\x0a/\\\\\\x0a/g;' | \ 108 | sed 's/\\x00$/\n/;s/^/\"/;s/$/\"\\/'; \ 109 | ) | sh > $PROGMEM.var 110 | 111 | #this step can be omitted because .txt file is not used 112 | cat $PROGMEM.var | sed 's/\r/\n/g' | sed -E 's/^[0-9a-f]{8} [^ ]* //' >$PROGMEM.txt 113 | 114 | echo "progmem.sh finished" >&2 115 | 116 | exit 0 -------------------------------------------------------------------------------- /lang/readme.txt: -------------------------------------------------------------------------------- 1 | Nova podpora vice jazyku ve firmware 2 | 3 | 4 | Zmeny oproti stavajicimu frameworku: 5 | 1. Deklarace lokalizovanych textu primo v kodu, neni nutne udrzovat tabulky. 6 | 2. Zatim dvoj jazycna verze (en_cz, en_de atd). Moznost rozsirit na vicejazycnou (en_cz_de - pro MK2). 7 | 3. Moznost vyberu druheho jazyka ulozeneho v SPI flash (nebude zabirat misto v interni flash, pouze MK3). 8 | 5. Bash postbuild proces namisto perloveho skriptu + nastroje na spravu slovniku. 9 | 10 | Popis: 11 | Novy framework je trochu podobny jako znamy i18n20, ale sity na miru pro AVR atmega s ohledem na maximalni jednoduchost a usporu interni flashe. 12 | Stringy ktere maji byt prelozene se deklaruji pomoci specialnich maker, zbytek obstara postbuild. 13 | Vsechny lokalizovane texty se nachazi ve specialni sekci, v pripade AVR musi byt stringy umisteny v dolnich 64kB flash - tzv 'progmem'. 14 | Po zbuildovani arduinem bude fungovat pouze anglictina, je treba spustit postbuild ktery na zaklade slovniku doplni data sekundarniho jazka a vytvori modifikovany hexfile. 15 | Jedina data ktera je treba udrzovat jsou slovniky pro preklad. Jsou to textove soubory kde je vzdy sparovan anglicky text s prelozenym textem. 16 | Kazdy text ve slovniku je jeden radek, muze obsahovat specialni znaky v hexadecimalni podobe (e.g. '\x0a'). Nasledujici radek je vzdy prelozeny text. 17 | Tento jednoduchy format je zvolen proto aby bylo mozno slovniky a proces prekladu spravovat jen pomoci gitu a nekolika skriptu. 18 | 19 | Pokud pridame nebo zmenime nejaky text v kodu, zmeni se po zbuildovani a spusteni nastroje 'update.sh' soubor lang_en_code.txt. 20 | To je generovany soubor ktery obsahuje vsechny lokalizovane texty pouzite v kodu setridene podle abecedy. 21 | V gitu uvidime zmenu kterou rucne preneseme do slovniku lang_en_xx.txt, zaroven vytvorime pozadavek na preklad ci korekturu pozadovaneho textu. 22 | Pokud pridame nebo zmenime nejaky text ve slovnikach, zmeni se po spusteni nastroje 'update.sh' soubor lang_en_dict.txt. 23 | Ten obsahuje vsechny lokalizovane texty ze slovniku (v anglictine), respektive mnozinu jejich sjednoceni. 24 | V idealnim pripade by soubory lang_en_code.txt a lang_en_dict.txt mely byt totozne. 25 | Pokud se zmeni slovnik, je treba znovu vygenerovat binarni soubory lang_en_xx.bin. 26 | 27 | 28 | Pouziti v kodu, priklady: 29 | 30 | 1. deklarace lokalizovaneho textu v kodu - makro '_i': 31 | puts_P(_i("Kill all humans!")); //v cz vypise "Zabit vsechny lidi!" 32 | 33 | 2. deklarace lokalizovaneho textu jako globalni konstanty - makro 'PROGMEM_I1' a 'ISTR': 34 | const char MSG_PREHEAT[] PROGMEM_I1 = ISTR("Preheat"); //deklarace 35 | puts_P(get_translation(MSG_PREHEAT)); //v cz vypise "Predehrev" 36 | 37 | 3. fukce get_translation - zkratka makro '_T': 38 | puts_P(_T(MSG_PREHEAT)); //v cz vypise "Predehrev" 39 | 40 | 4. deklarace lokalizovaneho textu jako lokalni promenne - makro '_I': 41 | const char* text = preheat?_I("Preheat"):_I("Cooldown"); 42 | puts_P(_T(text)); //v cz vypise "Predehrev" nebo "Zchlazeni" 43 | 44 | 5. deklarace nelokalizovaneho textu - makro 'PROGMEM_N1' a '_n' nebo '_N': 45 | const char MSG_MK3[] PROGMEM_N1 = "MK3"; //deklarace 46 | const char* text = _n("MK3"); 47 | nebo 48 | const char* text = _N("MK3"); 49 | -------------------------------------------------------------------------------- /lang/textaddr.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # textaddr.sh - multi-language support script 4 | # Compile progmem1.var and lang_en.txt files to textaddr.txt file (mapping of progmem addreses to text idenifiers) 5 | # 6 | # Input files: 7 | # progmem1.var 8 | # lang_en.txt 9 | # 10 | # Output files: 11 | # textaddr.txt 12 | # 13 | # 14 | # Dscription of process: 15 | # check if input files exists 16 | # create sorted list of strings from progmem1.var and lang_en.txt 17 | # lines from progmem1.var will contain addres (8 chars) and english text 18 | # lines from lang_en.txt will contain linenumber and english text 19 | # after sort this will generate pairs of lines (line from progmem1 first) 20 | # result of sort is compiled with simple script and stored into file textaddr.txt 21 | # 22 | 23 | echo "textaddr.sh started" >&2 24 | 25 | if [ ! -e progmem1.var ]; then echo 'textaddr.sh - file progmem1.var not found!' >&2; exit 1; fi 26 | if [ ! -e lang_en.txt ]; then echo 'textaddr.sh - file lang_en.txt not found!' >&2; exit 1; fi 27 | addr='' 28 | text='' 29 | (cat progmem1.var | sed -E "s/^([^ ]*) ([^ ]*) (.*)/\1 \"\3\"/";\ 30 | cat lang_en.txt | sed "/^$/d;/^#/d" | sed = | sed '{N;s/\n/ /}') |\ 31 | sort -k2 |\ 32 | sed "s/\\\/\\\\\\\/g" | while read num txt; do 33 | if [ ${#num} -eq 8 ]; then 34 | if [ -z "$addr" ]; then 35 | addr=$num 36 | else 37 | if [ "$text" = "$txt" ]; then 38 | addr="$addr $num" 39 | else 40 | echo "ADDR NF $addr $text" 41 | addr=$num 42 | fi 43 | fi 44 | text=$txt 45 | else 46 | if [ -z "$addr" ]; then 47 | if ! [ -z "$num" ]; then echo "TEXT NF $num $txt"; fi 48 | else 49 | if [ "$text" = "$txt" ]; then 50 | if [ ${#addr} -eq 8 ]; then 51 | echo "ADDR OK $addr $num" 52 | else 53 | echo "$addr" | sed "s/ /\n/g" | while read ad; do 54 | echo "ADDR OK $ad $num" 55 | done 56 | fi 57 | addr='' 58 | text='' 59 | else 60 | if ! [ -z "$num" ]; then echo "TEXT NF $num $txt"; fi 61 | fi 62 | fi 63 | fi 64 | done > textaddr.txt 65 | 66 | echo "textaddr.sh finished" >&2 67 | 68 | exit 0 -------------------------------------------------------------------------------- /lang/update_lang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # update_lang.sh - multi-language support script 4 | # Update secondary language in binary file. 5 | # 6 | # Config: 7 | if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi 8 | if [ -z "$OBJCOPY" ]; then echo 'variable OBJCOPY not set!' >&2; exit 1; fi 9 | if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi 10 | # 11 | # Selected language: 12 | LNG=$1 13 | if [ -z "$LNG" ]; then LNG='cz'; fi 14 | # 15 | 16 | finish() 17 | { 18 | echo 19 | if [ "$1" = "0" ]; then 20 | echo "update_lang.sh finished with success" >&2 21 | else 22 | echo "update_lang.sh finished with errors!" >&2 23 | fi 24 | case "$-" in 25 | *i*) echo "press enter key" >&2; read ;; 26 | esac 27 | exit $1 28 | } 29 | 30 | echo "update_lang.sh started" >&2 31 | echo " selected language=$LNG" >&2 32 | 33 | echo -n " checking files..." >&2 34 | if [ ! -e text.sym ]; then echo "NG! file text.sym not found!" >&2; finish 1; fi 35 | if [ ! -e lang_$LNG.bin ]; then echo "NG! file lang_$LNG.bin not found!" >&2; finish 1; fi 36 | if [ ! -e firmware.bin ]; then echo "NG! file firmware.bin not found!" >&2; finish 1; fi 37 | echo "OK" >&2 38 | 39 | echo -n " checking symbols..." >&2 40 | #find symbol _SEC_LANG in section '.text' 41 | sec_lang=$(cat text.sym | grep -E "\b_SEC_LANG\b") 42 | if [ -z "$sec_lang" ]; then echo "NG!\n symbol _SEC_LANG not found!" >&2; finish 1; fi 43 | #find symbol _PRI_LANG_SIGNATURE in section '.text' 44 | pri_lang=$(cat text.sym | grep -E "\b_PRI_LANG_SIGNATURE\b") 45 | if [ -z "$pri_lang" ]; then echo "NG!\n symbol _PRI_LANG_SIGNATURE not found!" >&2; finish 1; fi 46 | echo "OK" >&2 47 | 48 | echo " calculating vars:" >&2 49 | #get pri_lang addres 50 | pri_lang_addr='0x'$(echo $pri_lang | cut -f1 -d' ') 51 | echo " pri_lang_addr =$pri_lang_addr" >&2 52 | #get addres and size 53 | sec_lang_addr='0x'$(echo $sec_lang | cut -f1 -d' ') 54 | sec_lang_size='0x'$(echo $sec_lang | cut -f2 -d' ') 55 | echo " sec_lang_addr =$sec_lang_addr" >&2 56 | echo " sec_lang_size =$sec_lang_size" >&2 57 | #calculate lang_table_addr (aligned to 256byte page) 58 | lang_table_addr=$((256*$((($sec_lang_addr + 255) / 256)))) 59 | printf " lang_table_addr =0x%04x\n" $lang_table_addr >&2 60 | #calculate lang_table_size 61 | lang_table_size=$((256*$((($sec_lang_size - ($lang_table_addr - $sec_lang_addr))/256)))) 62 | printf " lang_table_size =0x%04x (=%d bytes)\n" $lang_table_size $lang_table_size >&2 63 | 64 | #get lang_xx.bin file size 65 | lang_file_size=$(wc -c lang_$LNG.bin | cut -f1 -d' ') 66 | printf " lang_file_size =0x%04x (=%d bytes)\n" $lang_file_size $lang_file_size >&2 67 | 68 | if [ $lang_file_size -gt $lang_table_size ]; then echo "Lanaguage binary file size too big!" >&2; finish 1; fi 69 | 70 | echo "updating 'firmware.bin'..." >&2 71 | 72 | dd if=lang_$LNG.bin of=firmware.bin bs=1 seek=$lang_table_addr conv=notrunc 2>/dev/null 73 | 74 | #convert bin to hex 75 | echo "converting to hex..." >&2 76 | $OBJCOPY -I binary -O ihex ./firmware.bin ./firmware_$LNG.hex 77 | 78 | finish 0 79 | -------------------------------------------------------------------------------- /prepare_winbuild.ps1: -------------------------------------------------------------------------------- 1 | #This powershell script prepares your Windows 10 64-bit computer to be able to compile your 2 | #Prusa Firmware by installing a Linux Subsystem 3 | #Please run it as administrator 4 | 5 | Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux 6 | Invoke-WebRequest -Uri https://aka.ms/wsl-ubuntu -OutFile Ubuntu.appx -UseBasicParsing -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd .. || exit 5 3 | 4 | if [ ! -d "Prusa-Firmware-test" ]; then 5 | mkdir Prusa-Firmware-test || exit 10 6 | fi 7 | 8 | cd Prusa-Firmware-test || exit 20 9 | 10 | cmake -G "Eclipse CDT4 - Ninja" ../Prusa-Firmware || exit 30 11 | cmake --build . || exit 35 12 | ./tests || exit 40 --------------------------------------------------------------------------------