diff --git a/.gitignore b/.gitignore index 40220ff..e27dc13 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ build-env build doc tags +*.zip diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 1ae103d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -os: linux -dist: xenial -language: cpp -script: - - git fetch --tags --unshallow || if [ $? -eq 128 ]; then true; else false; fi - - git rev-list --count HEAD - - bash -x build.sh -deploy: - provider: releases - token: $ACCESS_TOKEN - file_glob: true - file: - - build/Prusa-CW1*-Firmware-*.hex - skip_cleanup: true - draft: true - prerelease: true - on: - tags: true diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c7d3a06 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,220 @@ +# 3.3.0 + +## Summary +* Max. 255 minutes runtime +* Fix: wash cycles +* New filter cleaning mode +* Travis build was removed + +## Detailed description +### Max. 255 minutes runtime +The maximum run time was set to 255 minutes for all operations. + +### fix: wash cycles +Wash cycles were not performed correctly after rotator run time changes. + +### New filter cleaning mode +Added a new “filtering” mode for cleaning IPA with a filter. This is another +washing mode without changing the direction of rotation with its own speed and +running time. Value settings are in the usual places. There is a new item “IPA +Filtering” in the main menu. Please refer to the updated user manual for +further use of the filter. + +### Travis build was removed +Building with Travis is no longer supported and future releases will not be +released using this system due to the limiting of terms of use on the Travis +side. + + +# 3.2.0 + +## Summary +* Code refactoring and optimizations +* Automatic fans control +* New heating algorithm for CW1 device +* Set all timers to max. 60 minutes +* Do not handle info pages as menus +* Change motor direction while washing +* Factory reset +* Improved self-test +* Allow to extend the run time to a defined maximum +* Updated documentation + +## Detailed description +### Code refactoring and optimizations +* The code for CW1 and CW1S was splitted into separate files for easier modifications. +* The Makefile was improved to support the build of different devices via command line option. +* Pluggable USB in USBCore library was dissabled to save space. It was not used. +* Menu with live values of fans RPM and temperatures was removed to save space. + It was used only for debugging purposes and had no importance for the user. + +### Automatic fans control +Prior to this version, the fans were set to a fixed speed. The fans are now +controlled according to the cooling demand. In most cases, they can remain at +the lowest possible speed and increase to the maximum only when the temperature +rises. This may affect device noise during certain operations. + +### New heating algorithm for CW1 device +The heating method was changed for original CW1. Newly, it tries to maintain +the set temperature in the chamber. CW1 can only switch the heating on and off +and, as a result, the temperature in the chamber fluctuates. These adjustments +were necessary for longer heating times, when CW1 significantly overheated the +chamber. If you have had your favorite heating temperatures, you need to revise +these settings. Please note that the maximum allowed temperature of 60 ˚C +(140 ˚F) is the limit and may affect the life of the device. + +### Set all timers to max. 60 minutes +All operations (curing, drying, washing, resin preheating) can now take up to +60 minutes. + +### Do not handle info pages as menus +The information page is displayed as scrolling text only and allows you to view +the entire serial number. + +### Change motor direction while washing +For washing, it is now possible to set the number of washing cycles. One cycle +is the rotation of the impeller in one direction. The length of one cycle is +calculated from the total washing time so that all cycles last the same time. +This could improve the efficiency of washing prints. The default value is one +cycle, i.e. washing without changing direction as before. + +### Factory reset +In the advanced settings (long press in the settings), a factory reset is now +available, which applies the default settings of all configurable values. + +### Improved self-test +The UV LED and heater test run only for the necessary time instead of a fixed +time. + +### Allow to extend the run time to a defined maximum. +The increase of run time during the ongoing operation was limited to 10 +minutes. Newly, this value is the maximum for each operation (60 minutes). + +### Updated documentation +The README has been updated and a CHANGELOG has been created. + + +# 3.1.0 + +## Summary +* Support for CW1S +* Drying temperature increased (CW1S) +* Drying session extended +* Hold the platform (new feature) +* Improved translations + +## Detailed description +This is the final release of firmware 3.1.0, the first firmware release with +support for both the CW1 and the new CW1S. `Attention, the firmware is not +universal, each device requires its own firmware file!` + +### Support for CW1S +This release of the firmware brings support for the recently announced Original +Prusa Curing and Washing Machine CW1S. The CW1S features a reworked heating +system, which required a completely redesigned heating algorithm. + +### Drying temperature increased (CW1S) +As mentioned above, the CW1S brings reworked internals with the aim to improve +its drying capabilities. This firmware release enables CW1S owners to increase +the target temperature up to 60 °C. Note that the limit for CW1 is 40 °C. + +### Drying session extended +Previously, the system allowed for a 10 minutes drying session. This is now +extended to 60 minutes for both CW1 and CW1S. + +### Hold the platform (new feature) +Original Prusa CW1S brings a removable platform protected with an FEP film. +Once there is a bigger amount of residue on the film, it might be necessary to +replace it with a new one. To help align the platform back to its original +position, the user can activate “Hold the platform” from the menu. + +The motor gets “locked” (rotation is disabled) by the system, temporarily +allowing the user to align the platform properly. Once the platform is properly +seated, exit the menu to “unlock” the motor. + +### Improved translations +Since there are some changes to firmware 3.1.0, the translators have rechecked +all the language strings. Should you find any incorrect translations, please +let us know. + + +# 3.0.0 + +## Summary +* Code refactoring and optimizations +* Firmware localized into 7 languages +* Resin preheat +* Extended curing time +* Factory self-test +* Updated user manual + +## Detailed description +### Code refactoring and optimizations +The firmware for the CW1 was refactored in order to provide more space in the +memory for new features and also to lower the CPU load. Most of the work on the +code is not visible to the user, however, it was needed for the new functions +introduced in this release. + +### Firmware localized into 7 languages +Until now, the firmware for the Original Prusa CW1 was available only in the +English language. With this release, we are adding support for more languages. +Apart from English, users can now also select: +* Czech +* German +* Spanish +* French +* Italian +* Polish + +Each language is distributed as a separate firmware file. For example to +install the German language select the file +`Prusa-CW1-Firmware-de-v3.0.0-rc.1.hex`, connect the CW1 to your computer and +flash the file over PrusaSlicer. + +### Resin preheat +Some advanced resins, for example, those used in the dental laboratories, +require elevated temperatures in order to improve the viscosity. Without +raising the temperature of the resin, the print will in many cases fail or the +model won't be exposed to the UV light properly. + +Based on the feedback from our customers, we have added this preheat feature to +the CW1. Insert the resin in a bottle in the CW1, close the cover and from the +menu select “Resin preheat“. Based on the requirements of your resin, you can +adjust the time in the range of 1 - 30 minutes and the temperature 20 - 40 °C. + +### Extended curing time +Advanced resins sometimes require longer curing periods and for this reason, +the time was extended to 1 hour (60 minutes). Several resins were tested in our +laboratory and the recommended curing times with CW1 will be included in the +resin datasheet (RDS) on our eshop. + +### Factory self-test +Before every unit of CW1 is sent to the customer, a series of tests is +performed to ensure the machine works as expected. The testing procedure is now +part of a semi-automated test routine, with the following parts: +* Cover switch (semi-automatic) +* IPA tank detection (semi-automatic) +* Motor test - platform rotation (semi-automatic) +* Cooling fans (automatic) +* UV LED (automatic) +* Heater (automatic) + +### Updated user manual +The technical documentation was updated and is covering all the changes and new +features introduced in this firmware. You can download an online copy of the +CW1 user manual from here https://prusa3d.com/drivers + + +# 2.1.4 + +## Summary +* Fan speed optimization + +## Detailed description +The RPMs of the fan were optimized to lower the level of noise. + + +# 2.1.3 + +## Summary +* Initial version release diff --git a/Makefile b/Makefile index fb73b69..3a3ccc7 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,9 @@ -PROJECT = Prusa-CW1-Firmware -PROJECT_CW1S = Prusa-CW1S-Firmware +# CW1S is the default, use `make DEVICE=CW1` for CW1 +DEVICE = CW1S +#DEVICE = CW1 +PROJECT = Prusa-${DEVICE}-Firmware DIRS = lib src +DEVICES_DIR = devices I18N = i18n LANG = en BUILD_DIR = build @@ -17,33 +20,35 @@ CPPTUNING = -fno-exceptions -fno-threadsafe-statics OPT = -g -Os -ffunction-sections -fdata-sections -flto -fno-fat-lto-objects -funsigned-char -funsigned-bitfields -fshort-enums -fno-inline-small-functions -mcall-prologues -fno-split-wide-types MCU = -mmcu=atmega32u4 -DEFS = -DF_CPU=16000000 -DARDUINO=10805 -DUSB_VID=0x2c99 -DUSB_MANUFACTURER='"Prusa Research prusa3d.com"' -INCLUDE = $(foreach dir, ${DIRS}, -I${dir}) -I${BUILD_DIR} +ifeq (${DEVICE}, CW1) +USB_PID = 0x0008 +else ifeq (${DEVICE}, CW1S) +USB_PID = 0x000F +else +$(error Use CW1 or CW1S as DEVICE) +endif + +DEFS = -DF_CPU=16000000 -DARDUINO=10805 -DUSB_VID=0x2c99 -DUSB_PID=${USB_PID} -DUSB_MANUFACTURER='"Prusa Research prusa3d.com"' -DUSB_PRODUCT='"Original Prusa ${DEVICE}"' -D${DEVICE}_HW +INCLUDE = $(foreach dir, ${DIRS}, -I${dir}) -I${DEVICES_DIR} -I${BUILD_DIR} CFLAGS = ${OPT} ${WARN} ${CSTANDARD} ${MCU} ${INCLUDE} ${DEFS} CPPFLAGS = ${OPT} ${WARN} ${CPPSTANDARD} ${CPPTUNING} ${MCU} ${INCLUDE} ${DEFS} -LINKFLAGS = -fuse-linker-plugin -Wl,--relax,--gc-sections,--defsym=__TEXT_REGION_LENGTH__=28k - -CSRCS = $(foreach dir, ${DIRS}, $(wildcard ${dir}/*.c)) -CPPSRCS = $(foreach dir, ${DIRS}, $(wildcard ${dir}/*.cpp)) -OBJS = $(addprefix $(BUILD_DIR)/, $(patsubst %.c, %.o, $(CSRCS))) $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.o, $(CPPSRCS))) -DEPS = $(addprefix $(BUILD_DIR)/, $(patsubst %.c, %.d, $(CSRCS))) $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.dd, $(CPPSRCS))) -VERSION = $(shell git describe --abbrev=0 --tags) +LINKFLAGS = -fuse-linker-plugin -Wl,--relax,--gc-sections,--defsym=__TEXT_REGION_LENGTH__=28k,--defsym=__DATA_REGION_LENGTH__=2560,--print-memory-usage + +DEVICE_LOWER := $(shell echo ${DEVICE} | tr '[:upper:]' '[:lower:]') +CSRCS := $(foreach dir, ${DIRS}, $(wildcard ${dir}/*.c)) +CPPSRCS := $(foreach dir, ${DIRS}, $(wildcard ${dir}/*.cpp)) ${DEVICES_DIR}/${DEVICE_LOWER}.cpp +OBJS := $(addprefix $(BUILD_DIR)/, $(patsubst %.c, %.o, $(CSRCS))) $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.o, $(CPPSRCS))) +DEPS := $(addprefix $(BUILD_DIR)/, $(patsubst %.c, %.d, $(CSRCS))) $(addprefix $(BUILD_DIR)/, $(patsubst %.cpp, %.dd, $(CPPSRCS))) +VERSION := $(shell git describe --abbrev=0 --tags) VERSION_FILE = ${BUILD_DIR}/version.h LANG_TEMPLATE = ${I18N}/${PROJECT}-${VERSION}.pot -default: DEFS += -DUSB_PRODUCT='"Original Prusa CW1"' -DUSB_PID=0x0008 -DSERIAL_COM_DEBUG -default: DEVICE = cw1 +default: DEFS += -DSERIAL_COM_DEBUG default: $(addprefix $(BUILD_DIR)/, ${PROJECT}-${LANG}-devel.hex) -dist: DEFS += -DUSB_PRODUCT='"Original Prusa CW1"' -DUSB_PID=0x0008 -dist: DEVICE = cw1 dist: $(addprefix $(BUILD_DIR)/, ${PROJECT}-${LANG}-${VERSION}.hex) -cw1s: DEFS += -DCW1S -DUSB_PRODUCT='"Original Prusa CW1S"' -DUSB_PID=0x000F -cw1s: DEVICE = cw1s -cw1s: $(addprefix $(BUILD_DIR)/, ${PROJECT_CW1S}-${LANG}-${VERSION}.hex) - .PHONY: clean distclean lang_extract default dist ${VERSION_FILE}.tmp doc .SECONDARY: @@ -58,7 +63,7 @@ $(BUILD_DIR)%/.: $(BUILD_DIR)/%.hex: ${BUILD_DIR}/%.elf ${OBJCOPY} -O ihex -R .eeprom $< $@.tmp - @echo "; device = ${DEVICE}" > $@ + @echo "; device = ${DEVICE_LOWER}" > $@ @echo >> $@ cat $@.tmp >> $@ rm $@.tmp @@ -92,7 +97,7 @@ $(VERSION_FILE).tmp: ${BUILD_DIR}/${LANG}.h | $${@D}/. @echo "\"${LANG}.h\"" >> $@ clean: - rm -f $(foreach dir, ${DIRS}, $(wildcard ${BUILD_DIR}/${dir}/*.o)) $(foreach dir, ${DIRS}, $(wildcard ${BUILD_DIR}/${dir}/*.d*)) ${BUILD_DIR}/*.h $(VERSION_FILE).tmp ${BUILD_DIR}/*.sed + rm -f $(foreach dir, ${DIRS} ${DEVICES_DIR}, $(wildcard ${BUILD_DIR}/${dir}/*.o)) $(foreach dir, ${DIRS} ${DEVICES_DIR}, $(wildcard ${BUILD_DIR}/${dir}/*.d*)) ${BUILD_DIR}/*.h $(VERSION_FILE).tmp ${BUILD_DIR}/*.sed distclean: clean rm -rf ${BUILD_DIR}/*.hex ${BUILD_DIR}/*.elf ${BUILD_DIR}/*.map ${I18N}/*.pot tags doc diff --git a/README.md b/README.md index 5a84be9..74dd3d3 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,16 @@ -# Prusa-CW1-Firmware +# Prusa CW1/CW1S Firmware Original Prusa Curing and Washing machine firmware ## Table of contents + * [Function notes](#function-notes) + * [Hidden menu](#hidden-menu) + * [Selftest](#selftest) + * [Cooling](#cooling) + * [Temperature display on CW1](#temperature-display-on-cw1) + * [Hold the platform](#hold-the-platform) * [Building with make](#building-with-make) - * [Automatic, remote, using travis-ci](#automatic-remote-using-travis-ci) * [Automatic, local, using script and prepared tools package](#automatic-local-using-script-and-prepared-tools-package) * [Manually with installed tools](#manually-with-installed-tools) * [Flashing](#flashing) @@ -13,15 +18,44 @@ Original Prusa Curing and Washing machine firmware -## Building with make -### Automatic, remote, using travis-ci +## Function notes +### Hidden menu + +You can get to the “hidden” settings menu by long pressing the rotator in the +settings menu. Contains UVLED intensity, Factory reset, Cooldown and Selftest. + +### Selftest + +You can use the self-test to test the functionality of your device. The +semi-automatic tests require your cooperation and are the lid switch test, the +IPA container detection test, and the motor test (which visually assesses that +the platform is moving). This is followed by fan, UV LED and heating tests. +They will run by themselves, all you have to do is close the lid. + +### Cooling + +The fans are controlled in such a way that the device is cooled as best as +possible. In some cases, the fans can run at full power, which can cause more +noise. That's normal. -Create new github user, eg. your_user_name-your_repository_name-travis. This step is not mandatory, only recomended to limit access rights for travis to single repository. Grant this user access to your repository. Register this user on https://www.travis-ci.com/. Create API key for this user. In Github click on this user, settings, Developer settings, Personal access tokens, Generate new token, select public_repo, click on Generate token and copy this token. +### Temperature display on CW1 -Login into https://www.travis-ci.com/ enable build of your repository, click on repository setting, add environment variable `ACCESS_TOKEN` and paste your token. +Due to the location of the thermistor in CW1 (not applicable to CW1S), the +temperature measurement inside the device is relatively imprecise and is +subsequently compensated. For this reason, the temperature is shown on the +display after 2 minutes from the start of heating. Until then, “-- ˚C” is +displayed. -Each commit is build, but only for tagged commits `Prusa-CW1-Firmware-LANG-GIT_TAG.hex` files are attached to your release by travis. +### Hold the platform +Original Prusa CW1S or CW1 platform upgrade brings a removable platform +protected with an FEP film. To help align the platform back to its original +position, the user can activate “Hold the platform” from the menu. The motor +gets “locked” (rotation is disabled) by the system, temporarily allowing the +user to align the platform properly. Once the platform is properly seated, exit +the menu to “unlock” the motor. + +## Building with make ### Automatic, local, using script and prepared tools package You need to install unzip, wget and make tools, next run the following command: @@ -34,6 +68,8 @@ It downloads neccessary tools, creates `build` subfolder, extracts tools to `bui You need make, avr-gcc and avr-libc installed. +You can use the DEVICE=CW1 or DEVICE=CW1S parameter to select which device you want to build, the default is CW1S. + To build version with debug turned on use: ~~~ make @@ -42,7 +78,7 @@ or with language code: ~~~ make LANG=xx ~~~ -The file `build/Prusa-CW1-Firmware-LANG-devel.hex` will be generated. +The file `build/Prusa-CW1S-Firmware-LANG-devel.hex` will be generated. To build version without debug use: ~~~ @@ -50,7 +86,7 @@ make dist ~~~ or with language code: ~~~ -make LANG=xx dist +make DEVICE=CW1 LANG=xx dist ~~~ The file `build/Prusa-CW1-Firmware-LANG-GIT_TAG.hex` will be generated. @@ -63,11 +99,14 @@ Configuration > Flash printer firmware, then fill up the path to generated .hex Board needs to be reset to bootloader. Bootloader has 5 seconds timeout and then returns to the application. -This can be accomplished manually by clicking reset button on CW1 (near microUSB port), or programmatically by opening and closing its virtual serial line at baudrate 1500. - -Than flash it using following command, replace \ with CDC device created by CW1 usually `com` under Windows and `/dev/ttyACM` under Linux. `-b` baud rate is don't care value, probably doesn't have to be specified at all, as there is no physical uart. +This can be accomplished manually by pressing reset button on CW1/CW1S (near microUSB port), or programmatically by opening and closing its virtual serial line at baudrate 1200. +Linux command (replace \ with CDC device created by CW1/CW1S usually `/dev/ttyACM`): +~~~ +stty -F 1200 crtscts; while :; do sleep 0.5; [ -c ] && break; done; +~~~ +Then flash it using following command, replace \ with CDC device created by CW1/CW1S usually `com` under Windows and `/dev/ttyACM` under Linux. `-b` baud rate is don't care value, probably doesn't have to be specified at all, as there is no physical uart. ~~~ -avrdude -v -p atmega32u4 -c avr109 -P -b 57600 -D -U flash:w:build/Prusa-CW1-Firmware-LANG-GIT_TAG.hex:i +avrdude -v -p atmega32u4 -c avr109 -P -b 57600 -D -U flash:w:build/Prusa-DEVICE-Firmware-LANG-GIT_TAG.hex:i ~~~ ### Linux with ModemManager installed diff --git a/build.sh b/build.sh index eb0f2e7..0bf4201 100755 --- a/build.sh +++ b/build.sh @@ -14,8 +14,8 @@ export PATH=$SCRIPT_PATH/$ENV_DIR/avr/bin:$PATH for LG in "en" "cs" "de" "es" "fr" "it" "pl" ; do make clean || exit 4 - make "LANG=$LG" dist || exit 5 + make "LANG=$LG" "DEVICE=CW1" dist || exit 5 - make clean || exit 4 - make "LANG=$LG" cw1s || exit 5 + make clean || exit 6 + make "LANG=$LG" "DEVICE=CW1S" dist || exit 7 done diff --git a/devices/cw1.cpp b/devices/cw1.cpp new file mode 100644 index 0000000..91c8ddb --- /dev/null +++ b/devices/cw1.cpp @@ -0,0 +1,64 @@ +#include "device.h" +#include "i18n.h" +#include "LiquidCrystal_Prusa.h" + +CW1::CW1() +: + Hardware(0x3130), // "01" + heater_on_ms(0), + heater_pin_state(false) +{} + +void CW1::one_ms_tick() { +} + +char* CW1::print_heater_fan(char* buffer, uint8_t size) { + buffer_init(buffer, size); + print_P(pgmstr_fan3); + print(fan_rpm[2]); + return get_position(); +} + +inline bool CW1::handle_heater() { + return heater_pin_state && !fan_rpm[2] && millis() - heater_on_ms > HEATER_CHECK_DELAY; +} + +void CW1::heating() { + if (heating_in_progress and round_short(get_configured_temp(chamber_temp_celsius)) < chamber_target_temp) { + set_heater_pin_state(true); + } else { + set_heater_pin_state(false); + } +} + +void CW1::set_heater_pin_state(bool value) { + if (heater_pin_state != value) { + USB_PRINTP("heater: "); + USB_PRINTLN(value); + outputchip.digitalWrite(FAN_HEAT_PIN, value); + heater_pin_state = value; + if (value) { + heater_on_ms = millis(); + } + } +} + +inline void CW1::set_cooling_speed(uint8_t speed) { + set_fan_speed(0, speed); + set_fan_speed(1, speed); +} + +float CW1::adjust_chamber_temp(int16_t temp) { +// USB_PRINTLN(temp); + if (temp < 0.0) { + return temp; + } + // approx. dependency of chamber temp (2 mins delay) + unsigned long ms_now = millis(); + if (heating_in_progress && ms_now - heating_started_ms > 120000) { + return 0.15 * temp; + } + return 0.0; +} + +CW1 hw; diff --git a/devices/cw1.h b/devices/cw1.h new file mode 100644 index 0000000..2892cbf --- /dev/null +++ b/devices/cw1.h @@ -0,0 +1,24 @@ +#pragma once + +#include "hardware.h" +#include "simple_print.h" + +class CW1 : public Hardware, public SimplePrint { +public: + CW1(); + void one_ms_tick(); + char* print_heater_fan(char* buffer, uint8_t size); + +private: + inline bool handle_heater(); + void heating(); + void set_heater_pin_state(bool value); + inline void set_cooling_speed(uint8_t speed); + float adjust_chamber_temp(int16_t temp); + + unsigned long heater_on_ms; + bool heater_pin_state; +}; + + +extern CW1 hw; diff --git a/devices/cw1s.cpp b/devices/cw1s.cpp new file mode 100644 index 0000000..12a100c --- /dev/null +++ b/devices/cw1s.cpp @@ -0,0 +1,92 @@ +#include "device.h" +#include "i18n.h" +#include "LiquidCrystal_Prusa.h" +#include "config.h" + +CW1S::CW1S() +: + Hardware(0x3230), // "02" + wanted_heater_pin_state(false), + heater_pin_state(false), + heater_pwm(0) +{} + +void CW1S::one_ms_tick() { + static uint16_t ticks; // inicialized with zero by standard + if (heating_in_progress) { + // heater is on + if (++ticks > 1000) { + ticks = 0; + } + wanted_heater_pin_state = ticks < heater_pwm; + } +} + +void CW1S::stop_heater() { + wanted_heater_pin_state = false; + set_heater_pin_state(false); + Hardware::stop_heater(); +} + +char* CW1S::print_heater_fan(char* buffer, uint8_t size) { + buffer_init(buffer, size); + print_P(pgmstr_fan1); + print(fan_rpm[0]); + return get_position(); +} + +inline bool CW1S::handle_heater() { + if (wanted_heater_pin_state != heater_pin_state) { + set_heater_pin_state(wanted_heater_pin_state); + } + return !fan_rpm[0] && millis() - heating_started_ms > HEATER_CHECK_DELAY; +} + +void CW1S::heating() { + if (fans_forced) { + return; + } + if (heating_in_progress) { + // heater is on + float error = chamber_target_temp + 2 - get_configured_temp(chamber_temp_celsius); + uint16_t pwm = error > 0.0 ? round((error < 2.0 ? error : 2.0) * 500) : 0; + USB_PRINTP("req: "); + USB_PRINT(chamber_target_temp); + USB_PRINTP(" err: "); + USB_PRINT(error); + USB_PRINTP(" -> "); + USB_PRINTLN(pwm); + heater_pwm = pwm; + set_fan_speed(0, HEATING_ON_FAN1_SPEED); + } else { + // heater is off + set_fan_speed(0, MIN_FAN_SPEED); + } +} + +void CW1S::set_heater_pin_state(bool value) { + outputchip.digitalWrite(FAN_HEAT_PIN, value); + heater_pin_state = value; +} + +void CW1S::set_cooling_speed(uint8_t speed) { + set_fan_speed(1, speed); +} + +float CW1S::adjust_chamber_temp(int16_t temp) { +// USB_PRINTLN(temp); + return 0.1 * temp; +/* Denied solution to compensate temperature in chamber: + if (temp < 0.0) { + return temp; + } + // approx. dependency of chamber temp + if (heating_in_progress) { + return 0.06 * temp + 10; + } + return 0.0; +*/ +} + + +CW1S hw; diff --git a/devices/cw1s.h b/devices/cw1s.h new file mode 100644 index 0000000..d171e5f --- /dev/null +++ b/devices/cw1s.h @@ -0,0 +1,26 @@ +#pragma once + +#include "hardware.h" +#include "simple_print.h" + +class CW1S : public Hardware, public SimplePrint { +public: + CW1S(); + void one_ms_tick(); + void stop_heater(); + char* print_heater_fan(char* buffer, uint8_t size); + +private: + inline bool handle_heater(); + void heating(); + inline void set_cooling_speed(uint8_t speed); + void set_heater_pin_state(bool value); + float adjust_chamber_temp(int16_t temp); + + bool wanted_heater_pin_state; + bool heater_pin_state; + uint16_t heater_pwm; +}; + + +extern CW1S hw; diff --git a/i18n/cs.po b/i18n/cs.po index 6d20763..792cf50 100644 --- a/i18n/cs.po +++ b/i18n/cs.po @@ -1,363 +1,313 @@ msgid "" msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" "Language: cs\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " V2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || n%10 == 1 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 12 && n%100 <= 14)) ? 2 : 3);\n" +"X-Generator: Poedit 3.2.2\n" #: i18n/en.h:2 msgid "Back" msgstr "Zpet" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " msgstr "Sestaveni: " -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Tep. komory:" - -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" -msgstr "Zavrete viko" +msgstr "Zavrete kryt" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" msgstr "Pokracovat" -#: i18n/en.h:37 +#: i18n/en.h:44 +msgid "continuous" +msgstr "nepretrzite" + +#: i18n/en.h:41 msgid "Control echo" -msgstr "Odezva ovl." +msgstr "Zvuk. odezva" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" -msgstr "Zchladit" +msgstr "Ochlazeni" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" -msgstr "Test vika" +msgstr "Test krytu" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" -msgstr "Tvrzeni" +msgstr "Vytvrzeni" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" -msgstr "Cas vytvrzovani" +msgstr "Doba vytvrzeni" -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Rychlost pro tvrz." +msgstr "Rychlost vytvrzeni" -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" msgstr "Suseni" -#: i18n/en.h:17 +#: i18n/en.h:60 +msgid "Drying/curing" +msgstr "Suseni/Vytvrzeni" + +#: i18n/en.h:18 msgid "Drying run-time" msgstr "Doba suseni" -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "T. pro suseni" - -#: i18n/en.h:79 -msgid "Drying/curing" -msgstr "Tvrzeni/suseni" +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "T. suseni/vyhrevu" -#: i18n/en.h:141 +#: i18n/en.h:117 msgid "F1:" -msgstr "V1:" - -#: i18n/en.h:143 -msgid "F3:" -msgstr "V3:" - -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " +msgstr "F1:" -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "V1 ot/min: " +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2:" -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Rychlost V1 tvrz." +#: i18n/en.h:119 +msgid "F3:" +msgstr "F3:" -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Rychlost V1 sus." +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Tovarni reset" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" -msgstr "Ventilator1 selhal" - -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Rychl. V1 (menu)" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Rychlost V1 myti" +msgstr "Chyba Vent1" -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "V2 ot/min: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Rychlost V2 tvrz." - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Rychlost V2 sus." - -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" -msgstr "Ventilator2 selhal" - -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Rychlost V2 menu" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Rychl. V2 (myti)" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "V3 ot/min: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Ventilatory" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Rychl. v. (tvrzeni)" - -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Rychlost pro sus." - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Rychl. v. (menu)" +msgstr "Chyba Vent2" -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Test ventilatoru" +msgstr "Test vent." -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Rychlost pro myti" +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Doba filtrace" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Rychlost filtrace" + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Koncovy pip" +msgstr "Koncove pipnuti" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" -msgstr "Hotovo" +msgstr "Dokonceno" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW: " + +#: i18n/en.h:113 msgid "Heater failure" -msgstr "Chyba nahrivani" +msgstr "Chyba topeni" -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" -msgstr "Chyba nahriv. v." +msgstr "Chyba vent. topeni" -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" -msgstr "Test nahrivani" +msgstr "Test vyhrevu" -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" -msgstr "Nahrivani" +msgstr "Zahrivani" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" -msgstr "Podrzet platformu" +msgstr "Drzte platformu" -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "Test IPA nadoby" - -#: i18n/en.h:153 +#: i18n/en.h:129 msgid "Incorrect firmware!" -msgstr "Nespravny firmware!" +msgstr "Nespravny FW!" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" msgstr "Informace" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" -msgstr "Vlozte IPA nadobu" +msgstr "Vlozte nadrz s IPA" + +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "Filtrovani IPA" + +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "Test nadrze s IPA" -#: i18n/en.h:83 +#: i18n/en.h:64 msgid "LCD brightness" msgstr "Jas LCD" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr " min." + +#: i18n/en.h:115 msgid "No/low power" -msgstr "Zadny/maly vykon" +msgstr "Chyba napajeni" -#: i18n/en.h:147 +#: i18n/en.h:42 +msgid "none" +msgstr "zadne" + +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "Problem otaceni" +msgstr "Chyba otaceni" + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[vyp]" + +#: i18n/en.h:3 +msgid "[on]" +msgstr "[zap]" + +#: i18n/en.h:43 +msgid "once" +msgstr "jednou" -#: i18n/en.h:151 +#: i18n/en.h:127 msgid "Open the cover" -msgstr "Otevrete viko" +msgstr "Otevrete kryt" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" -msgstr "Prehrati" +msgstr "Prehrivani" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" msgstr "Pauza" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" msgstr "Pauza" -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Restartujte CW1" - -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" msgstr "Potvrdte stiskem" -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" -msgstr "Chyba cteni t." +msgstr "Chyba cteni tep." -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "Resetovat vse?" + +#: i18n/en.h:93 msgid "Remove IPA tank" -msgstr "Vyjmete IPA nadobu" +msgstr "Odstran IPA nadrz" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" msgstr "Ohrati resinu" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." -msgstr "T. ohrati resinu" +msgstr "Tep. ohrati res." -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" msgstr "Doba ohrati resinu" -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Rychlost otaceni" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Nastaveni otaceni" -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" msgstr "Test otaceni" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" -msgstr "Pracovni rezim" +msgstr "Rezim behu" -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" msgstr "Doba behu" -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Selftest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Nastaveni" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" msgstr "Zvuk" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" -msgstr "Toci se vypnuty" +msgstr "Otaceni vypnuto" -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Stop" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "T. jednotky" - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Teploty" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Jednotky t." + +#: i18n/en.h:104 msgid "UVLED failure" -msgstr "Chyba UVLED" +msgstr "Chyba UV LED" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "Intenzita UVLED" - -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "Tep. UVLED: " +msgstr "Intenzita UV LED" -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" -msgstr "Test UVLED" +msgstr "Test UV LED" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" msgstr "Predehrev" -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Cykly myti" + +#: i18n/en.h:72 msgid "Washing" msgstr "Myti" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" msgstr "Doba myti" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Rychlost pro myti" - -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Pozor - necistoty" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[vyp]" - -#: i18n/en.h:3 -msgid "[on]" -msgstr "[zap]" - -#: i18n/en.h:40 -msgid "continuous" -msgstr "nepretrzite" - -#: i18n/en.h:38 -msgid "none" -msgstr "zadny" - -#: i18n/en.h:39 -msgid "once" -msgstr "jednou" +msgstr "Rychlost myti" diff --git a/i18n/de.po b/i18n/de.po index d9ca1a3..3b7652f 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -1,363 +1,313 @@ msgid "" msgstr "" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" "Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " F2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"X-Generator: Poedit 3.2.2\n" #: i18n/en.h:2 msgid "Back" -msgstr "Zuruck" +msgstr "Zurueck" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " msgstr "Build: " -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Gehausetemp.:" - -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" -msgstr "Abdeckung zumachen" +msgstr "Abdeck. schliessen" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" -msgstr "Fortfahren" +msgstr "Weiter" + +#: i18n/en.h:44 +msgid "continuous" +msgstr "laufend" -#: i18n/en.h:37 +#: i18n/en.h:41 msgid "Control echo" -msgstr "Steuerung Echo" +msgstr "Kontrollecho" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" -msgstr "Abkuhlen" +msgstr "Cooldown" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" msgstr "Abdeckungstest" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" -msgstr "Harte" +msgstr "Haerten" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" -msgstr "Hartelaufzeit" +msgstr "Haertelaufzeit" -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Hartetempo" +msgstr "Haertegeschw." -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" -msgstr "Trochne" +msgstr "Trocknen" -#: i18n/en.h:17 -msgid "Drying run-time" -msgstr "Trockenlaufzeit" +#: i18n/en.h:60 +msgid "Drying/curing" +msgstr "Trocknen/Haerten" -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "Trocknen Aufwarmz." +#: i18n/en.h:18 +msgid "Drying run-time" +msgstr "Trocknungslaufzeit" -#: i18n/en.h:79 -msgid "Drying/curing" -msgstr "Trockne/Harte" +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "Tmp. trocknen/aufw" -#: i18n/en.h:141 +#: i18n/en.h:117 msgid "F1:" msgstr "F1:" -#: i18n/en.h:143 +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2:" + +#: i18n/en.h:119 msgid "F3:" msgstr "F3:" -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " - -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "Lufter1 UPM: " - -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Lufter1 Hartetempo" - -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Lufter1 Trocktempo" +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Werkseinstellung" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" -msgstr "Lufter1 Fehler" - -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Lufter1 Menutempo" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Lufter1 Waschtempo" +msgstr "Luefter1 Fehler" -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "Lufter2 UPM: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Lufter2 Hartetempo" - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Lufter2 Trocktempo" - -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" -msgstr "Lufter2 Fehler" +msgstr "Luefter2 Fehler" -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Lufter2 Menutempo" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Lufter2 Waschtempo" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "Lufter3 UPM: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Lufter" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Lufter Hartetempo" - -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Lufter Trocktempo" - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Lufter Menutempo" - -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Luftertest" +msgstr "Lueftertest" -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Lufter Waschtempo" +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Filterlaufzeit" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Filtergeschw." + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Endeton" +msgstr "Beendungston" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" -msgstr "Beended" +msgstr "Beendet" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW: " + +#: i18n/en.h:113 msgid "Heater failure" msgstr "Heizfehler" -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" -msgstr "Heizlufterfehler" +msgstr "Heizluefter Fehler" -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" -msgstr "Heiztest" +msgstr "Heizungs-Test" -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" -msgstr "Heize" +msgstr "Heizen" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" msgstr "Plattform halten" -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "IPA Tanktest" - -#: i18n/en.h:153 +#: i18n/en.h:129 msgid "Incorrect firmware!" -msgstr "Falsche Firmware!" +msgstr "Ungueltige FW!" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" msgstr "Informationen" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" msgstr "IPA Tank einsetzen" -#: i18n/en.h:83 +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "IPA Filtern" + +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "IPA Tank Test" + +#: i18n/en.h:64 msgid "LCD brightness" msgstr "LCD Helligkeit" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr " Min." + +#: i18n/en.h:115 msgid "No/low power" -msgstr "Keine/gering Power" +msgstr "Keine/geringe En." -#: i18n/en.h:147 +#: i18n/en.h:42 +msgid "none" +msgstr "keine" + +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "Kein/unzur. Ruhren" +msgstr "Kein/gering. Dreh." + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[aus]" + +#: i18n/en.h:3 +msgid "[on]" +msgstr "[an]" + +#: i18n/en.h:43 +msgid "once" +msgstr "einmal" -#: i18n/en.h:151 +#: i18n/en.h:127 msgid "Open the cover" -msgstr "Abdeckung offnen" +msgstr "Abdeckung oeffnen" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" -msgstr "Uberhitzt" +msgstr "Ueberhitzt" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" msgstr "Pause" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" msgstr "Pausiert" -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Bitte neu starten" - -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" -msgstr "Drucken fur weiter" +msgstr "Druecken z. Ffahren" -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" -msgstr "Temp.-Lesefehler" +msgstr "Temp.Lesefehler" -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "All. zuruecksetzen?" + +#: i18n/en.h:93 msgid "Remove IPA tank" msgstr "IPA Tank entfernen" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" -msgstr "Harz vorwarmen" +msgstr "Harz Vorwaermen" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." msgstr "Harz-Vorwarmtemp." -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" -msgstr "Harz-Vorwarmzeit" +msgstr "Harz Vorwaermzeit" -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Rotationstempo" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Rotations-Einst." -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" msgstr "Rotationstest" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" -msgstr "Laufmodus" +msgstr "Betriebsmodus" -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" -msgstr "Laufzeit" +msgstr "Laufzeiten" -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Selbsttest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Einstellungen" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" -msgstr "Sound" +msgstr "Ton" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" -msgstr "Umruhren aus" +msgstr "Drehen ausg." -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Stopp" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "Temp.einheit" - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Temperaturen" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Temp.Einheiten" + +#: i18n/en.h:104 msgid "UVLED failure" msgstr "UVLED Fehler" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "UVLED Intensitat" - -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "UVLED Temp.:" +msgstr "UVLED Intensitaet" -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" msgstr "UVLED Test" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" -msgstr "Aufwarmen" +msgstr "Aufwaermen" -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Waschzyklen" + +#: i18n/en.h:72 msgid "Washing" -msgstr "Wasche" +msgstr "Waschen" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" msgstr "Waschlaufzeit" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Waschtempo" - -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Bereich schmutzig" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[aus]" - -#: i18n/en.h:3 -msgid "[on]" -msgstr "[an]" - -#: i18n/en.h:40 -msgid "continuous" -msgstr "fortlaufend" - -#: i18n/en.h:38 -msgid "none" -msgstr "kein" - -#: i18n/en.h:39 -msgid "once" -msgstr "einmal" +msgstr "Waschgeschw." diff --git a/i18n/en.h b/i18n/en.h index ccfa58f..b7ed0ff 100644 --- a/i18n/en.h +++ b/i18n/en.h @@ -10,6 +10,7 @@ static const char pgmstr_minutes[] PROGMEM = _(" min."); static const char pgmstr_gt[] PROGMEM = " >"; static const char pgmstr_lt[] PROGMEM = "< "; static const char pgmstr_emptystr[] PROGMEM = ""; +static const char pgmstr_doubledash[] PROGMEM = "--"; // run-time menu static const char pgmstr_run_time[] PROGMEM = _("Run-time"); @@ -17,16 +18,19 @@ static const char pgmstr_curing_run_time[] PROGMEM = _("Curing run-time"); static const char pgmstr_drying_run_time[] PROGMEM = _("Drying run-time"); static const char pgmstr_washing_run_time[] PROGMEM = _("Washing run-time"); static const char pgmstr_resin_preheat_time[] PROGMEM = _("Resin preheat time"); +static const char pgmstr_filtering_run_time[] PROGMEM = _("Filtering run-time"); -// speed menu -static const char pgmstr_rotation_speed[] PROGMEM = _("Rotation speed"); +// rotation menu +static const char pgmstr_rotation_settings[] PROGMEM = _("Rotation settings"); static const char pgmstr_curing_speed[] PROGMEM = _("Curing speed"); static const char pgmstr_washing_speed[] PROGMEM = _("Washing speed"); +static const char pgmstr_wash_dir_changes[] PROGMEM = _("Wash cycles"); +static const char pgmstr_filtering_changes[] PROGMEM = _("Filtering speed"); // temperatore menu static const char pgmstr_temperatures[] PROGMEM = _("Temperatures"); static const char pgmstr_warmup[] PROGMEM = _("Warm-up"); -static const char pgmstr_drying_warmup_temp[] PROGMEM = _("Drying warm-up t."); +static const char pgmstr_drying_warmup_temp[] PROGMEM = _("Drying/Warm-up t."); static const char pgmstr_resin_preheat_temp[] PROGMEM = _("Resin preheat t."); static const char pgmstr_units[] PROGMEM = _("Temp. units"); static const char pgmstr_celsius_units[] PROGMEM = "[\xDF" "C]"; @@ -40,29 +44,6 @@ static const char pgmstr_once[] PROGMEM = _("once"); static const char pgmstr_continuous[] PROGMEM = _("continuous"); static const char pgmstr_finish_beep[] PROGMEM = _("Finish beep"); -// fans curing speed -static const char pgmstr_fans_curing[] PROGMEM = _("Fans curing speed"); -static const char pgmstr_fan1_curing_speed[] PROGMEM = _("Fan1 curing speed"); -static const char pgmstr_fan2_curing_speed[] PROGMEM = _("Fan2 curing speed"); - -// fans drying speed -static const char pgmstr_fans_drying[] PROGMEM = _("Fans drying speed"); -static const char pgmstr_fan1_drying_speed[] PROGMEM = _("Fan1 drying speed"); -static const char pgmstr_fan2_drying_speed[] PROGMEM = _("Fan2 drying speed"); - -// fans washing speed -static const char pgmstr_fans_washing[] PROGMEM = _("Fans washing speed"); -static const char pgmstr_fan1_washing_speed[] PROGMEM = _("Fan1 washing speed"); -static const char pgmstr_fan2_washing_speed[] PROGMEM = _("Fan2 washing speed"); - -// fans menu speed -static const char pgmstr_fans_menu[] PROGMEM = _("Fans menu speed"); -static const char pgmstr_fan1_menu_speed[] PROGMEM = _("Fan1 menu speed"); -static const char pgmstr_fan2_menu_speed[] PROGMEM = _("Fan2 menu speed"); - -// fans menu -static const char pgmstr_fans[] PROGMEM = _("Fans"); - // info menu static const char pgmstr_information[] PROGMEM = _("Information"); static const char pgmstr_fw_version[] PROGMEM = _("FW: ") FW_VERSION; @@ -70,7 +51,7 @@ static const char pgmstr_sn[] PROGMEM = "SN: "; static const char pgmstr_build_nr[] PROGMEM = _("Build: ") FW_BUILDNR; static const char pgmstr_fw_hash[] PROGMEM = FW_HASH; #if FW_LOCAL_CHANGES -static const char pgmstr_workspace_dirty[] PROGMEM = _("Workspace dirty"); +static const char pgmstr_workspace_dirty[] PROGMEM = "(modified sources)"; #endif // config menu @@ -89,18 +70,14 @@ static const char pgmstr_stop[] PROGMEM = _("Stop"); // home menu static const char pgmstr_washing[] PROGMEM = _("Washing"); +static const char pgmstr_filtering[] PROGMEM = _("IPA Filtering"); static const char pgmstr_resin_preheat[] PROGMEM = _("Resin preheat"); -// hw menu -static const char pgmstr_fan1_rpm[] PROGMEM = _("Fan1 RPM: "); -static const char pgmstr_fan2_rpm[] PROGMEM = _("Fan2 RPM: "); -static const char pgmstr_fan3_rpm[] PROGMEM = _("Fan3 RPM: "); -static const char pgmstr_chamber_temp[] PROGMEM = _("Cham. temp.:"); -static const char pgmstr_uvled_temp[] PROGMEM = _("UVLED temp.:"); - // advanced menu static const char pgmstr_cooldown[] PROGMEM = _("Cooldown"); static const char pgmstr_selftest[] PROGMEM = _("Selftest"); +static const char pgmstr_factory_reset[] PROGMEM = _("Factory reset"); +static const char pgmstr_reset_confirm[] PROGMEM = _("Really reset all?"); // state menu static const char pgmstr_progress[] PROGMEM = { '|', '/', '-', BACKSLASH_CHAR }; @@ -115,7 +92,6 @@ static const char pgmstr_paused[] PROGMEM = _("Paused"); static const char pgmstr_close_cover[] PROGMEM = _("Close the cover"); static const char pgmstr_remove_tank[] PROGMEM = _("Remove IPA tank"); static const char pgmstr_heater_error[] PROGMEM = _("Heater fan error"); -static const char pgmstr_please_restart[] PROGMEM = _("Please restart"); // confirm state static const char pgmstr_finished[] PROGMEM = _("Finished"); diff --git a/i18n/es.po b/i18n/es.po index db0c147..3f2d9a4 100644 --- a/i18n/es.po +++ b/i18n/es.po @@ -5,359 +5,306 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " F2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"X-Generator: Prusalator\n" #: i18n/en.h:2 msgid "Back" -msgstr "Atras" +msgstr "Volver" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " -msgstr "Build: " +msgstr "Build:" -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Temp. camara:" - -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" -msgstr "Cierra la tapa" +msgstr "Cierra la cubierta" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" msgstr "Continuar" -#: i18n/en.h:37 +#: i18n/en.h:44 +msgid "continuous" +msgstr "continuo" + +#: i18n/en.h:41 msgid "Control echo" -msgstr "Control sonido" +msgstr "Cont. de eco" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" msgstr "Enfriamiento" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" -msgstr "Test de la tapa" +msgstr "Test cubierta" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" msgstr "Curado" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" -msgstr "Tiempo de curado" +msgstr "Tiempo curado" -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Vel. de curado" +msgstr "Velocidad curado" -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" msgstr "Secado" -#: i18n/en.h:17 -msgid "Drying run-time" -msgstr "Tiempo de secado" - -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "Temp. de presecado" - -#: i18n/en.h:79 +#: i18n/en.h:60 msgid "Drying/curing" msgstr "Secado/curado" -#: i18n/en.h:141 +#: i18n/en.h:18 +msgid "Drying run-time" +msgstr "Tiempo secado" + +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "T. Secado/Cal." + +#: i18n/en.h:117 msgid "F1:" msgstr "F1:" -#: i18n/en.h:143 +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2:" + +#: i18n/en.h:119 msgid "F3:" msgstr "F3:" -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " - -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "RPM Vent1: " - -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Vel. cur. Vent1" - -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Vel. secado Vent1" +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Reset fabrica" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" msgstr "Fallo Vent1" -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Menu vel. Vent1" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Vel. curado Vent1" - -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "RPM Vent2: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Vel. cur. Vent2" - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Vel. secado Vent2" - -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" msgstr "Fallo Vent2" -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Menu vel. Vent2" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Vel. curado Vent2" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "RPM Vent3: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Ventiladores" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Vel. curado vent." - -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Vel. secado vent." - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Menu vel. vent." - -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Test ventilador" +msgstr "Test ventiladores" -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Vel. lavado vent." +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Tiempo filtrado" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Velocidad filtrado" + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Beep al finalizar" +msgstr "Beep al terminar" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" msgstr "Finalizado" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW: " + +#: i18n/en.h:113 msgid "Heater failure" -msgstr "Fallo en calentador" +msgstr "Fallo calentador" -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" -msgstr "Error vent. calent." +msgstr "Error vent. calentador" -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" msgstr "Test calentador" -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" -msgstr "Calentando" +msgstr "Calentamiento" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" -msgstr "Sujeta la plat." - -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "Test tanque IPA" +msgstr "Sujeta la plataf." -#: i18n/en.h:153 +#: i18n/en.h:129 msgid "Incorrect firmware!" -msgstr "Firmware incorrecto!" +msgstr "FW incorrecto!" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" msgstr "Informacion" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" -msgstr "Introd. tanque IPA" +msgstr "Intro. tanque IPA" -#: i18n/en.h:83 +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "Filtrado IPA" + +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "Test tanque IPA" + +#: i18n/en.h:64 msgid "LCD brightness" msgstr "Brillo LCD" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr " min." + +#: i18n/en.h:115 msgid "No/low power" -msgstr "No/poca energia" +msgstr "No/potencia baja" + +#: i18n/en.h:42 +msgid "none" +msgstr "ninguno" -#: i18n/en.h:147 +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "No/mal giro" +msgstr "Not/mala rotacion" + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[off]" + +#: i18n/en.h:3 +msgid "[on]" +msgstr "[on]" -#: i18n/en.h:151 +#: i18n/en.h:43 +msgid "once" +msgstr "una vez" + +#: i18n/en.h:127 msgid "Open the cover" -msgstr "Abre la tapa" +msgstr "Abrir la cubierta" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" -msgstr "Sobrecalent." +msgstr "Sobrecalentamiento" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" -msgstr "Pausar" +msgstr "Pausa" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" -msgstr "Pausada" +msgstr "Pausado" -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Por favor reinicia" - -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" -msgstr "Presiona para cont." +msgstr "Pulse para cont." -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" -msgstr "Error lect. temp." +msgstr "Err. lectura temp." -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "Reiniciar todo?" + +#: i18n/en.h:93 msgid "Remove IPA tank" -msgstr "Retira tanq. IPA" +msgstr "Retirar tanque IPA" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" -msgstr "Precalent. Resina" +msgstr "Precal. resina" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." -msgstr "Temp. precal. res." +msgstr "T. precal. resina" -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" -msgstr "Tiempo precal. res." +msgstr "T. precal. resina" -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Vel. rotacion" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Ajustes rotacion" -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" msgstr "Test rotacion" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" -msgstr "Modo de uso" +msgstr "Modo de func." -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" -msgstr "Tiempo de uso" +msgstr "Tiempo func." -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Selftest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Ajustes" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" msgstr "Sonido" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" -msgstr "Rotacion apagada" +msgstr "Giro apagado" -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Parar" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "Unidad de temp." - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Temperaturas" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Unidad temp." + +#: i18n/en.h:104 msgid "UVLED failure" -msgstr "Fallo LED UV" +msgstr "Fallo UVLED" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "Intensidad LED UV" +msgstr "Intensidad UVLED" -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "Temp. LED UV:" - -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" -msgstr "Test LED UV" +msgstr "Test UVLED" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" -msgstr "Precalent." +msgstr "Calentamiento" -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Ciclos lavado" + +#: i18n/en.h:72 msgid "Washing" msgstr "Lavado" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" msgstr "Tiempo lavado" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Vel. lavado" - -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Area sucia" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[off]" - -#: i18n/en.h:3 -msgid "[on]" -msgstr "[on]" - -#: i18n/en.h:40 -msgid "continuous" -msgstr "continuo" +msgstr "Velocidad lavado" -#: i18n/en.h:38 -msgid "none" -msgstr "ninguno" -#: i18n/en.h:39 -msgid "once" -msgstr "una vez" diff --git a/i18n/fr.po b/i18n/fr.po index cd9c111..44fb64b 100644 --- a/i18n/fr.po +++ b/i18n/fr.po @@ -5,355 +5,306 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " F2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"X-Generator: Prusalator\n" #: i18n/en.h:2 msgid "Back" msgstr "Retour" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " -msgstr "Build: " - -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Temp. chambre:" +msgstr "Version: " -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" msgstr "Fermez le capot" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" msgstr "Continuer" -#: i18n/en.h:37 +#: i18n/en.h:44 +msgid "continuous" +msgstr "continu" + +#: i18n/en.h:41 msgid "Control echo" msgstr "Echo controle" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" msgstr "Refroidissement" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" msgstr "Test capot" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" msgstr "Durcissement" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" -msgstr "Tps de durcissement" +msgstr "Temps durcis." -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Vitesse durcissement" +msgstr "Vitesse durcis." -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" msgstr "Sechage" -#: i18n/en.h:17 +#: i18n/en.h:60 +msgid "Drying/curing" +msgstr "Sechage/durciss." + +#: i18n/en.h:18 msgid "Drying run-time" msgstr "Temps de sechage" -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "Temp. prech. sech." +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "T. sechage/chauffe" -#: i18n/en.h:79 -msgid "Drying/curing" -msgstr "Sechage/durcissement" +#: i18n/en.h:117 +msgid "F1: " +msgstr "F1 :" -#: i18n/en.h:141 -msgid "F1:" -msgstr "F1:" +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2 :" -#: i18n/en.h:143 +#: i18n/en.h:119 msgid "F3:" msgstr "F3:" -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " - -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "RPM Ventilateur1: " - -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Vit. durcis. vent.1" - -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Vit. sech. ventil.1" +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Réinit. usine" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" -msgstr "Echec ventilateur1" +msgstr "Panne Vent.1" -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Menu vit. vent.1" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Vit. nettoy. vent.1" - -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "RPM ventilateur2: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Vit. durcis. vent.2" - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Vit. sech. vent.2" - -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" -msgstr "Echec ventilateur2" - -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Menu vit. vent.2" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Vit. nettoy. vent.2" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "RPM ventilateur3: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Ventilateurs" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Vit. durcis. vent." - -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Vit. sech. ventil." - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Menu vit. vent." +msgstr "Panne Vent.2" -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Test ventilateurs" +msgstr "Test de vent." -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Vit. nettoy. vent." +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Temps de filtrage" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Vit. de filtrage" + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Signal de fin" +msgstr "Bip de fin" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" -msgstr "Termine" +msgstr "Terminé" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW:" + +#: i18n/en.h:113 msgid "Heater failure" -msgstr "Echec chauffe" +msgstr "Panne chauffage" -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" -msgstr "Erreur vent. chauf." +msgstr "Err. vent. chauff." -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" -msgstr "Test chauffe" +msgstr "Test chauffage" -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" msgstr "Chauffe" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" -msgstr "Tenez la plateforme" +msgstr "Bloquer plateforme" -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "Test reservoir IPA" +#: i18n/en.h:129 +msgid "Incorrect firmware!" +msgstr "Mauvais firmware" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" -msgstr "Information" +msgstr "Informations" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" -msgstr "Inserer reserv. IPA" +msgstr "Ins. reserv IPA" + +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "Filtrage de l'IPA" -#: i18n/en.h:83 +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "Test du reserv IPA" + +#: i18n/en.h:64 msgid "LCD brightness" msgstr "Luminosite LCD" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr "min." + +#: i18n/en.h:115 msgid "No/low power" -msgstr "Pas/peu d'alim." +msgstr "Pas/faible pwr." -#: i18n/en.h:147 +#: i18n/en.h:42 +msgid "none" +msgstr "aucun" + +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "Ne tourne pas ou mal" +msgstr "Pas de/mauv. rot." + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[off]" + +#: i18n/en.h:3 +msgid "[on]" +msgstr "[on]" -#: i18n/en.h:151 +#: i18n/en.h:43 +msgid "once" +msgstr "une fois" + +#: i18n/en.h:127 msgid "Open the cover" msgstr "Ouvrez le capot" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" -msgstr "Surchauffe" +msgstr "Surchauffer" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" msgstr "Pause" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" msgstr "En pause" -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Veuillez redemarrer" - -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" -msgstr "Appuyer = continuer" +msgstr "App. pour cont." -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" -msgstr "Erreur lect. temp." +msgstr "Err. lecture temp." -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "Reinitialiser ?" + +#: i18n/en.h:93 msgid "Remove IPA tank" -msgstr "Retirez reserv. IPA" +msgstr "Retirez res. IPA" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" msgstr "Prechauf. resine" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." -msgstr "Temp. prech. resine." +msgstr "Tps de prech. res." -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" -msgstr "Tps de prech. resine" +msgstr "Tps de prech. res." -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Vitesse de rotation" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Reg. de rotation" -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" msgstr "Test de rotation" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" -msgstr "Mode utilisation" +msgstr "Mode de fonct." -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" msgstr "Duree" -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Selftest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Reglages" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" msgstr "Son" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" msgstr "Rotation desactivee" -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Stop" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "Unites temperature" - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Temperatures" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Unite de temp." + +#: i18n/en.h:104 msgid "UVLED failure" -msgstr "Echec UVLED" +msgstr "Panne LEDUV" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "Intensite UVLED" - -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "Temp. UVLED:" +msgstr "Intensite LEDUV" -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" -msgstr "Test UVLED" +msgstr "Test LEDUV" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" msgstr "Prechauffage" -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Cycles de lavage" + +#: i18n/en.h:72 msgid "Washing" -msgstr "Nettoyage" +msgstr "Lavage" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" -msgstr "Temps de nettoyage" +msgstr "Temps de lavage" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Vitesse de nettoyage" - -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Zone de travail sale" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[off]" +msgstr "Vitesse de lavage" -#: i18n/en.h:3 -msgid "[on]" -msgstr "[on]" -#: i18n/en.h:40 -msgid "continuous" -msgstr "continu" - -#: i18n/en.h:38 -msgid "none" -msgstr "aucun" - -#: i18n/en.h:39 -msgid "once" -msgstr "une fois" diff --git a/i18n/it.po b/i18n/it.po index 92c19fd..6bcbac1 100644 --- a/i18n/it.po +++ b/i18n/it.po @@ -5,359 +5,306 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " F2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"X-Generator: Prusalator\n" #: i18n/en.h:2 msgid "Back" msgstr "Indietro" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " msgstr "Build: " -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Temp. alloggio:" - -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" -msgstr "Chiudi il coperch." +msgstr "Chiudi coperchio" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" msgstr "Continua" -#: i18n/en.h:37 +#: i18n/en.h:44 +msgid "continuous" +msgstr "continuo" + +#: i18n/en.h:41 msgid "Control echo" msgstr "Controllo Eco" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" msgstr "Raffreddamento" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" msgstr "Test coperchio" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" msgstr "Indurimento" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" msgstr "Durata indurimento" -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Vel. indurimento" +msgstr "Veloc. indurimento" -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" msgstr "Asciugatura" -#: i18n/en.h:17 -msgid "Drying run-time" -msgstr "Durata asciugatura" +#: i18n/en.h:60 +msgid "Drying/curing" +msgstr "Asciug./indurim." -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "T. riscal. asciug" +#: i18n/en.h:18 +msgid "Drying run-time" +msgstr "Dur. asciugamento" -#: i18n/en.h:79 -msgid "Drying/curing" -msgstr "Asciugat./Indurim." +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "Tmp. Asciug./Risc." -#: i18n/en.h:141 +#: i18n/en.h:117 msgid "F1:" msgstr "F1:" -#: i18n/en.h:143 +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2:" + +#: i18n/en.h:119 msgid "F3:" msgstr "F3:" -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " - -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "RPM Ventola1: " - -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Vel. indur. Vent1" - -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Vel. asciug. Vent1" +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Ripr. fabbrica" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" -msgstr "Guasto Ventola1" - -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Menu vel. ventola1" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Vel. lavagg. Vent1" - -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "RPM Ventola2: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Vel. indur. Vent2" - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Vel. asciug. Vent2" +msgstr "Guasto Vent1" -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" -msgstr "Guasto Ventola2" - -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Menu vel. ventola2" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Vel. lavagg. Vent2" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "RPM Vent3: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Ventole" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Vel. indur. Vent" +msgstr "Guasto Vent2" -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Vel asciug Vent.le" - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Menu vel. ventole" - -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Test ventole" +msgstr "Test Ventole" -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Vel. vent. lavagg." +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Dur. filtraggio" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Vel. di filtraggio" + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Suono finale" +msgstr "Bip finale" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" msgstr "Completato" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW: " + +#: i18n/en.h:113 msgid "Heater failure" -msgstr "Guasto Riscald." +msgstr "Guasto riscald." -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" -msgstr "Err. vent. riscald" +msgstr "Err. vent. risc." -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" -msgstr "Test riscaldam." +msgstr "Test riscald." -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" msgstr "Riscaldamento" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" -msgstr "Tieni la piattaf." - -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "Test serb. IPA" +msgstr "Tieni piattaforma" -#: i18n/en.h:153 +#: i18n/en.h:129 msgid "Incorrect firmware!" -msgstr "Firmware incorretto!" +msgstr "Firmware errato!" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" msgstr "Informazioni" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" -msgstr "Inserire serb. IPA" +msgstr "Inser. serbatoio IPA." + +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "Filtraggio IPA" + +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "Test serbatoio IPA" -#: i18n/en.h:83 +#: i18n/en.h:64 msgid "LCD brightness" msgstr "Luminosita LCD" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr "min." + +#: i18n/en.h:115 msgid "No/low power" -msgstr "No/poca energia" +msgstr "Nessuna/bassa pot." + +#: i18n/en.h:42 +msgid "none" +msgstr "nessuno" -#: i18n/en.h:147 +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "No/scarsa rotazione" +msgstr "Non gira/Gira male" + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[off]" + +#: i18n/en.h:3 +msgid "[on]" +msgstr "[on]" + +#: i18n/en.h:43 +msgid "once" +msgstr "singolo" -#: i18n/en.h:151 +#: i18n/en.h:127 msgid "Open the cover" msgstr "Apri il coperchio" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" msgstr "Surriscaldamento" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" msgstr "Pausa" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" -msgstr "In pausa" - -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Riavviare" +msgstr "in pausa" -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" -msgstr "Premi per contin." +msgstr "Premi per cont." -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" msgstr "Err. lettura temp." -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "Vuoi reset. tutto?" + +#: i18n/en.h:93 msgid "Remove IPA tank" msgstr "Rimuovi serb. IPA" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" -msgstr "Preriscalda resina" +msgstr "Riscald. resina" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." -msgstr "T. prerisc. resina" +msgstr "Tmpr. risc. resina" -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" -msgstr "D. prerisc. resina" +msgstr "Tempo risc. resina" -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Vel. di rotazione" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Impostaz. rotaz." -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" msgstr "Test rotazione" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" msgstr "Mod. funzionamento" -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" msgstr "Durata" -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Autotest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Impostazioni" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" msgstr "Suono" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" -msgstr "Rotazione spenta" +msgstr "Rot. disattivata" -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Stop" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "Unita temperatura" - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Temperature" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Unita temp." + +#: i18n/en.h:104 msgid "UVLED failure" -msgstr "Guasto UVLED" +msgstr "guasto LEDUV" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "Intensita UVLED" - -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "Temp. UVLED:" +msgstr "Intensita LEDUV" -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" -msgstr "Test UVLED" +msgstr "test LEDUV" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" -msgstr "Riscalda" +msgstr "Riscaldamento" -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Cicli lavaggio" + +#: i18n/en.h:72 msgid "Washing" msgstr "Lavaggio" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" msgstr "Durata lavaggio" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Vel. lavaggio" +msgstr "Velocita lavaggio" -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Area sporca" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[off]" -#: i18n/en.h:3 -msgid "[on]" -msgstr "[on]" - -#: i18n/en.h:40 -msgid "continuous" -msgstr "continuo" - -#: i18n/en.h:38 -msgid "none" -msgstr "nessuno" - -#: i18n/en.h:39 -msgid "once" -msgstr "una volta" diff --git a/i18n/pl.po b/i18n/pl.po index 1728eb3..f950551 100644 --- a/i18n/pl.po +++ b/i18n/pl.po @@ -4,362 +4,307 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n" -"%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || n%10 == 1 || (n%10 >= 5 && n" -"%10 <=9)) || (n%100 >= 12 && n%100 <= 14)) ? 2 : 3);\n" - -#: i18n/en.h:142 -msgid " F2:" -msgstr " W2:" - -#: i18n/en.h:9 -msgid " min." -msgstr " min." +"Plural-Forms: nplurals=4; plural=(n == 1) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || n%10 == 1 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 12 && n%100 <= 14)) ? 2 : 3);\n" +"X-Generator: Prusalator\n" #: i18n/en.h:2 msgid "Back" msgstr "Wstecz" -#: i18n/en.h:70 +#: i18n/en.h:51 msgid "Build: " msgstr "Build: " -#: i18n/en.h:98 -msgid "Cham. temp.:" -msgstr "Temp. wewn.:" - -#: i18n/en.h:115 +#: i18n/en.h:92 msgid "Close the cover" msgstr "Zamknij pokrywe" -#: i18n/en.h:87 +#: i18n/en.h:68 msgid "Continue" msgstr "Kontynuuj" -#: i18n/en.h:37 +#: i18n/en.h:44 +msgid "continuous" +msgstr "ciagle" + +#: i18n/en.h:41 msgid "Control echo" -msgstr "Inf. zwr. pokretla" +msgstr "Ust. dzwieku" -#: i18n/en.h:102 +#: i18n/en.h:77 msgid "Cooldown" msgstr "Chlodzenie" -#: i18n/en.h:150 +#: i18n/en.h:126 msgid "Cover test" msgstr "Test pokrywy" -#: i18n/en.h:80 +#: i18n/en.h:61 msgid "Curing" msgstr "Utwardzanie" -#: i18n/en.h:16 +#: i18n/en.h:17 msgid "Curing run-time" msgstr "Czas utwardzania" -#: i18n/en.h:23 +#: i18n/en.h:25 msgid "Curing speed" -msgstr "Predk. utwardzania" +msgstr "Szyb. utwardzania" -#: i18n/en.h:81 +#: i18n/en.h:62 msgid "Drying" msgstr "Suszenie" -#: i18n/en.h:17 -msgid "Drying run-time" -msgstr "Czas suszenia" - -#: i18n/en.h:29 -msgid "Drying warm-up t." -msgstr "Temp. suszenia" - -#: i18n/en.h:79 +#: i18n/en.h:60 msgid "Drying/curing" msgstr "Suszenie/utwardz." -#: i18n/en.h:141 -msgid "F1:" -msgstr "W1:" +#: i18n/en.h:18 +msgid "Drying run-time" +msgstr "Czas suszenia" -#: i18n/en.h:143 -msgid "F3:" -msgstr "W3:" +#: i18n/en.h:33 +msgid "Drying/Warm-up t." +msgstr "Temp. Susz./Nagrz." -#: i18n/en.h:68 -msgid "FW: " -msgstr "FW: " +#: i18n/en.h:117 +msgid "F1:" +msgstr "F1:" -#: i18n/en.h:95 -msgid "Fan1 RPM: " -msgstr "Obroty w1: " +#: i18n/en.h:118 +msgid " F2:" +msgstr " F2:" -#: i18n/en.h:45 -msgid "Fan1 curing speed" -msgstr "Predk. utw. went 1" +#: i18n/en.h:119 +msgid "F3:" +msgstr "F3:" -#: i18n/en.h:50 -msgid "Fan1 drying speed" -msgstr "Predk. susz. went1" +#: i18n/en.h:79 +msgid "Factory reset" +msgstr "Ustaw. fabryczne" -#: i18n/en.h:144 +#: i18n/en.h:120 msgid "Fan1 failure" -msgstr "Blad wentylatora 1" - -#: i18n/en.h:60 -msgid "Fan1 menu speed" -msgstr "Pr. jalowa went. 1" - -#: i18n/en.h:55 -msgid "Fan1 washing speed" -msgstr "Predk. myc. went 1" +msgstr "Blad went.1" -#: i18n/en.h:96 -msgid "Fan2 RPM: " -msgstr "Obroty w2: " - -#: i18n/en.h:46 -msgid "Fan2 curing speed" -msgstr "Predk. utw. went 2" - -#: i18n/en.h:51 -msgid "Fan2 drying speed" -msgstr "Predk. susz. went2" - -#: i18n/en.h:145 +#: i18n/en.h:121 msgid "Fan2 failure" -msgstr "Blad wentylatora 2" - -#: i18n/en.h:61 -msgid "Fan2 menu speed" -msgstr "Pr. jalowa went. 2" - -#: i18n/en.h:56 -msgid "Fan2 washing speed" -msgstr "Predk. myc. went 2" - -#: i18n/en.h:97 -msgid "Fan3 RPM: " -msgstr "Obroty w3: " - -#: i18n/en.h:64 -msgid "Fans" -msgstr "Wentylatory" - -#: i18n/en.h:44 -msgid "Fans curing speed" -msgstr "Predk. went. utw." - -#: i18n/en.h:49 -msgid "Fans drying speed" -msgstr "Predk. went. susz." - -#: i18n/en.h:59 -msgid "Fans menu speed" -msgstr "Pr. jalowa went." +msgstr "Blad went.2" -#: i18n/en.h:140 +#: i18n/en.h:116 msgid "Fans test" -msgstr "Test wentylatorow" +msgstr "Test went." -#: i18n/en.h:54 -msgid "Fans washing speed" -msgstr "Predk. went. myc." +#: i18n/en.h:21 +msgid "Filtering run-time" +msgstr "Czas filtrowania" -#: i18n/en.h:41 +#: i18n/en.h:28 +msgid "Filtering speed" +msgstr "Szyb. filtrowania" + +#: i18n/en.h:45 msgid "Finish beep" -msgstr "Powiadom. o zakon." +msgstr "Dzwiek na koniec" -#: i18n/en.h:121 +#: i18n/en.h:97 msgid "Finished" msgstr "Zakonczono" -#: i18n/en.h:137 +#: i18n/en.h:49 +msgid "FW: " +msgstr "FW: " + +#: i18n/en.h:113 msgid "Heater failure" msgstr "Blad grzalki" -#: i18n/en.h:117 +#: i18n/en.h:94 msgid "Heater fan error" msgstr "Blad went. grzalki" -#: i18n/en.h:136 +#: i18n/en.h:112 msgid "Heater test" msgstr "Test grzalki" -#: i18n/en.h:125 +#: i18n/en.h:101 msgid "Heating" -msgstr "Podgrzewanie" +msgstr "Nagrzewanie" -#: i18n/en.h:152 +#: i18n/en.h:128 msgid "Hold the platform" -msgstr "Trzymaj platforme" +msgstr "Przytrzymaj platf." -#: i18n/en.h:149 -msgid "IPA tank test" -msgstr "Test zbiornika IPA" - -#: i18n/en.h:153 +#: i18n/en.h:129 msgid "Incorrect firmware!" -msgstr "Bledne firmware!" +msgstr "Niewlasciwe FW!" -#: i18n/en.h:67 +#: i18n/en.h:48 msgid "Information" -msgstr "Informacja" +msgstr "Informacje" -#: i18n/en.h:133 +#: i18n/en.h:109 msgid "Insert IPA tank" -msgstr "Wsun zbiornik IPA" +msgstr "Wloz zbiornik IPA" + +#: i18n/en.h:73 +msgid "IPA Filtering" +msgstr "Filtrowanie IPA" -#: i18n/en.h:83 +#: i18n/en.h:125 +msgid "IPA tank test" +msgstr "Test zbiornika IPA" + +#: i18n/en.h:64 msgid "LCD brightness" msgstr "Jasnosc LCD" -#: i18n/en.h:139 +#: i18n/en.h:9 +msgid " min." +msgstr "min." + +#: i18n/en.h:115 msgid "No/low power" msgstr "Brak/niska moc" -#: i18n/en.h:147 +#: i18n/en.h:42 +msgid "none" +msgstr "brak" + +#: i18n/en.h:123 msgid "Not/bad spinning" -msgstr "Nie/nie obraca sie" +msgstr "Nie/blad obrotu" + +#: i18n/en.h:4 +msgid "[off]" +msgstr "[wyl.]" -#: i18n/en.h:151 +#: i18n/en.h:3 +msgid "[on]" +msgstr "[wl.]" + +#: i18n/en.h:43 +msgid "once" +msgstr "raz" + +#: i18n/en.h:127 msgid "Open the cover" msgstr "Otworz pokrywe" -#: i18n/en.h:130 +#: i18n/en.h:106 msgid "Overheat" msgstr "Przegrzanie" -#: i18n/en.h:86 +#: i18n/en.h:67 msgid "Pause" msgstr "Pauza" -#: i18n/en.h:114 +#: i18n/en.h:91 msgid "Paused" -msgstr "Wstrzymane" - -#: i18n/en.h:118 -msgid "Please restart" -msgstr "Zrestartuj" +msgstr "Pauza" -#: i18n/en.h:122 +#: i18n/en.h:98 msgid "Press to continue" -msgstr "Nacisnij, aby kont" +msgstr "Nacisnij aby kont." -#: i18n/en.h:129 +#: i18n/en.h:105 msgid "Read temper. error" msgstr "Blad odczytu temp." -#: i18n/en.h:116 +#: i18n/en.h:80 +msgid "Really reset all?" +msgstr "Zreset. wszystko?" + +#: i18n/en.h:93 msgid "Remove IPA tank" msgstr "Wyc. zbiornik IPA" -#: i18n/en.h:92 +#: i18n/en.h:74 msgid "Resin preheat" msgstr "Podgrzew. zywicy" -#: i18n/en.h:30 +#: i18n/en.h:34 msgid "Resin preheat t." -msgstr "Temp. podg. zywicy" +msgstr "Temp. podgrz. zyw." -#: i18n/en.h:19 +#: i18n/en.h:20 msgid "Resin preheat time" -msgstr "Czas podg. zywicy" +msgstr "Czas podgrz. zyw." -#: i18n/en.h:22 -msgid "Rotation speed" -msgstr "Predkosc obrotowa" +#: i18n/en.h:24 +msgid "Rotation settings" +msgstr "Ustawienia obrotu" -#: i18n/en.h:148 +#: i18n/en.h:124 msgid "Rotation test" -msgstr "Test obracania" +msgstr "Test obrotu" -#: i18n/en.h:78 +#: i18n/en.h:59 msgid "Run mode" msgstr "Tryb pracy" -#: i18n/en.h:15 +#: i18n/en.h:16 msgid "Run-time" msgstr "Czasy" -#: i18n/en.h:103 +#: i18n/en.h:78 msgid "Selftest" msgstr "Selftest" -#: i18n/en.h:77 +#: i18n/en.h:58 msgid "Settings" msgstr "Ustawienia" -#: i18n/en.h:36 +#: i18n/en.h:40 msgid "Sound" msgstr "Dzwiek" -#: i18n/en.h:146 +#: i18n/en.h:122 msgid "Spinning turned off" -msgstr "Obracanie wyl." +msgstr "Obracanie wylacz." -#: i18n/en.h:88 +#: i18n/en.h:69 msgid "Stop" msgstr "Stop" #: i18n/en.h:31 -msgid "Temp. units" -msgstr "Jednostki temp." - -#: i18n/en.h:27 msgid "Temperatures" msgstr "Temperatury" -#: i18n/en.h:128 +#: i18n/en.h:35 +msgid "Temp. units" +msgstr "Jednost. temp." + +#: i18n/en.h:104 msgid "UVLED failure" -msgstr "Blad UVLED" +msgstr "Blad UV LED" -#: i18n/en.h:82 +#: i18n/en.h:63 msgid "UVLED intensity" -msgstr "Intensywnosc UVLED" - -#: i18n/en.h:99 -msgid "UVLED temp.:" -msgstr "Temp. UVLED:" +msgstr "Intens. UV LED" -#: i18n/en.h:138 +#: i18n/en.h:114 msgid "UVLED test" -msgstr "Test UVLED" +msgstr "Test UV LED" -#: i18n/en.h:28 +#: i18n/en.h:32 msgid "Warm-up" -msgstr "Nagrzewanie" +msgstr "Nagrzew." -#: i18n/en.h:91 +#: i18n/en.h:27 +msgid "Wash cycles" +msgstr "Cykle mycia" + +#: i18n/en.h:72 msgid "Washing" msgstr "Mycie" -#: i18n/en.h:18 +#: i18n/en.h:19 msgid "Washing run-time" msgstr "Czas mycia" -#: i18n/en.h:24 +#: i18n/en.h:26 msgid "Washing speed" -msgstr "Predkosc mycia" - -#: i18n/en.h:73 -msgid "Workspace dirty" -msgstr "Wykr. zm. w kodzie" - -#: i18n/en.h:4 -msgid "[off]" -msgstr "[wyl]" - -#: i18n/en.h:3 -msgid "[on]" -msgstr "[wl]" - -#: i18n/en.h:40 -msgid "continuous" -msgstr "ciagle" +msgstr "Szybkosc mycia" -#: i18n/en.h:38 -msgid "none" -msgstr "brak" -#: i18n/en.h:39 -msgid "once" -msgstr "raz" diff --git a/lib/Countimer.cpp b/lib/Countimer.cpp index 44a0c01..4ad912b 100644 --- a/lib/Countimer.cpp +++ b/lib/Countimer.cpp @@ -20,13 +20,13 @@ void Countimer::setCounter(uint8_t hours, uint8_t minutes, uint8_t seconds, bool if (seconds > COUNTIMER_MAX_MINUTES_SECONDS) { seconds = COUNTIMER_MAX_MINUTES_SECONDS; } - _countUp = countUp; - setCounterInSeconds((hours * 3600L) + (minutes * 60L) + seconds); + setCounterInSeconds((hours * 3600L) + (minutes * 60L) + seconds, countUp); } -void Countimer::setCounterInSeconds(uint16_t seconds) { +void Countimer::setCounterInSeconds(uint16_t seconds, bool countUp) { _currentCountTime = seconds * 1000L; _countTime = _currentCountTime; + _countUp = countUp; if (_countUp) { // if is count up mode, we have to start from 00:00:00; @@ -77,7 +77,7 @@ void Countimer::stop() { _currentCountTime = _countTime; if (_countUp) { - _currentCountTime = 0; + _currentCountTime = 0; } } diff --git a/lib/Countimer.h b/lib/Countimer.h index 42d567f..92c5842 100644 --- a/lib/Countimer.h +++ b/lib/Countimer.h @@ -11,8 +11,8 @@ class Countimer { // Set up counter time(hours, minutes, seconds and type) for existing timer. void setCounter(uint8_t hours, uint8_t minutes, uint8_t seconds, bool countUp); - // Set up counter time in seconds for existing timer. - void setCounterInSeconds(uint16_t seconds); + // Set up counter time in seconds and type for existing timer. + void setCounterInSeconds(uint16_t seconds, bool countUp); // Returns timer's current hours. uint8_t getCurrentHours(); @@ -54,7 +54,7 @@ class Countimer { private: // Counting up timer. void countDown(); - + // Counting down timer. void countUp(); diff --git a/lib/USBCore.cpp b/lib/USBCore.cpp index ea13e57..c82ecdb 100644 --- a/lib/USBCore.cpp +++ b/lib/USBCore.cpp @@ -2,19 +2,19 @@ /* Copyright (c) 2010, Peter Barrett ** Sleep/Wakeup support added by Michael Dreher -** -** Permission to use, copy, modify, and/or distribute this software for -** any purpose with or without fee is hereby granted, provided that the -** above copyright notice and this permission notice appear in all copies. -** -** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL -** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED -** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR -** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES -** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -** SOFTWARE. +** +** Permission to use, copy, modify, and/or distribute this software for +** any purpose with or without fee is hereby granted, provided that the +** above copyright notice and this permission notice appear in all copies. +** +** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL +** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED +** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR +** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES +** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +** SOFTWARE. */ #include "USBAPI.h" @@ -113,9 +113,9 @@ static inline void Recv(volatile u8* data, u8 count) { while (count--) *data++ = UEDATX; - + RXLED1; // light the RX LED - RxLEDPulse = TX_RX_LED_PULSE_MS; + RxLEDPulse = TX_RX_LED_PULSE_MS; } static inline u8 Recv8() @@ -123,7 +123,7 @@ static inline u8 Recv8() RXLED1; // light the RX LED RxLEDPulse = TX_RX_LED_PULSE_MS; - return UEDATX; + return UEDATX; } static inline void Send8(u8 d) @@ -223,7 +223,7 @@ int USB_Recv(u8 ep, void* d, int len) { if (!_usbConfiguration || len < 0) return -1; - + LockEP lock(ep); u8 n = FifoByteCount(); len = min(n,len); @@ -233,7 +233,7 @@ int USB_Recv(u8 ep, void* d, int len) *dst++ = Recv8(); if (len && !FifoByteCount()) // release empty buffer ReleaseRX(); - + return len; } @@ -329,7 +329,7 @@ int USB_Send(u8 ep, const void* d, int len) u8 _initEndpoints[USB_ENDPOINTS] = { 0, // Control Endpoint - + EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN @@ -497,14 +497,13 @@ bool SendConfiguration(int maxlen) static bool SendDescriptor(USBSetup& setup) { - int ret; u8 t = setup.wValueH; if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t) return SendConfiguration(setup.wLength); InitControl(setup.wLength); #ifdef PLUGGABLE_USB_ENABLED - ret = PluggableUSB().getDescriptor(setup); + int ret = PluggableUSB().getDescriptor(setup); if (ret != 0) { return (ret > 0 ? true : false); } @@ -757,7 +756,7 @@ ISR(USB_GEN_vect) if (udint & (1<(magic), MAGIC_SIZE); - EEPROM.put(EEPROM_BASE + MAGIC_SIZE, reinterpret_cast(&config), sizeof(config)); + EEPROM.put(CONFIG_START, reinterpret_cast(magic), MAGIC_SIZE); + EEPROM.put(CONFIG_START + MAGIC_SIZE, reinterpret_cast(&config), sizeof(config)); } /*! \brief This function loads user-defined values from eeprom. @@ -63,22 +56,26 @@ void write_config() { */ void read_config() { char test_magic[MAGIC_SIZE]; - EEPROM.get(EEPROM_BASE, reinterpret_cast(test_magic), MAGIC_SIZE); + EEPROM.get(CONFIG_START, reinterpret_cast(test_magic), MAGIC_SIZE); if (!strncmp_P(test_magic, config_magic, MAGIC_SIZE)) { // latest magic - EEPROM.get(EEPROM_BASE + MAGIC_SIZE, reinterpret_cast(&config), sizeof(config)); + EEPROM.get(CONFIG_START + MAGIC_SIZE, reinterpret_cast(&config), sizeof(config)); + } else if (!strncmp_P(test_magic, legacy_magic3, MAGIC_SIZE)) { + // legacy magic + EEPROM.get(CONFIG_START + MAGIC_SIZE, reinterpret_cast(&config), sizeof(eeprom_v3_t)); + } else if (!strncmp_P(test_magic, legacy_magic2, MAGIC_SIZE)) { + // legacy magic + EEPROM.get(CONFIG_START + MAGIC_SIZE, reinterpret_cast(&config), sizeof(eeprom_v2_t) - 9); + EEPROM.get(CONFIG_START + MAGIC_SIZE + sizeof(eeprom_v2_t) - 1, reinterpret_cast(&config.lcd_brightness), 1); } else if (!strncmp_P(test_magic, legacy_magic1, MAGIC_SIZE)) { // legacy magic uint8_t tmp = config.resin_target_temp; // remember default - EEPROM.get(EEPROM_BASE + MAGIC_SIZE, reinterpret_cast(&config), sizeof(eeprom_v1_t)); + EEPROM.get(CONFIG_START + MAGIC_SIZE, reinterpret_cast(&config), sizeof(eeprom_v1_t)); if (config.SI_unit_system) { config.resin_target_temp = tmp; } else { - config.target_temp = round(celsius2fahrenheit(config.target_temp)); - config.resin_target_temp = round(celsius2fahrenheit(tmp)); + config.target_temp = round_short(celsius2fahrenheit(config.target_temp)); + config.resin_target_temp = round_short(celsius2fahrenheit(tmp)); } } - #ifdef CW1S - config.fans_menu_speed[0] = 0; - #endif } diff --git a/src/config.h b/src/config.h index b6a4485..4bcf01f 100644 --- a/src/config.h +++ b/src/config.h @@ -2,6 +2,9 @@ #include +#define EEPROM_OFFSET 128 +#define CONFIG_START E2END + 1 - EEPROM_OFFSET + //! @brief legacy configuration store structure //! //! It is restored when magic read from eeprom equals magic "CURWA". @@ -22,12 +25,10 @@ typedef struct { // bool heater_failure; this is not used any more and may be forgotten } eeprom_v1_t; -//! @brief configuration store structure +//! @brief legacy configuration store structure //! //! It is restored when magic read from eeprom equals magic "CW1v2" -//! Do not change. If new items needs to be stored, magic needs to be -//! changed, this struct needs to be made legacy and new structure needs -//! to be created. +//! Do not change. typedef struct { uint8_t washing_speed; uint8_t curing_speed; @@ -41,7 +42,6 @@ typedef struct { uint8_t target_temp; uint8_t resin_target_temp; // v1 change! uint8_t SI_unit_system; - uint8_t resin_preheat_run_time; uint8_t led_intensity; uint8_t fans_menu_speed[2]; @@ -51,7 +51,57 @@ typedef struct { uint8_t lcd_brightness; } eeprom_v2_t; -extern eeprom_v2_t config; +//! @brief configuration store structure +//! +//! It is restored when magic read from eeprom equals magic "CW1v3" +//! Do not change. +typedef struct { + uint8_t washing_speed; + uint8_t curing_speed; + uint8_t washing_run_time; + uint8_t curing_run_time; + uint8_t finish_beep_mode; + uint8_t drying_run_time; + uint8_t sound_response; + uint8_t curing_machine_mode; + uint8_t heat_to_target_temp; + uint8_t target_temp; + uint8_t resin_target_temp; + uint8_t SI_unit_system; + uint8_t resin_preheat_run_time; + uint8_t led_intensity; + uint8_t lcd_brightness; + uint8_t wash_cycles; +} eeprom_v3_t; + +//! @brief configuration store structure +//! +//! It is restored when magic read from eeprom equals magic "CW1v4" +//! Do not change. If new items needs to be stored, magic needs to be +//! changed, this struct needs to be made legacy and new structure needs +//! to be created. +typedef struct { + uint8_t washing_speed; + uint8_t curing_speed; + uint8_t washing_run_time; + uint8_t curing_run_time; + uint8_t finish_beep_mode; + uint8_t drying_run_time; + uint8_t sound_response; + uint8_t curing_machine_mode; + uint8_t heat_to_target_temp; + uint8_t target_temp; + uint8_t resin_target_temp; + uint8_t SI_unit_system; + uint8_t resin_preheat_run_time; + uint8_t led_intensity; + uint8_t lcd_brightness; + uint8_t wash_cycles; + uint8_t filtering_speed; + uint8_t filtering_run_time; +} eeprom_v4_t; + +extern eeprom_v4_t config; void read_config(); void write_config(); diff --git a/src/defines.h b/src/defines.h index 04ff09a..d398c12 100644 --- a/src/defines.h +++ b/src/defines.h @@ -15,9 +15,9 @@ #define DISPLAY_CHARS 20 #define DISPLAY_LINES 4 -#define LAYOUT_TIME_X 3 +#define LAYOUT_TIME_X 2 #define LAYOUT_TIME_Y 2 -#define LAYOUT_TIME_LT 1 +#define LAYOUT_TIME_LT 0 #define LAYOUT_TIME_GT 8 #define LAYOUT_INFO1_X 12 #define LAYOUT_INFO1_Y 2 @@ -35,44 +35,34 @@ #define FAN3_ERROR_MASK B100 // various constants -#define LED_DELAY 2000 -#define LONG_PRESS_TIME 1000 -#define P 10 // 0.5 -#define I 0.001 +#define LED_DELAY 2000 // microseconds +#define LONG_PRESS_TIME 1000 // microseconds #define MIN_TARGET_TEMP_C 20 -#ifdef CW1S - #define MAX_TARGET_TEMP_C 60 - #define HEATING_ON_FAN1_DUTY 100 - #define CHAMBER_TEMP_THR_FAN1_ON 35 - #define CHAMBER_TEMP_THR_FAN1_DUTY 40 -#else - #define MAX_TARGET_TEMP_C 40 -#endif +#define MAX_TARGET_TEMP_C 60 #define MIN_TARGET_TEMP_F MIN_TARGET_TEMP_C * 1.8 + 32 #define MAX_TARGET_TEMP_F MAX_TARGET_TEMP_C * 1.8 + 32 #define MAX_WARMUP_RUNTIME 15 // minutes -#define MAX_CURING_RUNTIME 60 // minutes -#define MAX_DRYING_RUNTIME 60 // minutes -#define MAX_WASHING_RUNTIME 10 // minutes -#define MAX_PREHEAT_RUNTIME 30 // minutes +#define MAX_CURING_RUNTIME 255 // minutes +#define MAX_DRYING_RUNTIME 255 // minutes +#define MAX_WASHING_RUNTIME 255 // minutes +#define MAX_PREHEAT_RUNTIME 255 // minutes +#define MAX_FILTER_RUNTIME 255 // minutes #define COOLDOWN_RUNTIME 10 // minutes #define INC_DEC_TIME_STEP 30 // seconds #define MIN_LED_INTENSITY 1 // 0-100 % #define MIN_LCD_BRIGHTNESS 5 // 0-100 % #define MIN_FAN_SPEED 30 // 0-100 % -#define FAN_CHECK_PERIOD 500 // microseconds #define SWITCH_TEST_COUNT 10 #define ROTATION_TEST_TIME 3 // minutes #define FANS_TEST_TIME 2 // minutes -#define UVLED_TEST_TIME 10 // minutes -#define UVLED_TEST_GAIN 10.0 // celsius -#define UVLED_MAX_TEMP 70.0 // celsius -#define HEATER_TEST_TIME 10 // minutes -#define HEATER_TEST_GAIN 5.0 // celsius -#define HEATER_CHECK_DELAY 2000 // microseconds -#define SN_LENGTH 15 +#define UVLED_TEST_MAX_TIME 10 // minutes +#define UVLED_MAX_TEMP 70 // celsius +#define OPTIMAL_TEMP 35.0 // celsius +#define TEST_TEMP 50 // celsius +#define HEATER_CHECK_DELAY 2500 // microseconds +#define SN_ADDRESS 0x7fe0 +#define SN_LENGTH 16 #define MAX_MENU_DEPTH 5 -#define MENU_REDRAW_US 1000 #define ADC_OVRSAMPL 4 // motor speeds (smaller is faster) #define FAST_SPEED_START 200 @@ -80,6 +70,7 @@ #define MAX_FAST_SPEED 16 #define MIN_SLOW_SPEED 220 #define MAX_SLOW_SPEED 25 +#define DIR_CHANGE_DELAY 2 // seconds #define MCP_A0 1 // pin 21 #define MCP_A1 2 // pin 22 diff --git a/src/device.h b/src/device.h new file mode 100644 index 0000000..a6348c3 --- /dev/null +++ b/src/device.h @@ -0,0 +1,10 @@ +#pragma once + +#ifdef CW1_HW +#include "cw1.h" +#endif + +#ifdef CW1S_HW +#include "cw1s.h" +#define HEATING_ON_FAN1_SPEED 100 +#endif diff --git a/src/hardware.cpp b/src/hardware.cpp index 93a06d6..88202c3 100644 --- a/src/hardware.cpp +++ b/src/hardware.cpp @@ -12,6 +12,15 @@ float fahrenheit2celsius(float fahrenheit) { return (fahrenheit - 32) / 1.8; } +uint8_t round_short(float temp) { + return (uint8_t)round(temp); +} + +float get_configured_temp(float temp) { + return config.SI_unit_system ? temp : celsius2fahrenheit(temp); +} + + const int16_t chamber_temp_table_raw[34] PROGMEM = { 25, 29, 34, 40, 46, 54, 64, 75, 88, 105, 124, 146, 173, 204, 241, 282, 330, 382, 439, 500, 563, 625, 687, 744, 796, 842, 882, 915, 941, 963, 979, 992, 1001, 1008 @@ -23,47 +32,36 @@ const int16_t uvled_temp_table_raw[34] PROGMEM = { }; -uint16_t Hardware::fan_rpm[3] = {1, 1, 1}; -volatile uint8_t Hardware::fan_tacho_count[3] = {0, 0, 0}; -volatile uint8_t Hardware::microstep_control(FAST_SPEED_START); -float Hardware::chamber_temp_celsius(-40.0); -float Hardware::chamber_temp(-40.0); -float Hardware::uvled_temp_celsius(-40.0); -float Hardware::uvled_temp(-40.0); -bool Hardware::heater_error(false); -#ifdef CW1S - bool Hardware::wanted_heater_pin_state(false); - bool Hardware::slow_pwm_on(false); -#endif -MCP Hardware::outputchip(0, 8); -Trinamic_TMC2130 Hardware::myStepper(CS_PIN); -uint8_t Hardware::lcd_encoder_bits(0); -volatile int8_t Hardware::rotary_diff(0); -uint8_t Hardware::target_accel_period(FAST_SPEED_START); -uint8_t Hardware::fan_duty[2] = {0, 0}; -uint8_t Hardware::fan_pwm_pins[2] = {FAN1_PWM_PIN, FAN2_PWM_PIN}; -uint8_t Hardware::fan_enable_pins[2] = {FAN1_PIN, FAN2_PIN}; -uint8_t Hardware::fans_target_temp(0); -unsigned long Hardware::accel_us_last(0); -unsigned long Hardware::fans_us_last(0); -unsigned long Hardware::adc_us_last(0); -unsigned long Hardware::heater_us_last(0); -unsigned long Hardware::button_timer(0); -double Hardware::PI_summ_err(0.0); -bool Hardware::do_acceleration(false); -bool Hardware::cover_closed(false); -bool Hardware::tank_inserted(false); -bool Hardware::button_active(false); -bool Hardware::long_press_active(false); -bool Hardware::adc_channel(false); -#ifdef CW1S - bool Hardware::heater_on(false); - bool Hardware::heater_pin_state(false); - uint16_t Hardware::heater_pwm_duty(0); -#endif - - -Hardware::Hardware() { +Hardware::Hardware(uint16_t model_magic) +: + model_magic(model_magic), + fan_rpm{0, 0, 0}, + fan_tacho_count{0, 0, 0}, + microstep_control(FAST_SPEED_START), + chamber_temp_celsius(0.0), + uvled_temp_celsius(0.0), + heater_error(false), + disable_controls(false), + outputchip(0, 8), + stepper(CS_PIN), + lcd_encoder_bits(0), + rotary_diff(0), + target_accel_period(FAST_SPEED_START), + fan_speed{0, 0}, + chamber_target_temp(0), + accel_ms_last(0), + one_second_ms_last(0), + heating_started_ms(0), + button_timer(0), + heating_in_progress(false), + do_acceleration(false), + cover_closed(false), + tank_inserted(false), + button_active(false), + long_press_active(false), + adc_channel(false), + fans_forced(false) +{ outputchip.begin(); outputchip.pinMode(0B0000000010010111); @@ -77,6 +75,8 @@ Hardware::Hardware() { pinMode(BEEPER, OUTPUT); // motor + pinMode(EN_PIN, OUTPUT); + pinMode(DIR_PIN, OUTPUT); pinMode(STEP_PIN, OUTPUT); // led @@ -94,13 +94,13 @@ Hardware::Hardware() { stop_heater(); // stepper driver init - myStepper.init(); - myStepper.set_mres(16); // ({1,2,4,8,16,32,64,128,256}) number of microsteps - myStepper.set_IHOLD_IRUN(10, 10, 0); // ([0-31],[0-31],[0-5]) sets all currents to maximum - myStepper.set_I_scale_analog(0); // ({0,1}) 0: I_REF internal, 1: sets I_REF to AIN - myStepper.set_tbl(1); // ([0-3]) set comparator blank time to 16, 24, 36 or 54 clocks, 1 or 2 is recommended - myStepper.set_toff(8); // ([0-15]) 0: driver disable, 1: use only with TBL>2, 2-15: off time setting during slow decay phase - myStepper.set_en_pwm_mode(1); // 0: driver disable PWM mode, 1: driver enable PWM mode + stepper.init(); + stepper.set_mres(16); // ({1,2,4,8,16,32,64,128,256}) number of microsteps + stepper.set_IHOLD_IRUN(10, 10, 0); // ([0-31],[0-31],[0-5]) sets all currents to maximum + stepper.set_I_scale_analog(0); // ({0,1}) 0: I_REF internal, 1: sets I_REF to AIN + stepper.set_tbl(1); // ([0-3]) set comparator blank time to 16, 24, 36 or 54 clocks, 1 or 2 is recommended + stepper.set_toff(8); // ([0-15]) 0: driver disable, 1: use only with TBL>2, 2-15: off time setting during slow decay phase + stepper.set_en_pwm_mode(1); // 0: driver disable PWM mode, 1: driver enable PWM mode cover_closed = is_cover_closed(); tank_inserted = is_tank_inserted(); @@ -109,24 +109,12 @@ Hardware::Hardware() { void Hardware::read_adc() { if (adc_channel) { uvled_temp_celsius = interpolate_i16_ylin_P(read_adc_raw(THERM_READ_PIN) >> 2, 34, uvled_temp_table_raw, 1250, -50) / 10.0; - uvled_temp = config.SI_unit_system ? uvled_temp_celsius : celsius2fahrenheit(uvled_temp_celsius); + USB_PRINTP("UV: "); + USB_PRINTLN(uvled_temp_celsius); } else { - chamber_temp_celsius = interpolate_i16_ylin_P(read_adc_raw(THERM_READ_PIN) >> 2, 34, chamber_temp_table_raw, 1250, -50) / 10.0; - chamber_temp = config.SI_unit_system ? chamber_temp_celsius : celsius2fahrenheit(chamber_temp_celsius); - - #ifdef CW1S - if(heater_on){ - float error = config.target_temp - chamber_temp_celsius; - uint16_t pwm_duty = error > 0.0 ? round((error < 2.0 ? error : 2.0) * 980) : 0; - set_heater_pwm_duty(pwm_duty); - adjust_fan_speed(0, HEATING_ON_FAN1_DUTY); - - }else{ - adjust_fan_speed(0, chamber_temp_celsius > CHAMBER_TEMP_THR_FAN1_ON ? (fan_duty[0] > CHAMBER_TEMP_THR_FAN1_DUTY ? fan_duty[0] : CHAMBER_TEMP_THR_FAN1_DUTY) : fan_duty[0]); - - } - #endif - + chamber_temp_celsius = adjust_chamber_temp(interpolate_i16_ylin_P(read_adc_raw(THERM_READ_PIN) >> 2, 34, chamber_temp_table_raw, 1250, -50)); + USB_PRINTP("CH: "); + USB_PRINTLN(chamber_temp_celsius); } adc_channel = !adc_channel; outputchip.digitalWrite(ANALOG_SWITCH_A, adc_channel); @@ -187,23 +175,14 @@ void Hardware::encoder_read() { } } -#ifdef CW1S - void Hardware::slow_pwm_tick() { - static uint16_t timer0_ticks = 0; - if(slow_pwm_on){ - if(++timer0_ticks > 1000) timer0_ticks = 0; - wanted_heater_pin_state = timer0_ticks < heater_pwm_duty; - } - } -#endif - -void Hardware::run_motor() { - TIMSK3 |= (1 << OCIE3A); // enable stepper timer +void Hardware::run_motor(bool direction) { + TIMSK3 |= (1 << OCIE3A); // enable stepper timer + outputchip.digitalWrite(DIR_PIN, direction); enable_stepper(); } void Hardware::stop_motor() { - TIMSK3 = 0; // disable stepper timer + TIMSK3 = 0; // disable stepper timer disable_stepper(); } @@ -217,18 +196,18 @@ void Hardware::disable_stepper() { void Hardware::speed_configuration(uint8_t speed, bool fast_mode, bool gear_shifting) { if (fast_mode) { - myStepper.set_IHOLD_IRUN(31, 31, 5); - myStepper.set_mres(16); + stepper.set_IHOLD_IRUN(31, 31, 5); + stepper.set_mres(16); if (gear_shifting) { microstep_control = map(speed, 1, 10, MIN_FAST_SPEED, MAX_FAST_SPEED); } else { target_accel_period = map(speed, 1, 10, MIN_FAST_SPEED, MAX_FAST_SPEED); microstep_control = FAST_SPEED_START; - accel_us_last = millis(); + accel_ms_last = millis(); } } else { - myStepper.set_IHOLD_IRUN(10, 10, 0); - myStepper.set_mres(256); + stepper.set_IHOLD_IRUN(10, 10, 0); + stepper.set_mres(256); microstep_control = map(speed, 1, 10, MIN_SLOW_SPEED, MAX_SLOW_SPEED); } do_acceleration = fast_mode && !gear_shifting; @@ -242,31 +221,19 @@ void Hardware::acceleration() { microstep_control--; } else { do_acceleration = false; - myStepper.set_IHOLD_IRUN(10, 10, 5); + stepper.set_IHOLD_IRUN(10, 10, 5); } } void Hardware::run_heater() { - #ifdef CW1S - heater_on = true; - slow_pwm_on = true; - #else - outputchip.digitalWrite(FAN_HEAT_PIN, HIGH); - #endif - heater_us_last = millis(); + chamber_temp_celsius = 0.0; + heating_started_ms = millis(); + heating_in_progress = true; wdt_enable(WDTO_4S); } void Hardware::stop_heater() { - #ifdef CW1S - set_heater_pin_state(false); - heater_on = false; - slow_pwm_on = false; - set_heater_pwm_duty(0); - #else - outputchip.digitalWrite(FAN_HEAT_PIN, LOW); - #endif - heater_us_last = 0; + heating_in_progress = false; wdt_disable(); } @@ -298,13 +265,8 @@ void Hardware::echo() { } void Hardware::beep() { - analogWrite(BEEPER, 220); - delay(50); - digitalWrite(BEEPER, LOW); - delay(250); - analogWrite(BEEPER, 220); - delay(50); - digitalWrite(BEEPER, LOW); + warning_beep(); + warning_beep(); } void Hardware::warning_beep() { @@ -314,67 +276,33 @@ void Hardware::warning_beep() { delay(250); } -void Hardware::set_fans(uint8_t* duties) { - fan_duty[0] = duties[0]; - fan_duty[1] = duties[1]; - fans_target_temp = 0; - fans_duty(); -} - -void Hardware::set_target_temp(uint8_t target_temp) { - fans_target_temp = target_temp; - PI_summ_err = 0; -} - -void Hardware::set_fan1_duty(uint8_t duty) { - fans_duty(0, duty); -} - -void Hardware::set_fan2_duty(uint8_t duty) { - fans_duty(1, duty); +void Hardware::set_chamber_target_temp(uint8_t target_temp) { + chamber_target_temp = target_temp; } -#ifdef CW1S - void Hardware::adjust_fan_speed(uint8_t fan, uint8_t duty) { - if(fan_duty[fan] != duty){ - fan_duty[fan] = duty; - fans_duty(fan, duty); - } - } - - uint8_t Hardware::get_heater_pwm_duty() { - return heater_pwm_duty; - } - - void Hardware::set_heater_pwm_duty(uint16_t duty) { - heater_pwm_duty = duty; - if(heater_pwm_duty > 1000) heater_pwm_duty = 1000; - if(duty == 0){ - wanted_heater_pin_state = false; - } - } - - void Hardware::set_heater_pin_state(bool value) { - if(heater_pin_state != value) { - outputchip.digitalWrite(FAN_HEAT_PIN, value); - heater_pin_state = value; - } - } -#endif - -void Hardware::fans_duty() { - for (uint8_t i = 0; i < 2; ++i) { - fans_duty(i, fan_duty[i]); +void Hardware::force_fan_speed(uint8_t fan_speed_1, uint8_t fan_speed_2) { + if (fan_speed_1 || fan_speed_2) { + fans_forced = true; + set_fan_speed(0, fan_speed_1); + set_fan_speed(1, fan_speed_2); + } else { + fans_forced = false; } } -void Hardware::fans_duty(uint8_t fan, uint8_t duty) { +void Hardware::set_fan_speed(uint8_t fan, uint8_t speed) { + if (fan_speed[fan] == speed) { + return; + } + fan_speed[fan] = speed; USB_PRINTP("fan "); USB_PRINT(fan); USB_PRINTP("->"); - if (duty) { - USB_PRINTLN(duty); - analogWrite(fan_pwm_pins[fan], map(duty, 0, 100, 255, 0)); + uint8_t fan_pwm_pins[2] = {FAN1_PWM_PIN, FAN2_PWM_PIN}; + uint8_t fan_enable_pins[2] = {FAN1_PIN, FAN2_PIN}; + if (speed) { + USB_PRINTLN(speed); + analogWrite(fan_pwm_pins[fan], map(speed, 0, 100, 255, 0)); outputchip.digitalWrite(fan_enable_pins[fan], HIGH); } else { USB_PRINTLNP("OFF"); @@ -383,81 +311,63 @@ void Hardware::fans_duty(uint8_t fan, uint8_t duty) { } } -void Hardware::fans_PI_regulator() { - // FIXME this is not working as expected :( -// USB_PRINTP("actual: "); -// USB_PRINTLN(chamber_temp); -// USB_PRINTP("target: "); -// USB_PRINTLN(fans_target_temp); - double err_value = chamber_temp - fans_target_temp; -// USB_PRINTP("err: "); -// USB_PRINTLN(err_value); - PI_summ_err += err_value; -// USB_PRINTP("sum: "); -// USB_PRINTLN(PI_summ_err); - - if ((PI_summ_err > 10000) || (PI_summ_err < -10000)) { - PI_summ_err = 10000; - } - - double new_speed = P * err_value + I * PI_summ_err; // TODO uint8_t? -// USB_PRINTP("PI new value: "); -// USB_PRINTLN(new_speed); - if (new_speed > 100) { - new_speed = 100; - } else if (new_speed < MIN_FAN_SPEED) { +void Hardware::cooling() { + float error = uvled_temp_celsius - OPTIMAL_TEMP; + uint8_t new_speed = error > 0.0 ? round_short((error < 10.0 ? error : 10.0) * 10) : 0; +/* + USB_PRINTP("actual t.: "); + USB_PRINTLN(uvled_temp_celsius); + USB_PRINTP("target t.: "); + USB_PRINTLN(OPTIMAL_TEMP); + USB_PRINTP("error: "); + USB_PRINTLN(error); + USB_PRINTP("new_speed: "); + USB_PRINTLN(new_speed); +*/ + if (new_speed < MIN_FAN_SPEED || heating_in_progress) { new_speed = MIN_FAN_SPEED; } - - if (new_speed != fan_duty[0] || new_speed != fan_duty[1]) { - fan_duty[0] = new_speed; - fan_duty[1] = new_speed; - fans_duty(); - } + set_cooling_speed(new_speed); } -void Hardware::fans_check() { +void Hardware::fans_rpm() { for (uint8_t i = 0; i < 3; ++i) { - fan_rpm[i] = 60000 / FAN_CHECK_PERIOD * fan_tacho_count[i]; - fan_tacho_count[i] = 0; + fan_rpm[i] = 60 * fan_tacho_count[i]; // USB_PRINT(i); // USB_PRINTP(": "); +// USB_PRINT(fan_tacho_count[i]); +// USB_PRINTP("->"); // USB_PRINTLN(fan_rpm[i]); + fan_tacho_count[i] = 0; } } uint8_t Hardware::loop() { - unsigned long us_now = millis(); - if (do_acceleration && us_now - accel_us_last >= 50) { - accel_us_last = us_now; + unsigned long ms_now = millis(); + if (do_acceleration && ms_now - accel_ms_last >= 50) { + accel_ms_last = ms_now; acceleration(); } - if (us_now - fans_us_last >= FAN_CHECK_PERIOD) { - fans_us_last = us_now; - fans_check(); - } - if (us_now - adc_us_last >= 500) { - adc_us_last = us_now; + if (ms_now - one_second_ms_last >= 1000) { + one_second_ms_last = ms_now; read_adc(); - if (fans_target_temp) { - fans_PI_regulator(); + fans_rpm(); + // after uvled_temp_celsius has been read + if (!adc_channel and !fans_forced) { + cooling(); } + heating(); } - #ifdef CW1S - if (wanted_heater_pin_state != heater_pin_state) { - set_heater_pin_state(wanted_heater_pin_state); - } - #endif - uint8_t events = 0; - if (heater_error) + if (disable_controls) { return events; + } - #ifndef CW1S - // failed once, failed every time - heater_error = heater_us_last && !fan_rpm[2] && us_now - heater_us_last > HEATER_CHECK_DELAY; - #endif + heater_error = heating_in_progress && handle_heater(); + if (heater_error) { + stop_heater(); + } // cover bool cover_closed_now = is_cover_closed(); @@ -512,5 +422,3 @@ uint8_t Hardware::loop() { return events; } - -Hardware hw; diff --git a/src/hardware.h b/src/hardware.h index 1268890..cac61c1 100644 --- a/src/hardware.h +++ b/src/hardware.h @@ -13,105 +13,81 @@ #define EVENT_CONTROL_UP 64 #define EVENT_CONTROL_DOWN 128 -float celsius2fahrenheit(float); -float fahrenheit2celsius(float); +float celsius2fahrenheit(float celsius); +float fahrenheit2celsius(float fahrenheit); +uint8_t round_short(float); +float get_configured_temp(float temp); + class Hardware { public: - Hardware(); - - static void encoder_read(); - - static void run_motor(); - static void stop_motor(); - static void enable_stepper(); - static void disable_stepper(); - static void speed_configuration(uint8_t speed, bool fast_mode, bool gear_shifting = false); - static void acceleration(); - - static void run_heater(); - static void stop_heater(); - - static void run_led(); - static void stop_led(); - - static bool is_cover_closed(); - static bool is_tank_inserted(); - - static void echo(); - static void beep(); - static void warning_beep(); - - static void set_fans(uint8_t* duties); - static void set_target_temp(uint8_t target_temp); - static void set_fan1_duty(uint8_t duty); - static void set_fan2_duty(uint8_t duty); - - static uint8_t loop(); - - #ifdef CW1S - static void slow_pwm_tick(); - static void adjust_fan_speed(uint8_t fan, uint8_t duty); - static uint8_t get_heater_pwm_duty(); - static void set_heater_pwm_duty(uint16_t duty); - #endif - - static uint16_t fan_rpm[3]; - static volatile uint8_t fan_tacho_count[3]; - static volatile uint8_t microstep_control; - static float chamber_temp_celsius; - static float chamber_temp; - static float uvled_temp_celsius; - static float uvled_temp; - static bool heater_error; - #ifdef CW1S - static bool wanted_heater_pin_state; - static bool slow_pwm_on; - #endif - -private: - static MCP outputchip; - static Trinamic_TMC2130 myStepper; - - static void read_adc(); - static int16_t read_adc_raw(uint8_t pin); - static void fans_duty(); - static void fans_duty(uint8_t fan, uint8_t duty); - static void fans_PI_regulator(); - static void fans_check(); - #ifdef CW1S - static void set_heater_pin_state(bool value); - #endif - - static uint8_t lcd_encoder_bits; - static volatile int8_t rotary_diff; - static uint8_t target_accel_period; - - static uint8_t fan_duty[2]; - static uint8_t fan_pwm_pins[2]; - static uint8_t fan_enable_pins[2]; - static uint8_t fans_target_temp; - - static uint8_t fan_errors; - - static unsigned long accel_us_last; - static unsigned long fans_us_last; - static unsigned long adc_us_last; - static unsigned long heater_us_last; - static unsigned long button_timer; - static double PI_summ_err; - static bool do_acceleration; - static bool cover_closed; - static bool tank_inserted; - static bool button_active; - static bool long_press_active; - static bool adc_channel; - - #ifdef CW1S - static bool heater_on; - static bool heater_pin_state; - static uint16_t heater_pwm_duty; - #endif + Hardware(uint16_t model_magic); + + void encoder_read(); + void run_motor(bool direction); + void stop_motor(); + void enable_stepper(); + void disable_stepper(); + void speed_configuration(uint8_t speed, bool fast_mode, bool gear_shifting = false); + void acceleration(); + + void run_heater(); + void stop_heater(); + void run_led(); + void stop_led(); + + bool is_cover_closed(); + bool is_tank_inserted(); + + void echo(); + void beep(); + void warning_beep(); + + void set_chamber_target_temp(uint8_t target_temp); + void force_fan_speed(uint8_t fan_speed_1, uint8_t fan_speed_2); + + uint8_t loop(); + + uint16_t model_magic; + uint16_t fan_rpm[3]; + volatile uint8_t fan_tacho_count[3]; + volatile uint8_t microstep_control; + float chamber_temp_celsius; + float uvled_temp_celsius; + bool heater_error; + bool disable_controls; + +protected: + MCP outputchip; + Trinamic_TMC2130 stepper; + + void read_adc(); + int16_t read_adc_raw(uint8_t pin); + void cooling(); + void fans_rpm(); + void set_fan_speed(uint8_t fan, uint8_t speed); + virtual void heating() = 0; + virtual bool handle_heater() = 0; + virtual void set_cooling_speed(uint8_t speed) = 0; + virtual float adjust_chamber_temp(int16_t temp) = 0; + + uint8_t lcd_encoder_bits; + volatile int8_t rotary_diff; + uint8_t target_accel_period; + + uint8_t fan_speed[2]; + uint8_t chamber_target_temp; + + unsigned long accel_ms_last; + unsigned long one_second_ms_last; + unsigned long heating_started_ms; + unsigned long button_timer; + bool heating_in_progress; + bool do_acceleration; + bool cover_closed; + bool tank_inserted; + bool button_active; + bool long_press_active; + bool adc_channel; + bool fans_forced; }; - -extern Hardware hw; diff --git a/src/main.cpp b/src/main.cpp index fcecb03..4620fff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,12 @@ #include -#include "hardware.h" +#include "device.h" #include "config.h" #include "ui.h" #include "states.h" #include "LiquidCrystal_Prusa.h" -const char* pgmstr_serial_number = reinterpret_cast(0x7fe0); // see SN_LENGTH!!! +const char* pgmstr_serial_number = reinterpret_cast(SN_ADDRESS); volatile uint16_t* const bootKeyPtr = (volatile uint16_t *)(RAMEND - 1); static volatile uint16_t bootKeyPtrVal __attribute__ ((section (".noinit"))); @@ -74,9 +74,7 @@ void setupTimer0() { ISR(TIMER0_COMPA_vect) { hw.encoder_read(); - #ifdef CW1S - hw.slow_pwm_tick(); - #endif + hw.one_ms_tick(); } // timer for stepper move @@ -111,13 +109,19 @@ void fan_tacho2() { hw.fan_tacho_count[1]++; } -#ifndef CW1S - void fan_tacho3() { - hw.fan_tacho_count[2]++; - } -#endif +void fan_tacho3() { + hw.fan_tacho_count[2]++; +} void setup() { + uint16_t model_magic = pgm_read_word_near(SN_ADDRESS); + if (hw.model_magic != model_magic) { + lcd.clear(); + lcd.print_P(pgmstr_wrong_model, (20 - strlen_P(pgmstr_wrong_model)) / 2, 1); + while(true) { + delay(1000); + } + } read_config(); @@ -130,33 +134,20 @@ void setup() { // FAN tachos pinMode(FAN1_TACHO_PIN, INPUT_PULLUP); - pinMode(FAN2_TACHO_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(FAN1_TACHO_PIN), fan_tacho1, RISING); + + pinMode(FAN2_TACHO_PIN, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(FAN2_TACHO_PIN), fan_tacho2, RISING); - #ifndef CW1S - pinMode(FAN_HEAT_TACHO_PIN, INPUT_PULLUP); - attachInterrupt(digitalPinToInterrupt(FAN_HEAT_TACHO_PIN), fan_tacho3, RISING); - #endif + + pinMode(FAN_HEAT_TACHO_PIN, INPUT_PULLUP); + attachInterrupt(digitalPinToInterrupt(FAN_HEAT_TACHO_PIN), fan_tacho3, RISING); noInterrupts(); setupTimer0(); setupTimer3(); interrupts(); - States::init(); UI::init(); - - #ifdef CW1S - hw.set_heater_pwm_duty(0); - static const char model_cmp[] = "02_"; - #else - static const char model_cmp[] = "01_"; - #endif - if(memcmp_P(model_cmp, pgmstr_serial_number, 3) != 0) { - lcd.clear(); - lcd.print_P(pgmstr_wrong_model, (20 - strlen_P(pgmstr_wrong_model)) / 2, 1); - while(1); - } } void loop() { @@ -167,23 +158,8 @@ void loop() { uint8_t events = hw.loop(); States::loop(events); UI::loop(events); - } -/* - // FIXME is this needed to fix ESD shock? Any better solution? - TODO - if (millis() > time_now + 5500) { - time_now = millis(); - lcd.reinit(); - lcd.createChar(BACKSLASH_CHAR, Backslash); - lcd.createChar(BACK_CHAR, Back); - lcd.createChar(RIGHT_CHAR, Right); - lcd.createChar(PLAY_CHAR, Play); - lcd.createChar(STOP_CHAR, Stop); - // REDRAW! - } -*/ #if 0 //! @brief Get reset flags diff --git a/src/pins_board_4.h b/src/pins_board_4.h index 6127dff..25de681 100644 --- a/src/pins_board_4.h +++ b/src/pins_board_4.h @@ -41,9 +41,7 @@ #define FAN2_TACHO_PIN 2 #define FAN_HEAT_PIN MCP_B2 -#ifndef CW1S - #define FAN_HEAT_TACHO_PIN 1 -#endif +#define FAN_HEAT_TACHO_PIN 1 #define ANALOG_SWITCH_A MCP_B1 #define ANALOG_SWITCH_B MCP_B0 diff --git a/src/simple_print.cpp b/src/simple_print.cpp index a329efa..c6e56f0 100644 --- a/src/simple_print.cpp +++ b/src/simple_print.cpp @@ -39,7 +39,7 @@ void SimplePrint::print(float number) { void SimplePrint::printTime(uint16_t time) { uint8_t min = time / 60; uint8_t sec = time % 60; - print(min, 10, '0'); + print(min, 100, ' '); write(':'); print(sec, 10, '0'); } @@ -72,5 +72,6 @@ void SimplePrint::write(uint8_t c) { } char* SimplePrint::get_position() { + *_buffer_position = char(0); return _buffer_position; } diff --git a/src/states.cpp b/src/states.cpp index 9218f4c..485e17f 100644 --- a/src/states.cpp +++ b/src/states.cpp @@ -1,5 +1,7 @@ #include "states.h" #include "defines.h" +#include "wrappers.h" +#include "ui.h" namespace States { @@ -7,65 +9,59 @@ namespace States { Base menu; Confirm confirm(false); Confirm error(true); - Base washing( + Direction_change washing( pgmstr_washing, STATE_OPTION_CONTROLS | STATE_OPTION_WASHING, - config.fans_washing_speed, + &config.wash_cycles, &confirm, &config.washing_run_time, + MAX_WASHING_RUNTIME, &config.washing_speed); - // FIXME - would be better to set PI regulator and manage heater for drying/curing? + Base filtering( + pgmstr_filtering, + STATE_OPTION_CONTROLS | STATE_OPTION_WASHING, + &confirm, + &config.filtering_run_time, + MAX_FILTER_RUNTIME, + &config.filtering_speed); Base drying( pgmstr_drying, STATE_OPTION_CONTROLS | STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, - config.fans_drying_speed, &confirm, &config.drying_run_time, + MAX_DRYING_RUNTIME, &config.curing_speed); Base curing( pgmstr_curing, - STATE_OPTION_CONTROLS | STATE_OPTION_UVLED | STATE_OPTION_CHAMB_TEMP, - config.fans_curing_speed, + STATE_OPTION_CONTROLS | STATE_OPTION_UVLED, &confirm, &config.curing_run_time, + MAX_CURING_RUNTIME, &config.curing_speed); Base resin( pgmstr_heating, STATE_OPTION_CONTROLS | STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, - config.fans_drying_speed, &confirm, &config.resin_preheat_run_time, + MAX_PREHEAT_RUNTIME, &config.curing_speed, &config.resin_target_temp); - uint8_t max_warmup_run_time = MAX_WARMUP_RUNTIME; Warmup warmup_print( pgmstr_warmup, nullptr, - &max_warmup_run_time, - &config.curing_speed, &config.target_temp); Warmup warmup_resin( pgmstr_warmup, &resin, - &max_warmup_run_time, - &config.curing_speed, &config.resin_target_temp); - uint8_t cooldown_time = COOLDOWN_RUNTIME; - uint8_t cooldown_fans_speed[2] = {100, 100}; - Base cooldown( - pgmstr_cooldown, - STATE_OPTION_CONTROLS, - cooldown_fans_speed, - &confirm, - &cooldown_time); + Cooldown cooldown(&confirm); + Reset reset; Test_heater selftest_heater( pgmstr_heater_test, - config.fans_drying_speed, &confirm); Test_uvled selftest_uvled( pgmstr_led_test, - config.fans_curing_speed, &selftest_heater); Test_fans selftest_fans( pgmstr_fans_test, @@ -78,13 +74,13 @@ namespace States { &selftest_rotation, pgmstr_remove_tank, pgmstr_insert_tank, - hw.is_tank_inserted); + is_tank_inserted); Test_switch selftest_cover( pgmstr_cover_test, &selftest_tank, pgmstr_open_cover, pgmstr_close_cover, - hw.is_cover_closed); + is_cover_closed); /*** states data ***/ @@ -98,14 +94,20 @@ namespace States { active_state->process_events(events); Base* new_state = active_state->loop(); if (new_state) { - change(new_state); + if (active_state == &menu && new_state == &error) { + UI::set_menu(&UI::error); + } else { + change(new_state); + } } } void change(Base* new_state) { - active_state->do_pause(); + bool handle_heater = new_state->options & STATE_OPTION_HEATER; + active_state->do_pause(!handle_heater); + handle_heater = active_state->options & STATE_OPTION_HEATER; active_state = new_state; - active_state->start(); + active_state->start(!handle_heater); } } diff --git a/src/states.h b/src/states.h index 06e2ba7..80e4fdd 100644 --- a/src/states.h +++ b/src/states.h @@ -10,13 +10,15 @@ namespace States { extern Base menu; extern Confirm confirm; extern Confirm error; - extern Base washing; + extern Direction_change washing; + extern Base filtering; extern Base drying; extern Base curing; extern Base resin; extern Warmup warmup_print; extern Warmup warmup_resin; - extern Base cooldown; + extern Cooldown cooldown; + extern Reset reset; extern Test_switch selftest_cover; void init(); diff --git a/src/states_items.cpp b/src/states_items.cpp index ff57b21..a434d80 100644 --- a/src/states_items.cpp +++ b/src/states_items.cpp @@ -1,4 +1,7 @@ +#include +#include #include "states.h" +#include "EEPROM.h" namespace States { @@ -9,42 +12,40 @@ namespace States { Base::Base( const char* title, uint8_t options, - uint8_t* fans_duties, Base* continue_to, uint8_t* continue_after, + uint8_t max_runtime, uint8_t* motor_speed, uint8_t* target_temp) : + options(options), continue_to(continue_to), message(nullptr), target_temp(target_temp), - fans_duties(fans_duties), - us_last(0), - canceled(false), - title(title), - continue_after(continue_after), motor_speed(motor_speed), - options(options) + continue_after(continue_after), + max_runtime(60 * max_runtime - INC_DEC_TIME_STEP), + title(title) {} - void Base::start() { + void Base::start(bool handle_heater) { + ms_last = 0; canceled = false; - hw.set_fans(fans_duties); + motor_direction = false; if (continue_after) { - timer.setCounter(0, *continue_after, 0, options & STATE_OPTION_TIMER_UP); + timer.setCounterInSeconds(*continue_after * 60, options & STATE_OPTION_TIMER_UP); } - /* FIXME PI_regulator is not working as expected if (target_temp) { - hw.set_target_temp(*target_temp); + hw.set_chamber_target_temp(*target_temp); } - */ - if (options & (STATE_OPTION_UVLED | STATE_OPTION_HEATER) && (!hw.is_cover_closed() || hw.is_tank_inserted())) { + if ((options & (STATE_OPTION_UVLED | STATE_OPTION_HEATER) && (!hw.is_cover_closed() || hw.is_tank_inserted())) + || (options & STATE_OPTION_WASHING && !hw.is_tank_inserted())) { if (continue_after) { timer.start(); } - do_pause(); + do_pause(handle_heater); } else { - do_continue(); + do_continue(handle_heater); } } @@ -56,22 +57,24 @@ namespace States { return continue_to; } if (hw.heater_error) { - error.new_text(pgmstr_heater_error, pgmstr_please_restart); + error.new_text(pgmstr_heater_error, pgmstr_not_spinning); return &error; } - if (options & STATE_OPTION_UVLED) { - if (hw.uvled_temp_celsius < 0.0) { - error.new_text(pgmstr_led_failure, pgmstr_read_temp_error); - return &error; - } - if (hw.uvled_temp_celsius > UVLED_MAX_TEMP) { - error.new_text(pgmstr_led_failure, pgmstr_overheat_error); - return &error; - } + if (hw.chamber_temp_celsius < 0.0) { + error.new_text(pgmstr_heater_failure, pgmstr_read_temp_error); + return &error; } - if (us_last && millis() - us_last > LED_DELAY && options & STATE_OPTION_UVLED) { + if (hw.uvled_temp_celsius < 0.0) { + error.new_text(pgmstr_led_failure, pgmstr_read_temp_error); + return &error; + } + if (options & STATE_OPTION_UVLED && (uint8_t)hw.uvled_temp_celsius > UVLED_MAX_TEMP) { + error.new_text(pgmstr_led_failure, pgmstr_overheat_error); + return &error; + } + if (ms_last && millis() - ms_last > LED_DELAY && options & STATE_OPTION_UVLED) { hw.run_led(); - us_last = 0; + ms_last = 0; } return nullptr; } @@ -84,11 +87,11 @@ namespace States { return false; } - void Base::do_pause() { + void Base::do_pause(bool handle_heater) { if (options & STATE_OPTION_UVLED) { hw.stop_led(); } - if (options & STATE_OPTION_HEATER) { + if (handle_heater && options & STATE_OPTION_HEATER) { hw.stop_heater(); } if (motor_speed) { @@ -99,18 +102,18 @@ namespace States { } } - void Base::do_continue() { + void Base::do_continue(bool handle_heater) { if (motor_speed) { hw.speed_configuration(*motor_speed, options & STATE_OPTION_WASHING); - hw.run_motor(); + hw.run_motor(motor_direction); } - if (options & STATE_OPTION_HEATER) { + if (handle_heater && options & STATE_OPTION_HEATER) { hw.run_heater(); } if (continue_after) { timer.start(); } - us_last = millis(); + ms_last = millis(); } void Base::pause_continue() { @@ -166,10 +169,10 @@ namespace States { float Base::get_temperature() { if (options & STATE_OPTION_CHAMB_TEMP) { - return hw.chamber_temp; + return hw.chamber_temp_celsius; } if (options & STATE_OPTION_UVLED_TEMP) { - return hw.uvled_temp; + return hw.uvled_temp_celsius; } return -40.0; } @@ -180,7 +183,7 @@ namespace States { if (secs < INC_DEC_TIME_STEP) { return pgmstr_min_symb; } else { - timer.setCounterInSeconds(secs - INC_DEC_TIME_STEP); + timer.setCounterInSeconds(secs - INC_DEC_TIME_STEP, options & STATE_OPTION_TIMER_UP); return pgmstr_double_lt; } } @@ -190,10 +193,10 @@ namespace States { const char* Base::increase_time() { if (continue_after && options & STATE_OPTION_CONTROLS) { uint16_t secs = timer.getCurrentTimeInSeconds(); - if (secs > 10 * 60 - INC_DEC_TIME_STEP) { + if (secs > max_runtime) { return pgmstr_max_symb; } else { - timer.setCounterInSeconds(secs + INC_DEC_TIME_STEP); + timer.setCounterInSeconds(secs + INC_DEC_TIME_STEP, options & STATE_OPTION_TIMER_UP); return pgmstr_double_gt; } } @@ -240,38 +243,122 @@ namespace States { } - // States::Warmup - Warmup::Warmup( + // States::Direction_change + Direction_change::Direction_change( const char* title, + uint8_t options, + uint8_t* direction_cycles, Base* continue_to, uint8_t* continue_after, + uint8_t max_runtime, uint8_t* motor_speed, uint8_t* target_temp) : - Base(title, STATE_OPTION_TIMER_UP | STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, config.fans_drying_speed, continue_to, continue_after, motor_speed, target_temp) + Base(title, options, continue_to, continue_after, max_runtime, motor_speed, target_temp), + direction_cycles(direction_cycles) + {} + + void Direction_change::start(bool handle_heater) { + old_seconds = 0; + stop_seconds = 0; + remaining_cycles = *direction_cycles; + if (*direction_cycles) { + direction_change_time = *continue_after * 60 / *direction_cycles; + direction_change_time++; + } else { + direction_change_time = *continue_after * 60; + } + Base::start(handle_heater); + } + + Base* Direction_change::loop() { + uint16_t seconds = timer.getCurrentTimeInSeconds(); + if (seconds != old_seconds) { + if (stop_seconds && stop_seconds - seconds >= DIR_CHANGE_DELAY) { + hw.speed_configuration(*motor_speed, options & STATE_OPTION_WASHING); + hw.run_motor(motor_direction); + stop_seconds = 0; + if (remaining_cycles > 1) { + remaining_cycles--; + } + } + if (old_seconds && !(seconds % direction_change_time)) { + hw.stop_motor(); + motor_direction = !motor_direction; + stop_seconds = seconds; + } + old_seconds = seconds; + } + return Base::loop(); + } + + const char* Direction_change::decrease_time() { + const char* symbol = Base::decrease_time(); + update_direction_change_time(); + return symbol; + } + + const char* Direction_change::increase_time() { + const char* symbol = Base::increase_time(); + update_direction_change_time(); + return symbol; + } + + void Direction_change::update_direction_change_time() { + uint16_t seconds = timer.getCurrentTimeInSeconds(); + direction_change_time = seconds / remaining_cycles; + direction_change_time++; + if (stop_seconds) { + stop_seconds = seconds; + } + old_seconds = seconds; + } + + + // States::Warmup + Warmup::Warmup( + const char* title, + Base* continue_to, + uint8_t* target_temp) + : + Base(title, STATE_OPTION_TIMER_UP | STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, continue_to, &continue_after, MAX_WARMUP_RUNTIME, &config.curing_speed, target_temp), + continue_after(MAX_WARMUP_RUNTIME) {} Base* Warmup::loop() { - if (!config.heat_to_target_temp || hw.chamber_temp >= *target_temp) { + if (!config.heat_to_target_temp || round_short(get_configured_temp(hw.chamber_temp_celsius)) >= *target_temp) { return continue_to; } return Base::loop(); } + // States::Cooldown + Cooldown::Cooldown(Base* continue_to) : + Base(pgmstr_cooldown, STATE_OPTION_CONTROLS, continue_to, &cooldown_time) + {} + + void Cooldown::start(bool handle_heater) { + cooldown_time = COOLDOWN_RUNTIME; + hw.force_fan_speed(100, 100); + Base::start(handle_heater); + } + + // States::Confirm Confirm::Confirm(bool force_wait) : Base(pgmstr_emptystr, STATE_OPTION_SHORT_CANCEL), force_wait(force_wait), quit(false) {} - void Confirm::start() { + void Confirm::start(__attribute__((unused)) bool handle_heater) { canceled = false; quit = true; - us_last = 1; // beep + ms_last = 1; // beep const char* text2 = pgmstr_emptystr; uint8_t mode = config.finish_beep_mode; if (force_wait) { mode = 2; + hw.disable_controls = true; } switch(mode) { case 2: @@ -279,21 +366,21 @@ namespace States { text2 = pgmstr_press2continue; break; case 0: - us_last = 0; // no beep + ms_last = 0; // no beep break; default: break; } confirm.new_text(pgmstr_finished, text2); - hw.set_fans(fans_duties); + hw.force_fan_speed(0, 0); // automatic fan control } Base* Confirm::loop() { canceled = quit; - unsigned long us_now = millis(); - if (us_last && us_now - us_last > 1000) { + unsigned long ms_now = millis(); + if (ms_last && ms_now - ms_last > 1000) { hw.beep(); - us_last = us_now; + ms_last = ms_now; } if (canceled) { return continue_to; @@ -303,6 +390,19 @@ namespace States { } + // States::Reset + Reset::Reset() : + Base(pgmstr_emptystr, 0) + {} + + void Reset::start(__attribute__((unused)) bool handle_heater) { + EEPROM.write(CONFIG_START, 0xff); + // use internal Watchdog to reset + wdt_enable(WDTO_30MS); + while(1) {}; + } + + // States::Test_switch Test_switch::Test_switch( const char* title, @@ -311,20 +411,18 @@ namespace States { const char* message_off, bool (*value_getter)()) : - Base(title, 0, config.fans_menu_speed, continue_to), + Base(title, 0, continue_to), message_on(message_on), message_off(message_off), - value_getter(value_getter), - test_count(0), - old_state(false) + value_getter(value_getter) {} - void Test_switch::start() { + void Test_switch::start(__attribute__((unused)) bool handle_heater) { canceled = false; old_state = value_getter(); message = old_state ? message_on : message_off; test_count = SWITCH_TEST_COUNT; - us_last = millis(); + ms_last = millis(); } Base* Test_switch::loop() { @@ -332,9 +430,9 @@ namespace States { hw.beep(); return continue_to; } - unsigned long us_now = millis(); - if (us_now - us_last > 250) { - us_last = us_now; + unsigned long ms_now = millis(); + if (ms_now - ms_last > 250) { + ms_last = ms_now; bool state = value_getter(); if (old_state != state) { old_state = state; @@ -351,20 +449,16 @@ namespace States { const char* title, Base* continue_to) : - Base(title, 0, config.fans_menu_speed, continue_to, &test_time, &test_speed), - test_time(ROTATION_TEST_TIME), - test_speed(0), - old_seconds(0), - fast_mode(false), - draw(false) + Base(title, 0, continue_to, &test_time, 10, &test_speed) {} - void Test_rotation::start() { + void Test_rotation::start(bool handle_heater) { + test_time = ROTATION_TEST_TIME; test_speed = 10; old_seconds = 60 * ROTATION_TEST_TIME; fast_mode = true; draw = true; - Base::start(); + Base::start(handle_heater); hw.speed_configuration(test_speed, fast_mode); } @@ -389,7 +483,7 @@ namespace States { buffer[0] = fast_mode ? 'W' : 'C'; buffer_init(++buffer, --size); print(test_speed, 10, '0'); - get_position()[0] = char(0); + get_position(); draw = false; return true; } @@ -402,16 +496,11 @@ namespace States { const char* title, Base* continue_to) : - Base(title, 0, fans_speed, continue_to, &test_time), - test_time(FANS_TEST_TIME), - fans_speed{0, 0}, - old_fan_rpm{0, 0}, - old_seconds(0), - draw1(false), - draw2(false) + Base(title, 0, continue_to, &test_time) {} - void Test_fans::start() { + void Test_fans::start(bool handle_heater) { + test_time = FANS_TEST_TIME; fans_speed[0] = 0; fans_speed[1] = 100; old_fan_rpm[0] = 0; @@ -419,7 +508,8 @@ namespace States { old_seconds = 60 * FANS_TEST_TIME; draw1 = true; draw2 = true; - Base::start(); + hw.force_fan_speed(fans_speed[0], fans_speed[1]); + Base::start(handle_heater); } Base* Test_fans::loop() { @@ -447,7 +537,7 @@ namespace States { if (fans_speed[0] < 100) { fans_speed[0] += 20; fans_speed[1] = 100 - fans_speed[0]; - hw.set_fans(fans_speed); + hw.force_fan_speed(fans_speed[0], fans_speed[1]); draw1 = true; old_fan_rpm[0] = hw.fan_rpm[0]; old_fan_rpm[1] = hw.fan_rpm[1]; @@ -463,7 +553,7 @@ namespace States { print(fans_speed[0]); print_P(pgmstr_double_space+1); print(fans_speed[1]); - get_position()[0] = char(0); + get_position(); draw1 = false; return true; } @@ -477,7 +567,7 @@ namespace States { print(hw.fan_rpm[0]); print_P(pgmstr_fan2); print(hw.fan_rpm[1]); - get_position()[0] = char(0); + get_position(); draw2 = false; return true; } @@ -488,22 +578,23 @@ namespace States { // States::Test_uvled Test_uvled::Test_uvled( const char* title, - uint8_t* fans_duties, Base* continue_to) : - Base(title, STATE_OPTION_UVLED | STATE_OPTION_UVLED_TEMP, fans_duties, continue_to, &test_time), - test_time(UVLED_TEST_TIME), - old_uvled_temp(0.0) + Base(title, STATE_OPTION_UVLED | STATE_OPTION_UVLED_TEMP, continue_to, &test_time) {} - void Test_uvled::start() { - old_uvled_temp = hw.uvled_temp_celsius; - Base::start(); + void Test_uvled::start(bool handle_heater) { + test_time = UVLED_TEST_MAX_TIME; + hw.force_fan_speed(30, 30); + Base::start(handle_heater); } Base* Test_uvled::loop() { + if (round_short(hw.uvled_temp_celsius) >= TEST_TEMP) { + return continue_to; + } uint16_t seconds = timer.getCurrentTimeInSeconds() - 1; - if (!seconds && old_uvled_temp + UVLED_TEST_GAIN > hw.uvled_temp_celsius) { + if (!seconds) { error.new_text(pgmstr_led_failure, pgmstr_nopower_error); return &error; } @@ -514,35 +605,29 @@ namespace States { // States::Test_heater Test_heater::Test_heater( const char* title, - uint8_t* fans_duties, Base* continue_to) : - Base(title, STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, fans_duties, continue_to, &test_time), - test_time(HEATER_TEST_TIME), - old_chamb_temp(0.0), - old_seconds(0), - draw(false) + Base(title, STATE_OPTION_HEATER | STATE_OPTION_CHAMB_TEMP, continue_to, &test_time, 10, nullptr, &temp) {} - void Test_heater::start() { - old_chamb_temp = hw.chamber_temp_celsius; + void Test_heater::start(bool handle_heater) { + test_time = MAX_WARMUP_RUNTIME; + old_seconds = 0; + temp = get_configured_temp(TEST_TEMP); + hw.force_fan_speed(0, 0); draw = true; - Base::start(); + Base::start(handle_heater); } Base* Test_heater::loop() { - if (old_chamb_temp < 0.0 || hw.chamber_temp_celsius < 0.0) { - error.new_text(pgmstr_heater_failure, pgmstr_read_temp_error); - return &error; + if (round_short(get_configured_temp(hw.chamber_temp_celsius)) >= temp) { + return continue_to; } uint16_t seconds = timer.getCurrentTimeInSeconds() - 1; -#ifdef CW1S - // TODO this is not working on CW1S - if (!seconds && old_chamb_temp + HEATER_TEST_GAIN > hw.chamber_temp_celsius) { + if (!seconds) { error.new_text(pgmstr_heater_failure, pgmstr_nopower_error); return &error; } -#endif if (seconds != old_seconds) { old_seconds = seconds; draw = true; @@ -552,15 +637,7 @@ namespace States { bool Test_heater::get_info2(char* buffer, uint8_t size) { if (draw) { - buffer_init(buffer, size); -#ifdef CW1S - print_P(pgmstr_fan1); - print(hw.fan_rpm[0]); -#else - print_P(pgmstr_fan3); - print(hw.fan_rpm[2]); -#endif - get_position()[0] = char(0); + hw.print_heater_fan(buffer, size); draw = false; return true; } diff --git a/src/states_items.h b/src/states_items.h index e752350..e2ed732 100644 --- a/src/states_items.h +++ b/src/states_items.h @@ -1,7 +1,7 @@ #pragma once #include "Countimer.h" -#include "hardware.h" +#include "device.h" #include "i18n.h" #include "config.h" #include "simple_print.h" @@ -24,19 +24,19 @@ namespace States { Base( const char* title = pgmstr_emptystr, uint8_t options = 0, - uint8_t* fans_duties = config.fans_menu_speed, Base* continue_to = nullptr, uint8_t* continue_after = nullptr, + uint8_t max_runtime = 10, uint8_t* motor_speed = nullptr, uint8_t* target_temp = nullptr); - virtual void start(); + virtual void start(bool handle_heater = true); virtual Base* loop(); virtual bool get_info1(char* buffer, uint8_t size); virtual bool get_info2(char* buffer, uint8_t size); - void do_pause(); - void do_continue(); + void do_pause(bool handle_heater = true); + void do_continue(bool handle_heater = true); void pause_continue(); void cancel(); void process_events(uint8_t events); @@ -45,25 +45,52 @@ namespace States { const char* get_message(); uint16_t get_time(); float get_temperature(); - const char* decrease_time(); - const char* increase_time(); + virtual const char* decrease_time(); + virtual const char* increase_time(); bool is_paused(); bool is_finished(); void set_continue_to(Base* to); void new_text(const char* new_title, const char* new_message); + uint8_t const options; protected: Base* continue_to; const char* message; - uint8_t* const target_temp; - uint8_t* const fans_duties; - unsigned long us_last; + uint8_t* target_temp; + uint8_t* const motor_speed; + uint8_t* const continue_after; + unsigned long ms_last; bool canceled; + bool motor_direction; private: const char* get_hw_pause_reason(); + uint16_t max_runtime; const char* title; - uint8_t* const continue_after; - uint8_t* const motor_speed; - uint8_t const options; + }; + + + // States::Direction_change + class Direction_change : public Base { + public: + Direction_change( + const char* title, + uint8_t options, + uint8_t* direction_cycles, + Base* continue_to = nullptr, + uint8_t* continue_after = nullptr, + uint8_t max_runtime = 10, + uint8_t* motor_speed = nullptr, + uint8_t* target_temp = nullptr); + void start(bool handle_heater = true); + Base* loop(); + const char* decrease_time(); + const char* increase_time(); + private: + void update_direction_change_time(); + uint8_t* const direction_cycles; + uint16_t direction_change_time; + uint16_t old_seconds; + uint16_t stop_seconds; + uint8_t remaining_cycles; }; @@ -73,10 +100,20 @@ namespace States { Warmup( const char* title, Base* continue_to, - uint8_t* continue_after, - uint8_t* motor_speed, uint8_t* target_temp); Base* loop(); + private: + uint8_t continue_after; + }; + + + // States::Cooldown + class Cooldown : public Base { + public: + Cooldown(Base* continue_to); + void start(bool handle_heater = true); + private: + uint8_t cooldown_time; }; @@ -84,7 +121,7 @@ namespace States { class Confirm : public Base { public: Confirm(bool force_wait); - void start(); + void start(bool handle_heater = true); Base* loop(); private: bool force_wait; @@ -92,6 +129,14 @@ namespace States { }; + // States::Reset + class Reset : public Base { + public: + Reset(); + void start(bool handle_heater = true); + }; + + // States::Test_switch class Test_switch : public Base { public: @@ -101,7 +146,7 @@ namespace States { const char* message_on, const char* message_off, bool (*value_getter)()); - void start(); + void start(bool handle_heater = true); Base* loop(); private: const char* const message_on; @@ -118,7 +163,7 @@ namespace States { Test_rotation( const char* title, Base* continue_to); - void start(); + void start(bool handle_heater = true); Base* loop(); bool get_info1(char* buffer, uint8_t size); private: @@ -136,7 +181,7 @@ namespace States { Test_fans( const char* title, Base* continue_to); - void start(); + void start(bool handle_heater = true); Base* loop(); bool get_info1(char* buffer, uint8_t size); bool get_info2(char* buffer, uint8_t size); @@ -155,29 +200,26 @@ namespace States { public: Test_uvled( const char* title, - uint8_t* fans_duties, - Base* to); - void start(); + Base* continue_to); + void start(bool handle_heater = true); Base* loop(); private: uint8_t test_time; - float old_uvled_temp; }; // States::Test_heater - class Test_heater : public Base, public SimplePrint { + class Test_heater : public Base { public: Test_heater( const char* title, - uint8_t* fans_duties, - Base* to); - void start(); + Base* continue_to); + void start(bool handle_heater = true); Base* loop(); bool get_info2(char* buffer, uint8_t size); private: uint8_t test_time; - float old_chamb_temp; + uint8_t temp; uint16_t old_seconds; bool draw; }; diff --git a/src/ui.cpp b/src/ui.cpp index 113982a..e55e114 100644 --- a/src/ui.cpp +++ b/src/ui.cpp @@ -9,6 +9,7 @@ namespace UI { /*** menu definitions ***/ Base back(pgmstr_back, BACK_CHAR); Base stop(pgmstr_stop, STOP_CHAR); + State error(pgmstr_emptystr, &States::error, nullptr); // move all following definitions to init() to save RAM instead of PROGMEM @@ -16,17 +17,20 @@ namespace UI { Minutes curing_run_time(pgmstr_curing_run_time, config.curing_run_time, MAX_CURING_RUNTIME); Minutes drying_run_time(pgmstr_drying_run_time, config.drying_run_time, MAX_DRYING_RUNTIME); Minutes washing_run_time(pgmstr_washing_run_time, config.washing_run_time, MAX_WASHING_RUNTIME); + Minutes filtering_run_time(pgmstr_filtering_run_time, config.filtering_run_time, MAX_FILTER_RUNTIME); Minutes resin_preheat_run_time(pgmstr_resin_preheat_time, config.resin_preheat_run_time, MAX_PREHEAT_RUNTIME); - Base* const run_time_items[] PROGMEM = {&back, &curing_run_time, &drying_run_time, &washing_run_time, &resin_preheat_run_time}; + Base* const run_time_items[] PROGMEM = {&back, &curing_run_time, &drying_run_time, &washing_run_time, &filtering_run_time, &resin_preheat_run_time}; Menu run_time_menu(pgmstr_run_time, run_time_items, COUNT_ITEMS(run_time_items)); - // speed menu + // rotation menu X_of_ten curing_speed(pgmstr_curing_speed, config.curing_speed); X_of_ten washing_speed(pgmstr_washing_speed, config.washing_speed); - Base* const speed_items[] PROGMEM = {&back, &curing_speed, &washing_speed}; - Menu speed_menu(pgmstr_rotation_speed, speed_items, COUNT_ITEMS(speed_items)); + X_of_ten wash_dir_changes(pgmstr_wash_dir_changes, config.wash_cycles); + X_of_ten filtering_speed(pgmstr_filtering_changes, config.filtering_speed); + Base* const speed_items[] PROGMEM = {&back, &curing_speed, &washing_speed, &wash_dir_changes, &filtering_speed}; + Menu speed_menu(pgmstr_rotation_settings, speed_items, COUNT_ITEMS(speed_items)); - // temperatore menu + // temperature menu Bool heat_to_target_temp(pgmstr_warmup, config.heat_to_target_temp); Temperature target_temp(pgmstr_drying_warmup_temp, config.target_temp); Temperature resin_target_temp(pgmstr_resin_preheat_temp, config.resin_target_temp); @@ -42,47 +46,7 @@ namespace UI { Base* const sound_items[] PROGMEM = {&back, &sound_response, &finish_beep}; Menu sound_menu(pgmstr_sound, sound_items, COUNT_ITEMS(sound_items)); - // fans curing speed - Percent fan1_curing_speed(pgmstr_fan1_curing_speed, config.fans_curing_speed[0], MIN_FAN_SPEED); - Percent fan2_curing_speed(pgmstr_fan2_curing_speed, config.fans_curing_speed[1], MIN_FAN_SPEED); - Base* const fans_curing_speed[] PROGMEM = {&back, &fan1_curing_speed, &fan2_curing_speed}; - Menu fans_curing_menu(pgmstr_fans_curing, fans_curing_speed, COUNT_ITEMS(fans_curing_speed)); - - // fans drying speed - Percent fan2_drying_speed(pgmstr_fan2_drying_speed, config.fans_drying_speed[1], MIN_FAN_SPEED); - #ifdef CW1S - Base* const fans_drying_speed[] PROGMEM = {&back, &fan2_drying_speed}; - #else - Percent fan1_drying_speed(pgmstr_fan1_drying_speed, config.fans_drying_speed[0], MIN_FAN_SPEED); - Base* const fans_drying_speed[] PROGMEM = {&back, &fan1_drying_speed, &fan2_drying_speed}; - #endif - Menu fans_drying_menu(pgmstr_fans_drying, fans_drying_speed, COUNT_ITEMS(fans_drying_speed)); - - // fans washing speed - Percent fan2_washing_speed(pgmstr_fan2_washing_speed, config.fans_washing_speed[1], MIN_FAN_SPEED); - #ifdef CW1S - Base* const fans_washing_speed[] PROGMEM = {&back, &fan2_washing_speed}; - #else - Percent fan1_washing_speed(pgmstr_fan1_washing_speed, config.fans_washing_speed[0], MIN_FAN_SPEED); - Base* const fans_washing_speed[] PROGMEM = {&back, &fan1_washing_speed, &fan2_washing_speed}; - #endif - Menu fans_washing_menu(pgmstr_fans_washing, fans_washing_speed, COUNT_ITEMS(fans_washing_speed)); - - // fans menu speed - Percent_with_action fan2_menu_speed(pgmstr_fan2_menu_speed, config.fans_menu_speed[1], MIN_FAN_SPEED, hw.set_fan2_duty); - #ifdef CW1S - Base* const fans_menu_speed[] PROGMEM = {&back, &fan2_menu_speed}; - #else - Percent_with_action fan1_menu_speed(pgmstr_fan1_menu_speed, config.fans_menu_speed[0], MIN_FAN_SPEED, hw.set_fan1_duty); - Base* const fans_menu_speed[] PROGMEM = {&back, &fan1_menu_speed, &fan2_menu_speed}; - #endif - Menu fans_menu_menu(pgmstr_fans_menu, fans_menu_speed, COUNT_ITEMS(fans_menu_speed)); - - // fans menu - Base* const fans_items[] PROGMEM = {&back, &fans_curing_menu, &fans_drying_menu, &fans_washing_menu, &fans_menu_menu}; - Menu fans_menu(pgmstr_fans, fans_items, COUNT_ITEMS(fans_items)); - - // info menu + // system info SN serial_number(pgmstr_sn); Text fw_version(pgmstr_fw_version); Text build_nr(pgmstr_build_nr); @@ -93,14 +57,13 @@ namespace UI { #else Base* const info_items[] PROGMEM = {&back, &serial_number, &fw_version, &build_nr, &fw_hash}; #endif - Menu info_menu(pgmstr_information, info_items, COUNT_ITEMS(info_items)); + Info system_info(pgmstr_information, info_items, COUNT_ITEMS(info_items)); // config menu const char* const curing_machine_mode_options[] PROGMEM = {pgmstr_drying_curing, pgmstr_curing, pgmstr_drying}; Option curing_machine_mode(pgmstr_run_mode, config.curing_machine_mode, curing_machine_mode_options, COUNT_ITEMS(curing_machine_mode_options)); - Percent led_intensity(pgmstr_led_intensity, config.led_intensity, MIN_LED_INTENSITY); Percent_with_action lcd_brightness(pgmstr_lcd_brightness, config.lcd_brightness, MIN_LCD_BRIGHTNESS, lcd.setBrightness); - Base* const config_items[] PROGMEM = {&back, &speed_menu, &curing_machine_mode, &temperature_menu, &sound_menu, &lcd_brightness, &info_menu}; + Base* const config_items[] PROGMEM = {&back, &speed_menu, &curing_machine_mode, &temperature_menu, &sound_menu, &lcd_brightness, &system_info}; Menu config_menu(pgmstr_settings, config_items, COUNT_ITEMS(config_items)); // run menu @@ -114,27 +77,21 @@ namespace UI { // home menu Do_it do_it(config.curing_machine_mode, &run_menu); + State filtering(pgmstr_filtering, &States::filtering, &run_menu); State resin_preheat(pgmstr_resin_preheat, &States::warmup_resin, &run_menu); - Base* const home_items[] PROGMEM = {&do_it, &resin_preheat, &run_time_menu, &hold_platform_menu, &config_menu}; + Base* const home_items[] PROGMEM = {&do_it, &filtering, &resin_preheat, &run_time_menu, &hold_platform_menu, &config_menu}; Menu home_menu(pgmstr_emptystr, home_items, COUNT_ITEMS(home_items)); - // hw menu - Live_value fan1_rpm(pgmstr_fan1_rpm, hw.fan_rpm[0]); - Live_value fan2_rpm(pgmstr_fan2_rpm, hw.fan_rpm[1]); - Live_value chamber_temp(pgmstr_chamber_temp, hw.chamber_temp); - Live_value uvled_temp(pgmstr_uvled_temp, hw.uvled_temp); - #ifdef CW1S - Base* const hw_items[] PROGMEM = {&back, &fan1_rpm, &fan2_rpm, &chamber_temp, &uvled_temp}; - #else - Live_value fan3_rpm(pgmstr_fan3_rpm, hw.fan_rpm[2]); - Base* const hw_items[] PROGMEM = {&back, &fan1_rpm, &fan2_rpm, &fan3_rpm, &chamber_temp, &uvled_temp}; - #endif - Menu_self_redraw hw_menu(pgmstr_emptystr, hw_items, COUNT_ITEMS(hw_items), MENU_REDRAW_US); + // factory reset confirm + State factory_reset(pgmstr_reset_confirm, &States::reset); + Base* const reset_items[] PROGMEM = {&back, &factory_reset}; + Menu reset(pgmstr_factory_reset, reset_items, COUNT_ITEMS(reset_items)); // advanced menu - State cooldown(pgmstr_cooldown, &States::cooldown, &hw_menu); + Percent led_intensity(pgmstr_led_intensity, config.led_intensity, MIN_LED_INTENSITY); + State cooldown(pgmstr_cooldown, &States::cooldown, nullptr); State selftest(pgmstr_selftest, &States::selftest_cover, nullptr); - Base* const advanced_items[] PROGMEM = {&back, &fans_menu, &led_intensity, &cooldown, &selftest}; + Base* const advanced_items[] PROGMEM = {&back, &led_intensity, &reset, &cooldown, &selftest}; Menu advanced_menu(pgmstr_emptystr, advanced_items, COUNT_ITEMS(advanced_items)); @@ -148,13 +105,23 @@ namespace UI { SI_changed[i]->init(config.SI_unit_system); } home_menu.set_long_press_ui_item(&curing_machine_mode); - info_menu.set_long_press_ui_item(&hw_menu); - run_menu.set_long_press_ui_item(&hw_menu); config_menu.set_long_press_ui_item(&advanced_menu); active_menu->invoke(); active_menu->show(); } + void set_menu(Base* new_menu) { + if (menu_depth < MAX_MENU_DEPTH) { + menu_stack[menu_depth++] = active_menu; + active_menu = new_menu; + lcd.clear(); + active_menu->invoke(); + active_menu->show(); + } else { + USB_PRINTLNP("ERROR: MAX_MENU_DEPTH reached!"); + } + } + void loop(uint8_t events) { active_menu->loop(); Base* new_menu = active_menu->process_events(events); @@ -170,15 +137,7 @@ namespace UI { USB_PRINTLNP("ERROR: back at menu depth 0!"); } } else if (new_menu) { - if (menu_depth < MAX_MENU_DEPTH) { - menu_stack[menu_depth++] = active_menu; - active_menu = new_menu; - lcd.clear(); - active_menu->invoke(); - active_menu->show(); - } else { - USB_PRINTLNP("ERROR: MAX_MENU_DEPTH reached!"); - } + set_menu(new_menu); } } diff --git a/src/ui.h b/src/ui.h index 0b6fadb..d7fa97b 100644 --- a/src/ui.h +++ b/src/ui.h @@ -4,7 +4,10 @@ namespace UI { + extern State error; + void init(); + void set_menu(Base* new_menu); void loop(uint8_t events); } diff --git a/src/ui_items.cpp b/src/ui_items.cpp index b23b5d8..b52bf60 100644 --- a/src/ui_items.cpp +++ b/src/ui_items.cpp @@ -3,12 +3,14 @@ #include "config.h" #include "ui_items.h" #include "states.h" +#include "device.h" namespace UI { // UI::Base Base::Base(const char* label, uint8_t last_char) : - label(label), last_char(last_char) + label(label), + last_char(last_char) {} char* Base::get_menu_label(char* buffer, uint8_t buffer_size) { @@ -71,31 +73,13 @@ namespace UI { } - // UI:Live_value - template - Live_value::Live_value(const char* label, T& value) : - Text(label), value(value) - {} - - template - char* Live_value::get_menu_label(char* buffer, uint8_t buffer_size) { - char* end = Base::get_menu_label(buffer, buffer_size); - int8_t size = buffer + buffer_size - end; - if (size < 0) { - size = 0; - } - buffer_init(end, size); - print(value); - return get_position(); - } - - template class Live_value; - template class Live_value; - - // UI::Menu Menu::Menu(const char* label, Base* const* items, uint8_t items_count) : - Base(label), items(items), long_press_ui_item(nullptr), items_count(items_count), menu_offset(0), cursor_position(0) + Base(label), + items(items), + long_press_ui_item(nullptr), + items_count(items_count), + menu_offset(0) { max_items = items_count < DISPLAY_LINES ? items_count : DISPLAY_LINES; } @@ -190,29 +174,80 @@ namespace UI { } - // UI::Menu_self_redraw - Menu_self_redraw::Menu_self_redraw(const char* label, Base* const* items, uint8_t items_count, uint16_t redraw_us) : - Menu(label, items, items_count), redraw_us(redraw_us), us_last(0) - {} + // UI::Info + Info::Info(const char* label, Base* const* items, uint8_t items_count, uint16_t redraw_us) : + Base(label), + items(items), + long_press_ui_item(nullptr), + items_count(items_count), + info_offset(0), + redraw_us(redraw_us), + us_last(0) + { + max_items = items_count - 1 < DISPLAY_LINES ? items_count - 1 : DISPLAY_LINES; + } - void Menu_self_redraw::show() { + void Info::loop() { + if (redraw_us) { + unsigned long us_now = millis(); + if (us_now - us_last > redraw_us) { + us_last = us_now; + show(); + } + } + Base::loop(); + } + + void Info::show() { us_last = millis(); - Menu::show(); + char buffer[DISPLAY_CHARS + 1]; + for (uint8_t i = 0; i < max_items; ++i) { + lcd.setCursor(0, i); + Base* item = (Base*)pgm_read_word(&(items[i + 1 + info_offset])); + item->get_menu_label(buffer, sizeof(buffer)); + lcd.print(buffer); + } + } + + void Info::invoke() { + info_offset = 0; + Base::invoke(); } - void Menu_self_redraw::loop() { - unsigned long us_now = millis(); - if (us_now - us_last > redraw_us) { - us_last = us_now; + Base* Info::process_events(uint8_t events) { + if (events & EVENT_CONTROL_UP) + event_control_up(); + if (events & EVENT_CONTROL_DOWN) + event_control_down(); + if (events & EVENT_BUTTON_SHORT_PRESS) + return (Base*)pgm_read_word(&(items[0])); + if (events & EVENT_BUTTON_LONG_PRESS) + return long_press_ui_item; + return nullptr; + } + + void Info::event_control_up() { + if (info_offset < items_count - 1 - DISPLAY_LINES) { + ++info_offset; + show(); + } + } + + void Info::event_control_down() { + if (info_offset) { + --info_offset; show(); } - Menu::loop(); } // UI::Value Value::Value(const char* label, uint8_t& value, const char* units, uint8_t max, uint8_t min) : - Base(label), units(units), value(value), max_value(max), min_value(min) + Base(label), + units(units), + value(value), + max_value(max), + min_value(min) {} void Value::show() { @@ -279,16 +314,17 @@ namespace UI { void Temperature::units_change(bool SI) { init(SI); if (SI) { - value = round(fahrenheit2celsius(value)); + value = round_short(fahrenheit2celsius(value)); } else { - value = round(celsius2fahrenheit(value)); + value = round_short(celsius2fahrenheit(value)); } } // UI::Percent_with_action Percent_with_action::Percent_with_action(const char* label, uint8_t& value, uint8_t min, void (*value_setter)(uint8_t)) : - Percent(label, value, min), value_setter(value_setter) + Percent(label, value, min), + value_setter(value_setter) {} void Percent_with_action::event_control_up() { @@ -304,7 +340,10 @@ namespace UI { // UI::Bool Bool::Bool(const char* label, uint8_t& value, const char* true_text, const char* false_text) : - Base(label, 0), true_text(true_text), false_text(false_text), value(value) + Base(label, 0), + true_text(true_text), + false_text(false_text), + value(value) {} char* Bool::get_menu_label(char* buffer, uint8_t buffer_size) { @@ -327,7 +366,9 @@ namespace UI { // UI::SI_switch SI_switch::SI_switch(const char* label, uint8_t& value, Temperature* const* to_change, uint8_t to_change_count) : - Bool(label, value, pgmstr_celsius_units, pgmstr_fahrenheit_units), to_change(to_change), to_change_count(to_change_count) + Bool(label, value, pgmstr_celsius_units, pgmstr_fahrenheit_units), + to_change(to_change), + to_change_count(to_change_count) {} Base* SI_switch::in_menu_action() { @@ -342,7 +383,10 @@ namespace UI { // UI::Option Option::Option(const char* label, uint8_t& value, const char* const* options, uint8_t options_count) : - Base(label), value(value), options(options), options_count(options_count) + Base(label), + value(value), + options(options), + options_count(options_count) { if (value > options_count) value = 0; @@ -400,8 +444,8 @@ namespace UI { old_title(nullptr), old_message(nullptr), old_time(UINT16_MAX), - spin_us_last(0), - bound_us_last(0), + spin_ms_last(0), + bound_ms_last(0), spin_count(0) {} @@ -409,8 +453,8 @@ namespace UI { old_title = nullptr; old_message = nullptr; old_time = UINT16_MAX; - spin_us_last = 0; - bound_us_last = 0; + spin_ms_last = 0; + bound_ms_last = 0; spin_count = 0; Base::show(); } @@ -430,22 +474,22 @@ namespace UI { lcd.print_P(tmp_str, 1, 2); } } else { - unsigned long us_now = millis(); + unsigned long ms_now = millis(); // spinner if (!States::active_state->is_paused()) { lcd.setCursor(19, 0); uint8_t c = pgm_read_byte(pgmstr_progress + spin_count); lcd.write(c); - if (us_now - spin_us_last > 100) { - spin_us_last = us_now; + if (ms_now - spin_ms_last > 100) { + spin_ms_last = ms_now; if (++spin_count >= sizeof(pgmstr_progress)) { spin_count = 0; } } } - if (bound_us_last && us_now - bound_us_last > 1000) { + if (bound_ms_last && ms_now - bound_ms_last > 1000) { clear_time_boundaries(); - bound_us_last = 0; + bound_ms_last = 0; } // time uint16_t time = States::active_state->get_time(); @@ -454,8 +498,12 @@ namespace UI { lcd.printTime(time, LAYOUT_TIME_X, LAYOUT_TIME_Y); // temperature float temp = States::active_state->get_temperature(); - if (temp > 0) { - lcd.print(temp, LAYOUT_INFO1_X, LAYOUT_INFO1_Y); + if (temp > -0.1) { + if (temp > 0.0) { + lcd.print(round_short(get_configured_temp(temp)), LAYOUT_INFO1_X, LAYOUT_INFO1_Y); + } else { + lcd.print_P(pgmstr_doubledash, LAYOUT_INFO1_X+1, LAYOUT_INFO1_Y); + } lcd.print_P(config.SI_unit_system ? pgmstr_celsius : pgmstr_fahrenheit); } } @@ -509,7 +557,7 @@ namespace UI { const char* symbol = States::active_state->increase_time(); if (symbol) { lcd.print_P(symbol, LAYOUT_TIME_GT, LAYOUT_TIME_Y); - bound_us_last = millis(); + bound_ms_last = millis(); } } } @@ -520,7 +568,7 @@ namespace UI { const char* symbol = States::active_state->decrease_time(); if (symbol) { lcd.print_P(symbol, LAYOUT_TIME_LT, LAYOUT_TIME_Y); - bound_us_last = millis(); + bound_ms_last = millis(); } } } @@ -533,7 +581,8 @@ namespace UI { // UI::Do_it Do_it::Do_it(uint8_t& curing_machine_mode, Base* state_menu) : - State(nullptr, nullptr, state_menu), curing_machine_mode(curing_machine_mode) + State(nullptr, nullptr, state_menu), + curing_machine_mode(curing_machine_mode) {} char* Do_it::get_menu_label(char* buffer, uint8_t buffer_size) { @@ -580,7 +629,8 @@ namespace UI { // UI::Pause Pause::Pause(Base* back) : - Base(pgmstr_emptystr), back(back) + Base(pgmstr_emptystr), + back(back) {} char* Pause::get_menu_label(char* buffer, uint8_t buffer_size) { diff --git a/src/ui_items.h b/src/ui_items.h index 677d56e..9b596f0 100644 --- a/src/ui_items.h +++ b/src/ui_items.h @@ -1,6 +1,5 @@ #pragma once -#include "hardware.h" #include "i18n.h" #include "states_items.h" #include "simple_print.h" @@ -40,17 +39,6 @@ namespace UI { }; - // UI:Live_value - template - class Live_value : public Text, public SimplePrint { - public: - Live_value(const char* label, T& value); - char* get_menu_label(char* buffer, uint8_t buffer_size); - private: - T& value; - }; - - // UI::Menu class Menu : public Base { public: @@ -81,13 +69,23 @@ namespace UI { }; - // UI::Menu_self_redraw - class Menu_self_redraw : public Menu { + // UI::Info + class Info : public Base { public: - Menu_self_redraw(const char* label, Base* const* items, uint8_t items_count, uint16_t redraw_us); + Info(const char* label, Base* const* items, uint8_t items_count, uint16_t redraw_us = 0); void show(); void loop(); + void invoke(); + Base* process_events(uint8_t events); + void set_long_press_ui_item(Base *ui_item); private: + void event_control_up(); + void event_control_down(); + Base* const* const items; + Base* long_press_ui_item; + uint8_t const items_count; + uint8_t info_offset; + uint8_t max_items; uint16_t redraw_us; unsigned long us_last; }; @@ -202,8 +200,8 @@ namespace UI { const char* old_title; const char* old_message; uint16_t old_time; - unsigned long spin_us_last; - unsigned long bound_us_last; + unsigned long spin_ms_last; + unsigned long bound_ms_last; uint8_t spin_count; }; diff --git a/src/wrappers.cpp b/src/wrappers.cpp new file mode 100644 index 0000000..ee4156b --- /dev/null +++ b/src/wrappers.cpp @@ -0,0 +1,14 @@ +#include "wrappers.h" +#include "device.h" + +bool is_cover_closed() { + return hw.is_cover_closed(); +} + +bool is_tank_inserted() { + return hw.is_tank_inserted(); +} + +extern "C" void __cxa_pure_virtual() { + USB_PRINTLNP("ERROR: pure virtual"); +} diff --git a/src/wrappers.h b/src/wrappers.h new file mode 100644 index 0000000..1325bca --- /dev/null +++ b/src/wrappers.h @@ -0,0 +1,6 @@ +#pragma once + +// static wrappers for UI +bool is_cover_closed(); +bool is_tank_inserted(); +extern "C" void __cxa_pure_virtual();