Merge remote-tracking branch 'upstream/MK3' into MK3_MK404

Fix merge
This commit is contained in:
3d-gussner 2021-03-17 18:33:54 +01:00
commit 0f771b1218
53 changed files with 8814 additions and 3262 deletions

View File

@ -231,33 +231,23 @@
* SD sorting uses static allocation (as set by SDSORT_LIMIT), allowing the
* compiler to calculate the worst-case usage and throw an error if the SRAM
* limit is exceeded.
*
* - SDSORT_USES_RAM provides faster sorting via a static directory buffer.
* - SDSORT_USES_STACK does the same, but uses a local stack-based buffer.
* - SDSORT_CACHE_NAMES will retain the sorted file listing in RAM. (Expensive!)
* - SDSORT_DYNAMIC_RAM only uses RAM when the SD menu is visible. (Use with caution!)
*/
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
// SD Card Sorting options
// In current firmware Prusa Firmware version,
// SDSORT_CACHE_NAMES and SDSORT_DYNAMIC_RAM is not supported and must be set to 0.
#ifdef SDCARD_SORT_ALPHA
#define SD_SORT_TIME 0
#define SD_SORT_ALPHA 1
#define SD_SORT_NONE 2
// #define SHELLSORT
// #define SORTING_DUMP
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
#define SDSORT_GCODE 0 // Allow turning sorting on/off with LCD and M34 g-code.
#define SDSORT_USES_RAM 0 // Pre-allocate a static array for faster pre-sorting.
#define SDSORT_USES_STACK 0 // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
#define SDSORT_CACHE_NAMES 0 // Keep sorted items in RAM longer for speedy performance. Most expensive option.
#define SDSORT_DYNAMIC_RAM 0 // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
#endif
#if defined(SDCARD_SORT_ALPHA)
#define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
#define HAS_FOLDER_SORTING (FOLDER_SORTING)
#endif
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.

View File

@ -173,19 +173,6 @@ void dcode_3()
#include "bootapp.h"
#if 0
#define FLASHSIZE 0x40000
#define RAMSIZE 0x2000
#define boot_src_addr (*((uint32_t*)(RAMSIZE - 16)))
#define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12)))
#define boot_copy_size (*((uint16_t*)(RAMSIZE - 8)))
#define boot_reserved (*((uint8_t*)(RAMSIZE - 6)))
#define boot_app_flags (*((uint8_t*)(RAMSIZE - 5)))
#define boot_app_magic (*((uint32_t*)(RAMSIZE - 4)))
#define BOOT_APP_FLG_ERASE 0x01
#define BOOT_APP_FLG_COPY 0x02
#define BOOT_APP_FLG_FLASH 0x04
extern float current_temperature_pinda;
extern float axis_steps_per_unit[NUM_AXIS];

View File

@ -766,31 +766,16 @@ static void factory_reset(char level)
#endif //FILAMENT_SENSOR
break;
case 3:{ // Level 3: erase everything, whole EEPROM will be set to 0xFF
lcd_puts_P(PSTR("Factory RESET"));
lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
uint16_t er_progress = 0;
lcd_set_cursor(3, 3);
lcd_space(6);
lcd_set_cursor(3, 3);
lcd_print(er_progress);
case 3:
menu_progressbar_init(EEPROM_TOP, PSTR("ERASING all data"));
// Erase EEPROM
for (uint16_t i = 0; i < 4096; i++) {
for (uint16_t i = 0; i < EEPROM_TOP; i++) {
eeprom_update_byte((uint8_t*)i, 0xFF);
if (i % 41 == 0) {
er_progress++;
lcd_set_cursor(3, 3);
lcd_space(6);
lcd_set_cursor(3, 3);
lcd_print(er_progress);
lcd_puts_P(PSTR("%"));
}
menu_progressbar_update(i);
}
menu_progressbar_finish();
softReset();
}break;
break;
#ifdef SNMM
@ -2436,38 +2421,44 @@ void refresh_cmd_timeout(void)
}
#ifdef FWRETRACT
void retract(bool retracting, bool swapretract = false) {
void retract(bool retracting, bool swapretract = false) {
// Perform FW retraction, just if needed, but behave as if the move has never took place in
// order to keep E/Z coordinates unchanged. This is done by manipulating the internal planner
// position, which requires a sync
if(retracting && !retracted[active_extruder]) {
destination[X_AXIS]=current_position[X_AXIS];
destination[Y_AXIS]=current_position[Y_AXIS];
destination[Z_AXIS]=current_position[Z_AXIS];
destination[E_AXIS]=current_position[E_AXIS];
st_synchronize();
set_destination_to_current();
current_position[E_AXIS]+=(swapretract?retract_length_swap:cs.retract_length)*float(extrudemultiply)*0.01f;
plan_set_e_position(current_position[E_AXIS]);
float oldFeedrate = feedrate;
feedrate=cs.retract_feedrate*60;
retracted[active_extruder]=true;
prepare_move();
if(cs.retract_zlift) {
st_synchronize();
current_position[Z_AXIS]-=cs.retract_zlift;
plan_set_position_curposXYZE();
prepare_move();
}
feedrate = oldFeedrate;
} else if(!retracting && retracted[active_extruder]) {
destination[X_AXIS]=current_position[X_AXIS];
destination[Y_AXIS]=current_position[Y_AXIS];
destination[Z_AXIS]=current_position[Z_AXIS];
destination[E_AXIS]=current_position[E_AXIS];
current_position[Z_AXIS]+=cs.retract_zlift;
plan_set_position_curposXYZE();
current_position[E_AXIS]-=(swapretract?(retract_length_swap+retract_recover_length_swap):(cs.retract_length+cs.retract_recover_length))*float(extrudemultiply)*0.01f;
plan_set_e_position(current_position[E_AXIS]);
st_synchronize();
set_destination_to_current();
float oldFeedrate = feedrate;
feedrate=cs.retract_recover_feedrate*60;
if(cs.retract_zlift) {
current_position[Z_AXIS]+=cs.retract_zlift;
plan_set_position_curposXYZE();
prepare_move();
st_synchronize();
}
current_position[E_AXIS]-=(swapretract?(retract_length_swap+retract_recover_length_swap):(cs.retract_length+cs.retract_recover_length))*float(extrudemultiply)*0.01f;
plan_set_e_position(current_position[E_AXIS]);
retracted[active_extruder]=false;
prepare_move();
feedrate = oldFeedrate;
}
} //retract
} //retract
#endif //FWRETRACT
void trace() {
@ -4382,21 +4373,22 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
if (total_filament_used > ((current_position[E_AXIS] - destination[E_AXIS]) * 100)) { //protection against total_filament_used overflow
total_filament_used = total_filament_used + ((destination[E_AXIS] - current_position[E_AXIS]) * 100);
}
#ifdef FWRETRACT
if(cs.autoretract_enabled)
#ifdef FWRETRACT
if(cs.autoretract_enabled) {
if( !(code_seen('X') || code_seen('Y') || code_seen('Z')) && code_seen('E')) {
float echange=destination[E_AXIS]-current_position[E_AXIS];
if((echange<-MIN_RETRACT && !retracted[active_extruder]) || (echange>MIN_RETRACT && retracted[active_extruder])) { //move appears to be an attempt to retract or recover
st_synchronize();
current_position[E_AXIS] = destination[E_AXIS]; //hide the slicer-generated retract/recover from calculations
plan_set_e_position(current_position[E_AXIS]); //AND from the planner
retract(!retracted[active_extruder]);
return;
}
}
#endif //FWRETRACT
}
#endif //FWRETRACT
prepare_move();
//ClearToSend();
}
@ -4464,9 +4456,9 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
lcd_update(0);
}
break;
#ifdef FWRETRACT
#ifdef FWRETRACT
/*!
### G10 - Retract <a href="https://reprap.org/wiki/G-code#G10:_Retract">G10: Retract</a>
Retracts filament according to settings of `M207`
@ -4492,7 +4484,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
retract(false);
#endif
break;
#endif //FWRETRACT
#endif //FWRETRACT
/*!
@ -7317,8 +7309,9 @@ Sigma_Exit:
if(code_seen(axis_codes[i])) cs.add_homing[i] = code_value();
}
break;
#ifdef FWRETRACT
#ifdef FWRETRACT
/*!
### M207 - Set firmware retraction <a href="https://reprap.org/wiki/G-code#M207:_Set_retract_length">M207: Set retract length</a>
#### Usage
@ -7416,7 +7409,9 @@ Sigma_Exit:
}
}break;
#endif // FWRETRACT
#endif // FWRETRACT
#if EXTRUDERS > 1
/*!
@ -11262,7 +11257,7 @@ void restore_print_from_eeprom(bool mbl_was_active) {
}
dir_name[8] = '\0';
MYSERIAL.println(dir_name);
// strcpy(dir_names[i], dir_name);
// strcpy(card.dir_names[i], dir_name);
card.chdir(dir_name, false);
}

View File

@ -28,15 +28,6 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
boot_app_magic = BOOT_APP_MAGIC;
boot_app_flags |= BOOT_APP_FLG_COPY;
boot_app_flags |= BOOT_APP_FLG_ERASE;
/* uint16_t ui; for (ui = 0; ui < size; ui++)
{
uint8_t uc = ram_array[ui+rptr];
if (pgm_read_byte(ui+fptr) & uc != uc)
{
boot_app_flags |= BOOT_APP_FLG_ERASE;
break;
}
}*/
boot_copy_size = (uint16_t)size;
boot_src_addr = (uint32_t)rptr;
boot_dst_addr = (uint32_t)fptr;

View File

@ -7,7 +7,6 @@
#define RAMSIZE 0x2000
#define ram_array ((uint8_t*)(0))
#define boot_src_addr (*((uint32_t*)(RAMSIZE - 16)))
#define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12)))
#define boot_copy_size (*((uint16_t*)(RAMSIZE - 8)))

View File

@ -15,11 +15,6 @@ CardReader::CardReader()
#ifdef SDCARD_SORT_ALPHA
sort_count = 0;
#if SDSORT_GCODE
sort_alpha = true;
sort_folders = FOLDER_SORTING;
//sort_reverse = false;
#endif
#endif
filesize = 0;
@ -82,7 +77,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
dir_t p;
uint8_t cnt = 0;
// Read the next entry from a directory
while (parent.readDir(p, longFilename) > 0) {
for (position = parent.curPosition(); parent.readDir(p, longFilename) > 0; position = parent.curPosition()) {
if (recursionCnt > MAX_DIR_DEPTH)
return;
else if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) { // If the entry is a directory and the action is LS_SerialPrint
@ -151,8 +146,8 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
case LS_GetFilename:
//SERIAL_ECHOPGM("File: ");
createFilename(filename, p);
cluster = parent.curCluster();
position = parent.curPosition();
// cluster = parent.curCluster();
// position = parent.curPosition();
/*MYSERIAL.println(filename);
SERIAL_ECHOPGM("Write date: ");
writeDate = p.lastWriteDate;
@ -397,7 +392,7 @@ static const char ofNowFreshFile[] PROGMEM = "Now fresh file: ";
static const char ofFileOpened[] PROGMEM = "File opened: ";
static const char ofSize[] PROGMEM = " Size: ";
static const char ofFileSelected[] PROGMEM = "File selected";
static const char ofSDPrinting[] PROGMEM = "SD-PRINTING ";
static const char ofSDPrinting[] PROGMEM = "SD-PRINTING";
static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
@ -446,17 +441,17 @@ void CardReader::openFileReadFilteredGcode(const char* name, bool replace_curren
return;
if (file.openFilteredGcode(curDir, fname)) {
getfilename(0, fname);
filesize = file.fileSize();
SERIAL_PROTOCOLRPGM(ofFileOpened);////MSG_SD_FILE_OPENED
SERIAL_PROTOCOL(fname);
printAbsFilenameFast();
SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
SERIAL_PROTOCOLLN(filesize);
sdpos = 0;
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
getfilename(0, fname);
lcd_setstatus(longFilename[0] ? longFilename : fname);
lcd_setstatuspgm(ofSDPrinting);
lcd_setstatuspgm(ofFileSelected);
scrollstuff = 0;
} else {
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(fname);
@ -517,9 +512,14 @@ void CardReader::openFileWrite(const char* name)
SERIAL_PROTOCOLLN('.');
} else {
saving = true;
getfilename(0, fname);
SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
SERIAL_PROTOCOLLN(fname);
lcd_setstatus(fname);
printAbsFilenameFast();
SERIAL_PROTOCOLLN();
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
lcd_setstatuspgm(ofFileSelected);
scrollstuff = 0;
}
}
@ -711,6 +711,15 @@ void CardReader::getfilename_simple(uint32_t position, const char * const match/
lsDive("", *curDir, match);
}
void CardReader::getfilename_next(uint32_t position, const char * const match/*=NULL*/)
{
curDir = &workDir;
lsAction = LS_GetFilename;
nrFiles = 1;
curDir->seekSet(position);
lsDive("", *curDir, match);
}
uint16_t CardReader::getnrfilenames()
{
curDir=&workDir;
@ -780,13 +789,11 @@ void CardReader::updir()
/**
* Get the name of a file in the current directory by sort-index
*/
void CardReader::getfilename_sorted(const uint16_t nr) {
getfilename(
#if SDSORT_GCODE
sort_alpha &&
#endif
(nr < sort_count) ? sort_order[nr] : nr
);
void CardReader::getfilename_sorted(const uint16_t nr, uint8_t sdSort) {
if (nr < sort_count)
getfilename_simple(sort_positions[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
else
getfilename(nr);
}
/**
@ -803,9 +810,6 @@ void CardReader::presort() {
if (sdSort == SD_SORT_NONE) return; //sd sort is turned off
#if SDSORT_GCODE
if (!sort_alpha) return;
#endif
KEEPALIVE_STATE(IN_HANDLER);
// Throw away old sort index
@ -821,177 +825,170 @@ void CardReader::presort() {
lcd_show_fullscreen_message_and_wait_P(_i("Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."));////MSG_FILE_CNT c=20 r=6
fileCnt = SDSORT_LIMIT;
}
lcd_clear();
#if !SDSORT_USES_RAM
lcd_set_progress();
#endif
lcd_puts_at_P(0, 1, _i("Sorting files"));////MSG_SORTING c=20 r=1
// Sort order is always needed. May be static or dynamic.
#if SDSORT_DYNAMIC_RAM
sort_order = new uint8_t[fileCnt];
#endif
// Use RAM to store the entire directory during pre-sort.
// SDSORT_LIMIT should be set to prevent over-allocation.
#if SDSORT_USES_RAM
// If using dynamic ram for names, allocate on the heap.
#if SDSORT_CACHE_NAMES
#if SDSORT_DYNAMIC_RAM
sortshort = new char*[fileCnt];
sortnames = new char*[fileCnt];
#endif
#elif SDSORT_USES_STACK
char sortnames[fileCnt][LONG_FILENAME_LENGTH];
uint16_t modification_time[fileCnt];
uint16_t modification_date[fileCnt];
#endif
// Folder sorting needs 1 bit per entry for flags.
#if HAS_FOLDER_SORTING
#if SDSORT_DYNAMIC_RAM
isDir = new uint8_t[(fileCnt + 7) >> 3];
#elif SDSORT_USES_STACK
uint8_t isDir[(fileCnt + 7) >> 3];
#endif
#endif
#else // !SDSORT_USES_RAM
uint32_t positions[fileCnt];
// By default re-read the names from SD for every compare
// retaining only two filenames at a time. This is very
// slow but is safest and uses minimal RAM.
char name1[LONG_FILENAME_LENGTH + 1];
char name1[LONG_FILENAME_LENGTH];
uint16_t crmod_time_bckp;
uint16_t crmod_date_bckp;
#if HAS_FOLDER_SORTING
uint16_t dirCnt = 0;
#endif
position = 0;
if (fileCnt > 1) {
// Init sort order.
uint8_t sort_order[fileCnt];
for (uint16_t i = 0; i < fileCnt; i++) {
if (!IS_SD_INSERTED) return;
manage_heater();
if (i == 0)
getfilename(0);
else
getfilename_next(position);
sort_order[i] = i;
positions[i] = position;
getfilename(i);
// If using RAM then read all filenames now.
#if SDSORT_USES_RAM
getfilename(i);
#if SDSORT_DYNAMIC_RAM
// Use dynamic method to copy long filename
sortnames[i] = strdup(LONGEST_FILENAME);
#if SDSORT_CACHE_NAMES
// When caching also store the short name, since
// we're replacing the getfilename() behavior.
sortshort[i] = strdup(filename);
#endif
#else
// Copy filenames into the static array
strcpy(sortnames[i], LONGEST_FILENAME);
modification_time[i] = crmodTime;
modification_date[i] = crmodDate;
#if SDSORT_CACHE_NAMES
strcpy(sortshort[i], filename);
#endif
#endif
// char out[30];
// sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
// SERIAL_ECHOLN(out);
sort_positions[i] = position;
#if HAS_FOLDER_SORTING
const uint16_t bit = i & 0x07, ind = i >> 3;
if (bit == 0) isDir[ind] = 0x00;
if (filenameIsDir) isDir[ind] |= _BV(bit);
#endif
if (filenameIsDir) dirCnt++;
#endif
}
#ifdef QUICKSORT
quicksort(0, fileCnt - 1);
#else //Qicksort not defined, use Bubble Sort
uint32_t counter = 0;
uint16_t total = 0.5*(fileCnt - 1)*(fileCnt);
#elif defined(SHELLSORT)
// Compare names from the array or just the two buffered names
#if SDSORT_USES_RAM
#define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
#define _SORT_CMP_TIME_NODIR() (((modification_date[o1] == modification_date[o2]) && (modification_time[o1] < modification_time[o2])) || \
(modification_date[o1] < modification_date [o2]))
#else
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0) //true if lowercase(name1) > lowercase(name2)
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || \
(crmod_date_bckp > crmodDate))
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) < 0) //true if lowercase(name1) < lowercase(name2)
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp < crmodTime)) || (crmod_date_bckp < crmodDate))
#endif
#if HAS_FOLDER_SORTING
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs < 0 ? dir1 : !dir1))
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
#endif
#if HAS_FOLDER_SORTING
#if SDSORT_USES_RAM
// Folder sorting needs an index and bit to test for folder-ness.
const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
ind2 = o2 >> 3, bit2 = o2 & 0x07;
#define _SORT_CMP_DIR(fs) \
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
? _SORT_CMP_NODIR() \
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
#define _SORT_CMP_TIME_DIR(fs) \
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
? _SORT_CMP_TIME_NODIR() \
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
#else
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
#endif
#endif
for (uint16_t i = fileCnt; --i;) {
if (!IS_SD_INSERTED) return;
bool didSwap = false;
#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
int8_t percent = (counter * 100) / total;//((counter * 100) / pow((fileCnt-1),2));
for (int column = 0; column < 20; column++) {
if (column < (percent / 5))
for (uint8_t runs = 0; runs < 2; runs++)
{
lcd_putc_at(column, 2, '\x01'); //simple progress bar
//run=0: sorts all files and moves folders to the beginning
//run=1: assumes all folders are at the beginning of the list and sorts them
uint16_t sortCountFiles = 0;
if (runs == 0)
{
sortCountFiles = fileCnt;
}
#if HAS_FOLDER_SORTING
else
{
sortCountFiles = dirCnt;
}
counter++;
#endif
//MYSERIAL.println(int(i));
for (uint16_t j = 0; j < i; ++j) {
if (!IS_SD_INSERTED) return;
manage_heater();
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
uint16_t counter = 0;
uint16_t total = 0;
for (uint16_t i = sortCountFiles/2; i > 0; i /= 2) total += sortCountFiles - i; //total runs for progress bar
menu_progressbar_init(total, (runs == 0)?_i("Sorting files"):_i("Sorting folders"));
// The most economical method reads names as-needed
// throughout the loop. Slow if there are many.
#if !SDSORT_USES_RAM
for (uint16_t gap = sortCountFiles/2; gap > 0; gap /= 2)
{
for (uint16_t i = gap; i < sortCountFiles; i++)
{
if (!IS_SD_INSERTED) return;
menu_progressbar_update(counter);
counter++;
getfilename_simple(positions[o1]);
manage_heater();
uint8_t orderBckp = sort_order[i];
getfilename_simple(sort_positions[orderBckp]);
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
crmod_date_bckp = crmodDate;
crmod_time_bckp = crmodTime;
#if HAS_FOLDER_SORTING
bool dir1 = filenameIsDir;
#endif
getfilename_simple(positions[o2]);
char *name2 = LONGEST_FILENAME; // use the string in-place
#endif // !SDSORT_USES_RAM
uint16_t j = i;
getfilename_simple(sort_positions[sort_order[j - gap]]);
char *name2 = LONGEST_FILENAME; // use the string in-place
#if HAS_FOLDER_SORTING
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_DIR(FOLDER_SORTING):_SORT_CMP_DIR(FOLDER_SORTING)))
#else
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_NODIR():_SORT_CMP_NODIR()))
#endif
{
sort_order[j] = sort_order[j - gap];
j -= gap;
#ifdef SORTING_DUMP
for (uint16_t z = 0; z < sortCountFiles; z++)
{
printf_P(PSTR("%2u "), sort_order[z]);
}
printf_P(PSTR("i%2d j%2d gap%2d orderBckp%2d\n"), i, j, gap, orderBckp);
#endif
if (j < gap) break;
getfilename_simple(sort_positions[sort_order[j - gap]]);
name2 = LONGEST_FILENAME; // use the string in-place
}
sort_order[j] = orderBckp;
}
}
}
#else //Bubble Sort
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) < 0) //true if lowercase(name1) < lowercase(name2)
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || (crmod_date_bckp > crmodDate))
#if HAS_FOLDER_SORTING
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs < 0 ? dir1 : !dir1))
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
#endif
uint16_t counter = 0;
menu_progressbar_init(0.5*(fileCnt - 1)*(fileCnt), _i("Sorting files"));
for (uint16_t i = fileCnt; --i;) {
if (!IS_SD_INSERTED) return;
bool didSwap = false;
menu_progressbar_update(counter);
counter++;
for (uint16_t j = 0; j < i; ++j) {
if (!IS_SD_INSERTED) return;
#ifdef SORTING_DUMP
for (uint16_t z = 0; z < fileCnt; z++)
{
printf_P(PSTR("%2u "), sort_order[z]);
}
MYSERIAL.println();
#endif
manage_heater();
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
counter++;
getfilename_simple(sort_positions[o1]);
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
crmod_date_bckp = crmodDate;
crmod_time_bckp = crmodTime;
#if HAS_FOLDER_SORTING
bool dir1 = filenameIsDir;
#endif
getfilename_simple(sort_positions[o2]);
char *name2 = LONGEST_FILENAME; // use the string in-place
// Sort the current pair according to settings.
if (
#if HAS_FOLDER_SORTING
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_DIR(FOLDER_SORTING))
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_DIR(FOLDER_SORTING))
#else
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_NODIR())
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_NODIR())
#endif
)
{
#ifdef SORTING_DUMP
puts_P(PSTR("swap"));
#endif
sort_order[j] = o2;
sort_order[j + 1] = o1;
didSwap = true;
@ -1000,45 +997,45 @@ void CardReader::presort() {
if (!didSwap) break;
} //end of bubble sort loop
#endif
// Using RAM but not keeping names around
#if (SDSORT_USES_RAM && !SDSORT_CACHE_NAMES)
#if SDSORT_DYNAMIC_RAM
for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
#if HAS_FOLDER_SORTING
free(isDir);
#endif
#endif
#ifdef SORTING_DUMP
for (uint16_t z = 0; z < fileCnt; z++)
printf_P(PSTR("%2u "), sort_order[z]);
SERIAL_PROTOCOLLN();
#endif
uint8_t sort_order_reverse_index[fileCnt];
for (uint8_t i = 0; i < fileCnt; i++)
sort_order_reverse_index[sort_order[i]] = i;
for (uint8_t i = 0; i < fileCnt; i++)
{
if (sort_order_reverse_index[i] != i)
{
uint32_t el = sort_positions[i];
uint8_t idx = sort_order_reverse_index[i];
while (idx != i)
{
uint32_t el1 = sort_positions[idx];
uint8_t idx1 = sort_order_reverse_index[idx];
sort_order_reverse_index[idx] = idx;
sort_positions[idx] = el;
idx = idx1;
el = el1;
}
sort_order_reverse_index[idx] = idx;
sort_positions[idx] = el;
}
}
menu_progressbar_finish();
}
else {
sort_order[0] = 0;
#if (SDSORT_USES_RAM && SDSORT_CACHE_NAMES)
getfilename(0);
#if SDSORT_DYNAMIC_RAM
sortnames = new char*[1];
sortnames[0] = strdup(LONGEST_FILENAME); // malloc
sortshort = new char*[1];
sortshort[0] = strdup(filename); // malloc
isDir = new uint8_t[1];
#else
strcpy(sortnames[0], LONGEST_FILENAME);
strcpy(sortshort[0], filename);
#endif
isDir[0] = filenameIsDir ? 0x01 : 0x00;
#endif
sort_positions[0] = position;
}
sort_count = fileCnt;
}
#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
for (int column = 0; column <= 19; column++)
{
lcd_putc_at(column, 2, '\x01'); //simple progress bar
}
_delay(300);
lcd_set_degree();
lcd_clear();
#endif
lcd_update(2);
KEEPALIVE_STATE(NOT_BUSY);
lcd_timeoutToStatus.start();
@ -1046,17 +1043,6 @@ void CardReader::presort() {
void CardReader::flush_presort() {
if (sort_count > 0) {
#if SDSORT_DYNAMIC_RAM
delete sort_order;
#if SDSORT_CACHE_NAMES
for (uint8_t i = 0; i < sort_count; ++i) {
free(sortshort[i]); // strdup
free(sortnames[i]); // strdup
}
delete sortshort;
delete sortnames;
#endif
#endif
sort_count = 0;
}
}

View File

@ -34,6 +34,7 @@ public:
void getfilename(uint16_t nr, const char* const match=NULL);
void getfilename_simple(uint32_t position, const char * const match = NULL);
void getfilename_next(uint32_t position, const char * const match = NULL);
uint16_t getnrfilenames();
void getAbsFilename(char *t);
@ -53,12 +54,7 @@ public:
void swap(uint8_t left, uint8_t right);
void quicksort(uint8_t left, uint8_t right);
#endif //SDSORT_QUICKSORT
void getfilename_sorted(const uint16_t nr);
#if SDSORT_GCODE
FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
#endif
void getfilename_sorted(const uint16_t nr, uint8_t sdSort);
#endif
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
@ -84,7 +80,7 @@ public:
// There are scenarios when simple modification time is not enough (on MS Windows)
// Therefore these timestamps hold the most recent one of creation/modification date/times
uint16_t crmodTime, crmodDate;
uint32_t cluster, position;
uint32_t /* cluster, */ position;
char longFilename[LONG_FILENAME_LENGTH];
bool filenameIsDir;
int lastnr; //last number of the autostart;
@ -99,45 +95,7 @@ private:
// Sort files and folders alphabetically.
#ifdef SDCARD_SORT_ALPHA
uint16_t sort_count; // Count of sorted items in the current directory
#if SDSORT_GCODE
bool sort_alpha; // Flag to enable / disable the feature
int sort_folders; // Flag to enable / disable folder sorting
//bool sort_reverse; // Flag to enable / disable reverse sorting
#endif
// By default the sort index is static
#if SDSORT_DYNAMIC_RAM
uint8_t *sort_order;
#else
uint8_t sort_order[SDSORT_LIMIT];
#endif
// Cache filenames to speed up SD menus.
#if SDSORT_USES_RAM
// If using dynamic ram for names, allocate on the heap.
#if SDSORT_CACHE_NAMES
#if SDSORT_DYNAMIC_RAM
char **sortshort, **sortnames;
#else
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
#endif
#elif !SDSORT_USES_STACK
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
uint16_t modification_time[SDSORT_LIMIT];
uint16_t modification_date[SDSORT_LIMIT];
#endif
// Folder sorting uses an isDir array when caching items.
#if HAS_FOLDER_SORTING
#if SDSORT_DYNAMIC_RAM
uint8_t *isDir;
#elif (SDSORT_CACHE_NAMES) || !(SDSORT_USES_STACK)
uint8_t isDir[(SDSORT_LIMIT + 7) >> 3];
#endif
#endif
#endif // SDSORT_USES_RAM
uint32_t sort_positions[SDSORT_LIMIT];
#endif // SDCARD_SORT_ALPHA

View File

@ -371,12 +371,6 @@ void repeatcommand_front()
cmdbuffer_front_already_processed = true;
}
bool is_buffer_empty()
{
if (buflen == 0) return true;
else return false;
}
void proc_commands() {
if (buflen)
{

View File

@ -69,7 +69,6 @@ extern bool cmd_buffer_empty();
extern void enquecommand(const char *cmd, bool from_progmem = false);
extern void enquecommand_front(const char *cmd, bool from_progmem = false);
extern void repeatcommand_front();
extern bool is_buffer_empty();
extern void get_command();
extern uint16_t cmdqueue_calc_sd_length();

View File

@ -68,5 +68,12 @@
#define LANG_SIZE_RESERVED 0x3000 // reserved space for secondary language (12288 bytes)
//Community language support
#define COMMUNITY_LANG_NL // Community Dutch language
//#define COMMUNITY_LANG_QR // Community new language //..use this as a template and replace 'QR'
#if defined(COMMUNITY_LANG_NL) //|| defined(COMMUNITY_LANG_QR) //..use last part as a template and replace 'QR'
#define COMMUNITY_LANG_SUPPORT
#endif
#endif //_CONFIG_H

View File

@ -53,6 +53,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
- __L__ Language
- __S__ Statistics
- __P__ Shipping prep
- __M__ Service/Maintenance prep
- __S/P__ Statistics and Shipping prep
will overwrite existing values to 0 or default.
@ -157,6 +158,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
| 0x0F60h 3936 | float | EEPROM_XYZ_CAL_SKEW | ??? | ff ff ff ffh | XYZ skew value | ??? | D3 Ax0f60 C4
| 0x0F5Fh 3935 | uint8 | EEPROM_WIZARD_ACTIVE | 01h 1 | 01h 1 __P__ | Wizard __active__ | ??? | D3 Ax0f5f C1
| ^ | ^ | ^ | 00h 0 | ^ | Wizard __inactive__ | ^ | ^
| ^ | ^ | ^ | 02h 2 | 02h 2 __M__ | Wizard active - Z cal after shipping/service prep | ^ | ^
| 0x0F5Dh 3933 | uint16 | EEPROM_BELTSTATUS_X | ??? | ff ffh | X Beltstatus | ??? | D3 Ax0f5d C2
| 0x0F5Bh 3931 | uint16 | EEPROM_BELTSTATUS_Y | ??? | ff ffh | Y Beltstatus | ??? | D3 Ax0f5b C2
| 0x0F5Ah 3930 | uint8 | EEPROM_DIR_DEPTH | 00h-ffh 0-255 | ffh 255 | Directory depth | ??? | D3 Ax0f5a C1

View File

@ -210,6 +210,16 @@ const char* lang_get_name_by_code(uint16_t code)
case LANG_CODE_FR: return _n("Francais");
case LANG_CODE_IT: return _n("Italiano");
case LANG_CODE_PL: return _n("Polski");
#ifdef COMMUNITY_LANG_SUPPORT //Community language support
#ifdef COMMUNITY_LANG_NL
case LANG_CODE_NL: return _n("Nederlands"); //community contribution
#endif // COMMUNITY_LANG_NL
//Use the 3 lines below as a template and replace 'QR' and 'New language'
//#ifdef COMMUNITY_LANG_QR
// case LANG_CODE_QR: return _n("New language"); //community contribution
//#endif // COMMUNITY_LANG_QR
#endif // COMMUNITY_LANG_SUPPORT
}
return _n("??");
}

View File

@ -96,6 +96,15 @@ typedef struct
#define LANG_CODE_FR 0x6672 //!<'fr'
#define LANG_CODE_IT 0x6974 //!<'it'
#define LANG_CODE_PL 0x706c //!<'pl'
#ifdef COMMUNITY_LANG_SUPPORT //Community language support
#ifdef COMMUNITY_LANG_NL
#define LANG_CODE_NL 0x6e6c //!<'nl'
#endif // COMMUNITY_LANG_NL
//Use the 3 lines below as a template and replace 'QR', '0X7172' and 'qr'
//#ifdef COMMUNITY_LANG_QR
//#define LANG_CODE_QR 0x7172 //!<'qr'
//#endif // COMMUNITY_LANG_QR
#endif // COMMUNITY_LANG_SUPPORT
///@}
#if defined(__cplusplus)

View File

@ -963,21 +963,6 @@ void lcd_set_custom_characters_arrows(void)
lcd_createChar_P(1, lcd_chardata_arrdown);
}
const uint8_t lcd_chardata_progress[8] PROGMEM = {
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111,
B11111};
void lcd_set_custom_characters_progress(void)
{
lcd_createChar_P(1, lcd_chardata_progress);
}
const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
B00000,
B00000,

View File

@ -204,7 +204,6 @@ private:
extern void lcd_set_custom_characters(void);
extern void lcd_set_custom_characters_arrows(void);
extern void lcd_set_custom_characters_progress(void);
extern void lcd_set_custom_characters_nextpage(void);
extern void lcd_set_custom_characters_degree(void);

View File

@ -34,33 +34,35 @@ uint8_t menu_top = 0;
uint8_t menu_clicked = 0;
uint8_t menu_entering = 0;
uint8_t menu_leaving = 0;
menu_func_t menu_menu = 0;
static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doesn't fit into menu_data");
void menu_data_reset(void)
{
// Resets the global shared C union.
// This ensures, that the menu entered will find out, that it shall initialize itself.
memset(&menu_data, 0, sizeof(menu_data));
}
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
{
asm("cli");
CRITICAL_SECTION_START;
if (menu_menu != menu)
{
menu_menu = menu;
lcd_encoder = encoder;
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
asm("sei");
CRITICAL_SECTION_END;
if (reset_menu_state)
{
// Resets the global shared C union.
// This ensures, that the menu entered will find out, that it shall initialize itself.
memset(&menu_data, 0, sizeof(menu_data));
}
menu_data_reset();
if (feedback) lcd_quick_feedback();
}
else
asm("sei");
CRITICAL_SECTION_END;
}
void menu_start(void)
@ -551,4 +553,33 @@ uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_v
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
template uint8_t menu_item_edit_P<uint8_t*>(const char* str, uint8_t *pval, int16_t min_val, int16_t max_val);
#undef _menu_data
static uint8_t progressbar_block_count = 0;
static uint16_t progressbar_total = 0;
void menu_progressbar_init(uint16_t total, const char* title)
{
lcd_clear();
progressbar_block_count = 0;
progressbar_total = total;
lcd_set_cursor(0, 1);
lcd_printf_P(PSTR("%-20.20S\n"), title);
}
void menu_progressbar_update(uint16_t newVal)
{
uint8_t newCnt = (newVal * LCD_WIDTH) / progressbar_total;
if (newCnt > LCD_WIDTH)
newCnt = LCD_WIDTH;
while (newCnt > progressbar_block_count)
{
lcd_print('\xFF');
progressbar_block_count++;
}
}
void menu_progressbar_finish(void)
{
progressbar_total = 1;
menu_progressbar_update(1);
_delay(300);
}

View File

@ -59,13 +59,12 @@ extern uint8_t menu_top;
extern uint8_t menu_clicked;
extern uint8_t menu_entering;
extern uint8_t menu_leaving;
//function pointer to the currently active menu
extern menu_func_t menu_menu;
extern void menu_data_reset(void);
extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
@ -151,5 +150,8 @@ extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
template <typename T>
extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val);
extern void menu_progressbar_init(uint16_t total, const char* title);
extern void menu_progressbar_update(uint16_t newVal);
extern void menu_progressbar_finish(void);
#endif //_MENU_H

View File

@ -21,6 +21,7 @@ const char MSG_CALIBRATE_Z_AUTO[] PROGMEM_I1 = ISTR("Calibrating Z"); ////c=20 r
const char MSG_CARD_MENU[] PROGMEM_I1 = ISTR("Print from SD"); ////
const char MSG_CHECKING_X[] PROGMEM_I1 = ISTR("Checking X axis"); ////c=20
const char MSG_CHECKING_Y[] PROGMEM_I1 = ISTR("Checking Y axis"); ////c=20
const char MSG_COMMUNITY_MADE[] PROGMEM_I1 = ISTR("Community made"); ////c=18
const char MSG_CONFIRM_NOZZLE_CLEAN[] PROGMEM_I1 = ISTR("Please clean the nozzle for calibration. Click when done."); ////c=20 r=8
const char MSG_COOLDOWN[] PROGMEM_I1 = ISTR("Cooldown"); ////
const char MSG_CRASH[] PROGMEM_I1 = ISTR("Crash"); ////c=7
@ -79,7 +80,7 @@ const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unl
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\xF8" "Refresh"); ////
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\x04" "Refresh"); ////
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
const char MSG_RESET[] PROGMEM_I1 = ISTR("Reset"); ////c=14
const char MSG_RESUME_PRINT[] PROGMEM_I1 = ISTR("Resume print"); ////c=18
@ -202,4 +203,3 @@ const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
const char MSG_FILE_SELECTED[] PROGMEM_N1 = "File selected"; ////c=20

View File

@ -22,6 +22,7 @@ extern const char MSG_CALIBRATE_Z_AUTO[];
extern const char MSG_CARD_MENU[];
extern const char MSG_CHECKING_X[];
extern const char MSG_CHECKING_Y[];
extern const char MSG_COMMUNITY_MADE[];
extern const char MSG_CONFIRM_NOZZLE_CLEAN[];
extern const char MSG_COOLDOWN[];
extern const char MSG_CRASH[];
@ -202,7 +203,6 @@ extern const char MSG_M112_KILL[];
extern const char MSG_ADVANCE_K[];
extern const char MSG_POWERPANIC_DETECTED[];
extern const char MSG_LCD_STATUS_CHANGED[];
extern const char MSG_FILE_SELECTED[];
#if defined(__cplusplus)
}

View File

@ -15,19 +15,6 @@
static unsigned const int __attribute__((section(".version")))
optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
/* Watchdog settings */
#define WATCHDOG_OFF (0)
#define WATCHDOG_16MS (_BV(WDE))
#define WATCHDOG_32MS (_BV(WDP0) | _BV(WDE))
#define WATCHDOG_64MS (_BV(WDP1) | _BV(WDE))
#define WATCHDOG_125MS (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_250MS (_BV(WDP2) | _BV(WDE))
#define WATCHDOG_500MS (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_1S (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
#define WATCHDOG_2S (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
#define WATCHDOG_4S (_BV(WDP3) | _BV(WDE))
#define WATCHDOG_8S (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
#if 0
#define W25X20CL_SIGNATURE_0 9
#define W25X20CL_SIGNATURE_1 8
@ -39,13 +26,6 @@ static unsigned const int __attribute__((section(".version")))
#define W25X20CL_SIGNATURE_2 0x01
#endif
static void watchdogConfig(uint8_t x) {
CRITICAL_SECTION_START
WDTCSR = _BV(WDCE) | _BV(WDE);
WDTCSR = x;
CRITICAL_SECTION_END
}
#define RECV_READY ((UCSR0A & _BV(RXC0)) != 0)
static uint8_t getch(void) {
@ -74,7 +54,7 @@ static void putch(char ch) {
static void verifySpace() {
if (getch() != CRC_EOP) {
putch(STK_FAILED);
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
wdt_enable(WDTO_15MS); // shorten WD timeout
while (1) // and busy-loop so that WD causes
; // a reset and app start.
}
@ -100,7 +80,10 @@ extern struct block_t *block_buffer;
//! @return 0 if "start\n" was sent. Optiboot ran normally. No need to send "start\n" in setup()
uint8_t optiboot_w25x20cl_enter()
{
if (boot_app_flags & BOOT_APP_FLG_USER0) return 1;
// Make sure to check boot_app_magic as well. Since these bootapp flags are located right in the middle of the stack,
// they can be unintentionally changed. As a workaround to the language upload problem, do not only check for one bit if it's set,
// but rather test 33 bits for the correct value before exiting optiboot early.
if ((boot_app_magic == BOOT_APP_MAGIC) && (boot_app_flags & BOOT_APP_FLG_USER0)) return 1;
uint8_t ch;
uint8_t rampz = 0;
register uint16_t address = 0;
@ -115,8 +98,6 @@ uint8_t optiboot_w25x20cl_enter()
// If the magic is not received on time, or it is not received correctly, continue to the application.
{
wdt_reset();
unsigned long boot_timeout = 2000000;
unsigned long boot_timer = 0;
const char *ptr = entry_magic_send;
const char *end = strlen_P(entry_magic_send) + ptr;
const uint8_t selectedSerialPort_bak = selectedSerialPort;
@ -138,11 +119,17 @@ uint8_t optiboot_w25x20cl_enter()
ptr = entry_magic_receive;
end = strlen_P(entry_magic_receive) + ptr;
while (ptr != end) {
while (rx_buffer.head == SerialHead) {
unsigned long boot_timer = 2000000;
// Beware of this volatile pointer - it is important since the while-cycle below
// doesn't contain any obvious references to rx_buffer.head
// thus the compiler is allowed to remove the check from the cycle
// i.e. rx_buffer.head == SerialHead would not be checked at all!
// With the volatile keyword the compiler generates exactly the same code as without it with only one difference:
// the last brne instruction jumps onto the (*rx_head == SerialHead) check and NOT onto the wdr instruction bypassing the check.
volatile int *rx_head = &rx_buffer.head;
while (*rx_head == SerialHead) {
wdt_reset();
delayMicroseconds(1);
if (++ boot_timer > boot_timeout)
{
if ( --boot_timer == 0) {
// Timeout expired, continue with the application.
selectedSerialPort = selectedSerialPort_bak; //revert Serial setting
return 0;
@ -161,13 +148,14 @@ uint8_t optiboot_w25x20cl_enter()
cbi(UCSR0B, RXCIE0); //disable the MarlinSerial0 interrupt
// Send the cfm magic string.
ptr = entry_magic_cfm;
end = strlen_P(entry_magic_cfm) + ptr;
while (ptr != end)
putch(pgm_read_byte(ptr ++));
}
spi_init();
w25x20cl_init();
watchdogConfig(WATCHDOG_OFF);
wdt_disable();
/* Forever loop: exits by causing WDT reset */
for (;;) {
@ -306,7 +294,7 @@ uint8_t optiboot_w25x20cl_enter()
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
// Adaboot no-wait mod
watchdogConfig(WATCHDOG_16MS);
wdt_enable(WDTO_15MS);
verifySpace();
}
else {

View File

@ -55,8 +55,6 @@
#endif
int scrollstuff = 0;
char longFilenameOLD[LONG_FILENAME_LENGTH];
int clock_interval = 0;
static void lcd_sd_updir();
@ -64,7 +62,7 @@ static void lcd_mesh_bed_leveling_settings();
static void lcd_backlight_menu();
int8_t ReInitLCD = 0;
uint8_t scrollstuff = 0;
int8_t SilentModeMenu = SILENT_MODE_OFF;
uint8_t SilentModeMenu_MMU = 1; //activate mmu unit stealth mode
@ -326,113 +324,31 @@ bool bSettings; // flag (i.e. 'fake parameter'
const char STR_SEPARATOR[] PROGMEM = "------------";
static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* filename, char* longFilename)
{
char c;
int enc_dif = lcd_encoder_diff / ENCODER_PULSES_PER_STEP;
uint8_t n = LCD_WIDTH - 1;
for(uint_least8_t g = 0; g<4;g++){
lcd_putc_at(0, g, ' ');
}
lcd_putc_at(0, row, '>');
if (longFilename[0] == '\0')
{
longFilename = filename;
}
int i = 1;
int j = 0;
char* longFilenameTMP = longFilename;
while((c = *longFilenameTMP) != '\0')
{
lcd_set_cursor(i, row);
lcd_print(c);
i++;
longFilenameTMP++;
if(i==LCD_WIDTH){
i=1;
j++;
longFilenameTMP = longFilename + j;
n = LCD_WIDTH - 1;
for(int g = 0; g<300 ;g++){
manage_heater();
if(LCD_CLICKED || ( enc_dif != (lcd_encoder_diff / ENCODER_PULSES_PER_STEP))){
longFilenameTMP = longFilename;
*(longFilenameTMP + LCD_WIDTH - 2) = '\0';
i = 1;
j = 0;
break;
}else{
if (j == 1) _delay_ms(3); //wait around 1.2 s to start scrolling text
_delay_ms(1); //then scroll with redrawing every 300 ms
}
}
}
}
if(c!='\0'){
lcd_putc_at(i, row, c);
i++;
}
n=n-i+1;
lcd_space(n);
}
static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* filename, char* longFilename)
static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 1;
lcd_putc_at(0, row, ' ');
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-1] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
lcd_set_cursor(0, row);
lcd_print((lcd_encoder == menu_item)?'>':' ');
while( ((c = *longFilename) != '\0') && (n>0) )
{
lcd_print(c);
filename++;
longFilename++;
n--;
}
lcd_space(n);
}
static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* filename, char* longFilename)
static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 2;
lcd_putc_at(0, row, '>');
lcd_set_cursor(0, row);
lcd_print((lcd_encoder == menu_item)?'>':' ');
lcd_print(LCD_STR_FOLDER[0]);
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-2] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
while( ((c = *longFilename) != '\0') && (n>0) )
{
lcd_print(c);
filename++;
n--;
}
lcd_space(n);
}
static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* filename, char* longFilename)
{
char c;
uint8_t n = LCD_WIDTH - 2;
lcd_putc_at(0, row, ' ');
lcd_print(LCD_STR_FOLDER[0]);
if (longFilename[0] != '\0')
{
filename = longFilename;
longFilename[LCD_WIDTH-2] = '\0';
}
while( ((c = *filename) != '\0') && (n>0) )
{
lcd_print(c);
filename++;
longFilename++;
n--;
}
lcd_space(n);
@ -441,48 +357,16 @@ static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* fil
#define MENU_ITEM_SDDIR(str_fn, str_fnl) do { if (menu_item_sddir(str_fn, str_fnl)) return; } while (0)
//#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
//extern uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl);
#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) do { if (menu_item_sdfile(str, str_fn, str_fnl)) return; } while (0)
//#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) MENU_ITEM(sdfile, str, str_fn, str_fnl)
//extern uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl);
#define MENU_ITEM_SDFILE(str_fn, str_fnl) do { if (menu_item_sdfile(str_fn, str_fnl)) return; } while (0)
uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
{
#ifdef NEW_SD_MENU
// str_fnl[18] = 0;
// printf_P(PSTR("menu dir %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
if (menu_item == menu_line)
{
if (lcd_draw_update)
{
lcd_set_cursor(0, menu_row);
int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fnl[0]?str_fnl:str_fn);
// int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fn);
}
if (menu_clicked && (lcd_encoder == menu_item))
{
uint8_t depth = (uint8_t)card.getWorkDirDepth();
strcpy(dir_names[depth], str_fn);
// printf_P(PSTR("%s\n"), dir_names[depth]);
card.chdir(str_fn);
lcd_encoder = 0;
return menu_item_ret();
}
}
menu_item++;
return 0;
#else //NEW_SD_MENU
if (menu_item == menu_line)
{
if (lcd_draw_update)
{
if (lcd_encoder == menu_item)
lcd_implementation_drawmenu_sddirectory_selected(menu_row, str_fn, str_fnl);
else
lcd_implementation_drawmenu_sddirectory(menu_row, str_fn, str_fnl);
lcd_implementation_drawmenu_sddirectory(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
}
if (menu_clicked && (lcd_encoder == menu_item))
{
@ -490,80 +374,32 @@ uint8_t menu_item_sddir(const char* str_fn, char* str_fnl)
lcd_update_enabled = 0;
menu_action_sddirectory(str_fn);
lcd_update_enabled = 1;
return menu_item_ret();
/* return */ menu_item_ret();
return 1;
}
}
menu_item++;
return 0;
#endif //NEW_SD_MENU
}
static uint8_t menu_item_sdfile(const char*
#ifdef NEW_SD_MENU
str
#endif //NEW_SD_MENU
,const char* str_fn, char* str_fnl)
static uint8_t menu_item_sdfile(const char* str_fn, char* str_fnl)
{
#ifdef NEW_SD_MENU
// printf_P(PSTR("menu sdfile\n"));
// str_fnl[19] = 0;
// printf_P(PSTR("menu file %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
if (menu_item == menu_line)
{
if (lcd_draw_update)
{
// printf_P(PSTR("menu file %d %d '%s'\n"), menu_row, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
lcd_set_cursor(0, menu_row);
/* if (lcd_encoder == menu_item)
{
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
if (menuData.sdcard_menu.viewState == 0)
{
menuData.sdcard_menu.viewState++;
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
}
else if (menuData.sdcard_menu.viewState == 1)
{
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 2);
}
}
else*/
{
str_fnl[19] = 0;
lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl[0]?str_fnl:str_fn);
}
// int cnt = lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl);
// int cnt = lcd_printf_P(PSTR("%cTESTIK.gcode"), (lcd_encoder == menu_item)?'>':' ');
}
if (menu_clicked && (lcd_encoder == menu_item))
{
return menu_item_ret();
}
}
menu_item++;
return 0;
#else //NEW_SD_MENU
if (menu_item == menu_line)
{
if (lcd_draw_update)
{
if (lcd_encoder == menu_item)
lcd_implementation_drawmenu_sdfile_selected(menu_row, str_fn, str_fnl);
else
lcd_implementation_drawmenu_sdfile(menu_row, str_fn, str_fnl);
lcd_implementation_drawmenu_sdfile(menu_row, (str_fnl[0] == '\0') ? str_fn : str_fnl);
}
if (menu_clicked && (lcd_encoder == menu_item))
{
lcd_consume_click();
menu_action_sdfile(str_fn);
return menu_item_ret();
/* return */ menu_item_ret();
return 1;
}
}
menu_item++;
return 0;
#endif //NEW_SD_MENU
}
// Print temperature (nozzle/bed) (9 chars total)
@ -735,14 +571,6 @@ void lcdui_print_time(void)
//! @Brief Print status line on status screen
void lcdui_print_status_line(void)
{
if (IS_SD_PRINTING) {
if (strcmp(longFilenameOLD, (card.longFilename[0] ? card.longFilename : card.filename)) != 0) {
memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
sprintf_P(longFilenameOLD, PSTR("%s"), (card.longFilename[0] ? card.longFilename : card.filename));
scrollstuff = 0;
}
}
if (heating_status) { // If heating flag, show progress of heating
heating_status_counter++;
if (heating_status_counter > 13) {
@ -776,6 +604,7 @@ void lcdui_print_status_line(void)
}
}
else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status)) { // If printing from SD, show what we are printing
const char* longFilenameOLD = (card.longFilename[0] ? card.longFilename : card.filename);
if(strlen(longFilenameOLD) > LCD_WIDTH) {
int inters = 0;
int gh = scrollstuff;
@ -4196,7 +4025,7 @@ static void prusa_stat_printinfo()
SERIAL_ECHOPGM("][FEM:");
SERIAL_ECHO(itostr3(feedmultiply));
SERIAL_ECHOPGM("][FNM:");
SERIAL_ECHO(longFilenameOLD);
SERIAL_ECHO(card.longFilename[0] ? card.longFilename : card.filename);
SERIAL_ECHOPGM("][TIM:");
if (starttime != 0)
{
@ -4511,17 +4340,10 @@ static void lcd_fsensor_state_set()
}
#endif //FILAMENT_SENSOR
#if !SDSORT_USES_RAM
void lcd_set_degree() {
lcd_set_custom_characters_degree();
}
void lcd_set_progress() {
lcd_set_custom_characters_progress();
}
#endif
#if (LANG_MODE != 0)
void menu_setlang(unsigned char lang)
@ -4538,6 +4360,26 @@ void menu_setlang(unsigned char lang)
}
}
#ifdef COMMUNITY_LANG_SUPPORT
#ifdef W25X20CL
static void lcd_community_language_menu()
{
MENU_BEGIN();
uint8_t cnt = lang_get_count();
MENU_ITEM_BACK_P(_i("Select language")); //Back to previous Menu
for (int i = 8; i < cnt; i++) //all community languages
if (menu_item_text_P(lang_get_name_by_code(lang_get_code(i))))
{
menu_setlang(i);
return;
}
MENU_END();
}
#endif //W25X20CL
#endif //COMMUNITY_LANG_SUPPORT && W52X20CL
static void lcd_language_menu()
{
MENU_BEGIN();
@ -4558,7 +4400,7 @@ static void lcd_language_menu()
}
}
else
for (int i = 2; i < cnt; i++) //skip seconday language - solved in lang_select (MK3)
for (int i = 2; i < 8; i++) //skip seconday language - solved in lang_select (MK3) 'i < 8' for 7 official languages
#else //W25X20CL
for (int i = 1; i < cnt; i++) //all seconday languages (MK2/25)
#endif //W25X20CL
@ -4567,6 +4409,13 @@ static void lcd_language_menu()
menu_setlang(i);
return;
}
#ifdef COMMUNITY_LANG_SUPPORT
#ifdef W25X20CL
MENU_ITEM_SUBMENU_P(_T(MSG_COMMUNITY_MADE), lcd_community_language_menu); ////MSG_COMMUNITY_MADE c=18
#endif //W25X20CL
#endif //COMMUNITY_LANG_SUPPORT && W52X20CL
MENU_END();
}
#endif //(LANG_MODE != 0)
@ -4984,10 +4833,10 @@ void lcd_wizard(WizState state)
saved_printing = false;
if( eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE)==2){
lcd_show_fullscreen_message_and_wait_P(MSG_WIZARD_WELCOME_SHIPPING);
lcd_show_fullscreen_message_and_wait_P(_T(MSG_WIZARD_WELCOME_SHIPPING));
state = S::Restore;
} else {
wizard_event = lcd_show_multiscreen_message_yes_no_and_wait_P(MSG_WIZARD_WELCOME, false, true);
wizard_event = lcd_show_multiscreen_message_yes_no_and_wait_P(_T(MSG_WIZARD_WELCOME), false, true);
if (wizard_event) {
state = S::Restore;
eeprom_update_byte((uint8_t*)EEPROM_WIZARD_ACTIVE, 1);
@ -7139,17 +6988,25 @@ static void lcd_control_temperature_menu()
}
#if SDCARDDETECT == -1
static void lcd_sd_refresh()
{
#if SDCARDDETECT == -1
card.initsd();
menu_top = 0;
}
#else
card.presort();
#endif
menu_top = 0;
lcd_encoder = 0;
menu_data_reset(); //Forces reloading of cached variables.
}
static void lcd_sd_updir()
{
card.updir();
menu_top = 0;
lcd_encoder = 0;
menu_data_reset(); //Forces reloading of cached variables.
}
void lcd_print_stop()
@ -7245,17 +7102,58 @@ void lcd_sdcard_stop()
void lcd_sdcard_menu()
{
uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
enum menuState_t : uint8_t {_uninitialized, _standard, _scrolling};
typedef struct
{
menuState_t menuState = _uninitialized;
uint8_t offset;
bool isDir;
const char* scrollPointer;
uint16_t selectedFileID;
uint16_t fileCnt;
int8_t row;
uint8_t sdSort;
ShortTimer lcd_scrollTimer;
} _menu_data_sdcard_t;
static_assert(sizeof(menu_data)>= sizeof(_menu_data_sdcard_t),"_menu_data_sdcard_t doesn't fit into menu_data");
_menu_data_sdcard_t* _md = (_menu_data_sdcard_t*)&(menu_data[0]);
if (card.presort_flag == true) {
switch(_md->menuState)
{
case _uninitialized: //Initialize menu data
{
if (card.presort_flag == true) //used to force resorting if sorting type is changed.
{
card.presort_flag = false;
card.presort();
}
if (lcd_draw_update == 0 && LCD_CLICKED == 0)
//_delay(100);
_md->fileCnt = card.getnrfilenames();
_md->sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
_md->menuState = _standard;
// FALLTHRU
}
case _standard: //normal menu structure.
{
if (!_md->lcd_scrollTimer.running()) //if the timer is not running, then the menu state was just switched, so redraw the screen.
{
_md->lcd_scrollTimer.start();
lcd_draw_update = 1;
}
if (_md->lcd_scrollTimer.expired(500) && (_md->row != -1)) //switch to the scrolling state on timeout if a file/dir is selected.
{
_md->menuState = _scrolling;
_md->offset = 0;
_md->scrollPointer = NULL;
_md->lcd_scrollTimer.start();
lcd_draw_update = 1; //forces last load before switching to scrolling.
}
if (lcd_draw_update == 0 && !LCD_CLICKED)
return; // nothing to do (so don't thrash the SD card)
uint16_t fileCnt = card.getnrfilenames();
_md->row = -1; // assume that no SD file/dir is currently selected. Once they are rendered, it will be changed to the correct row for the _scrolling state.
//if we reached this point it means that the encoder moved or clicked or the state is being switched. Reset the scrollTimer.
_md->lcd_scrollTimer.start();
MENU_BEGIN();
MENU_ITEM_BACK_P(_T(bMain?MSG_MAIN:MSG_BACK)); // i.e. default menu-item / menu-item after card insertion
@ -7264,38 +7162,96 @@ void lcd_sdcard_menu()
{
#if SDCARDDETECT == -1
MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
#else
if (card.ToshibaFlashAir_isEnabled())
MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh); //show the refresh option if in flashAir mode.
#endif
} else {
MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
}
else
MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir); //Show the updir button if in a subdir.
for (uint16_t i = 0; i < fileCnt; i++)
for (uint16_t i = _md->fileCnt; i-- > 0;) // Every file, from top to bottom.
{
if (menu_item == menu_line)
if (menu_item == menu_line) //If the file is on the screen.
{
//load filename to memory.
#ifdef SDCARD_SORT_ALPHA
if (_md->sdSort == SD_SORT_NONE)
card.getfilename(i);
else
card.getfilename_sorted(i, _md->sdSort);
#else
card.getfilename(i);
#endif
if (lcd_encoder == menu_item) //If the file is selected.
{
const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (fileCnt - 1 - i) : i;
/*#ifdef SDCARD_RATHERRECENTFIRST
#ifndef SDCARD_SORT_ALPHA
fileCnt - 1 -
#endif
#endif
i;*/
#ifdef SDCARD_SORT_ALPHA
if (sdSort == SD_SORT_NONE) card.getfilename(nr);
else card.getfilename_sorted(nr);
#else
card.getfilename(nr);
#endif
_md->selectedFileID = i;
_md->isDir = card.filenameIsDir;
_md->row = menu_row;
}
if (card.filenameIsDir)
MENU_ITEM_SDDIR(card.filename, card.longFilename);
else
MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
} else {
MENU_ITEM_DUMMY();
MENU_ITEM_SDFILE(card.filename, card.longFilename);
}
else MENU_ITEM_DUMMY(); //dummy item that just increments the internal menu counters.
}
MENU_END();
} break;
case _scrolling: //scrolling filename
{
const bool rewindFlag = LCD_CLICKED || lcd_draw_update; //flag that says whether the menu should return to _standard state.
if (_md->scrollPointer == NULL)
{
//load filename to memory.
#ifdef SDCARD_SORT_ALPHA
if (_md->sdSort == SD_SORT_NONE)
card.getfilename(_md->selectedFileID);
else
card.getfilename_sorted(_md->selectedFileID, _md->sdSort);
#else
card.getfilename(_md->selectedFileID);
#endif
_md->scrollPointer = (card.longFilename[0] == '\0') ? card.filename : card.longFilename;
}
if (rewindFlag == 1)
_md->offset = 0; //redraw once again from the beginning.
if (_md->lcd_scrollTimer.expired(300) || rewindFlag)
{
uint8_t i = LCD_WIDTH - ((_md->isDir)?2:1);
lcd_set_cursor(0, _md->row);
lcd_print('>');
if (_md->isDir)
lcd_print(LCD_STR_FOLDER[0]);
for (; i != 0; i--)
{
const char* c = (_md->scrollPointer + _md->offset + ((LCD_WIDTH - ((_md->isDir)?2:1)) - i));
lcd_print(c[0]);
if (c[1])
_md->lcd_scrollTimer.start();
else
{
_md->lcd_scrollTimer.stop();
break; //stop at the end of the string
}
}
if (i != 0) //adds spaces if string is incomplete or at the end (instead of null).
{
lcd_space(i);
}
_md->offset++;
}
if (rewindFlag) //go back to sd_menu.
{
_md->lcd_scrollTimer.stop(); //forces redraw in _standard state
_md->menuState = _standard;
}
} break;
default: _md->menuState = _uninitialized; //shouldn't ever happen. Anyways, initialize the menu.
}
}
#ifdef TMC2130
static void lcd_belttest_v()
@ -8550,7 +8506,6 @@ static bool check_file(const char* filename) {
const uint32_t filesize = card.getFileSize();
uint32_t startPos = 0;
const uint16_t bytesToCheck = min(END_FILE_SECTION, filesize);
uint8_t blocksPrinted = 0;
if (filesize > END_FILE_SECTION) {
startPos = filesize - END_FILE_SECTION;
card.setIndex(startPos);
@ -8558,22 +8513,15 @@ static bool check_file(const char* filename) {
cmdqueue_reset();
cmdqueue_serial_disabled = true;
lcd_clear();
lcd_puts_at_P(0, 1, _i("Checking file"));////c=20 r=1
lcd_set_cursor(0, 2);
menu_progressbar_init(bytesToCheck, _i("Checking file"));
while (!card.eof() && !result) {
for (; blocksPrinted < (((card.get_sdpos() - startPos) * LCD_WIDTH) / bytesToCheck); blocksPrinted++)
lcd_print('\xFF'); //simple progress bar
menu_progressbar_update(card.get_sdpos() - startPos);
card.sdprinting = true;
get_command();
result = check_commands();
}
for (; blocksPrinted < LCD_WIDTH; blocksPrinted++)
lcd_print('\xFF'); //simple progress bar
_delay(100); //for the user to see the end of the progress bar.
menu_progressbar_finish();
cmdqueue_serial_disabled = false;
card.printingHasFinished();
@ -8632,6 +8580,7 @@ void menu_action_sddirectory(const char* filename)
{
card.chdir(filename, true);
lcd_encoder = 0;
menu_data_reset(); //Forces reloading of cached variables.
}
/** LCD API **/
@ -8696,7 +8645,6 @@ static void lcd_connect_printer() {
int i = 0;
int t = 0;
lcd_set_custom_characters_progress();
lcd_puts_at_P(0, 0, _i("Connect printer to"));
lcd_puts_at_P(0, 1, _i("monitoring or hold"));
lcd_puts_at_P(0, 2, _i("the knob to continue"));
@ -8713,12 +8661,11 @@ static void lcd_connect_printer() {
i = 0;
lcd_puts_at_P(0, 3, PSTR(" "));
}
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\x01");
if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\xFF");
if (i == NC_BUTTON_LONG_PRESS * 10) {
no_response = false;
}
}
lcd_set_custom_characters_degree();
lcd_update_enable(true);
lcd_update(2);
}
@ -8726,7 +8673,7 @@ static void lcd_connect_printer() {
void lcd_ping() { //chceck if printer is connected to monitoring when in farm mode
if (farm_mode) {
bool empty = is_buffer_empty();
bool empty = cmd_buffer_empty();
if ((_millis() - PingTime) * 0.001 > (empty ? PING_TIME : PING_TIME_LONG)) { //if commands buffer is empty use shorter time period
//if there are comamnds in buffer, some long gcodes can delay execution of ping command
//therefore longer period is used

View File

@ -155,6 +155,8 @@ extern uint8_t SilentModeMenu_MMU;
extern bool cancel_heatup;
extern bool isPrintPaused;
extern uint8_t scrollstuff;
void lcd_ignore_click(bool b=true);
void lcd_commands();
@ -228,10 +230,7 @@ void lcd_temp_calibration_set();
void display_loading();
#if !SDSORT_USES_RAM
void lcd_set_degree();
void lcd_set_progress();
#endif
#if (LANG_MODE != 0)
void lcd_language();

View File

@ -699,26 +699,24 @@ uint8_t xyzcal_find_pattern_12x12_in_32x32(uint8_t* pixels, uint16_t* pattern, u
const uint16_t xyzcal_point_pattern_10[12] PROGMEM = {0x000, 0x0f0, 0x1f8, 0x3fc, 0x7fe, 0x7fe, 0x7fe, 0x7fe, 0x3fc, 0x1f8, 0x0f0, 0x000};
const uint16_t xyzcal_point_pattern_08[12] PROGMEM = {0x000, 0x000, 0x0f0, 0x1f8, 0x3fc, 0x3fc, 0x3fc, 0x3fc, 0x1f8, 0x0f0, 0x000, 0x000};
bool xyzcal_searchZ(void)
{
bool xyzcal_searchZ(void) {
//@size=118
DBG(_n("xyzcal_searchZ x=%ld y=%ld z=%ld\n"), count_position[X_AXIS], count_position[Y_AXIS], count_position[Z_AXIS]);
int16_t x0 = _X;
int16_t y0 = _Y;
int16_t z0 = _Z;
int16_t z = _Z;
// int16_t min_z = -6000;
// int16_t dz = 100;
int16_t z = z0;
while (z > -2300) //-6mm + 0.25mm
{
while (z > -2300) { //-6mm + 0.25mm
uint16_t ad = 0;
if (xyzcal_spiral8(x0, y0, z, 100, 900, 320, 1, &ad)) //dz=100 radius=900 delay=400
{
int16_t x_on = _X;
int16_t y_on = _Y;
int16_t z_on = _Z;
if (xyzcal_spiral8(x0, y0, z, 100, 900, 320, 1, &ad)) { //dz=100 radius=900 delay=400
//@size=82
DBG(_n(" ON-SIGNAL at x=%d y=%d z=%d ad=%d\n"), x_on, y_on, z_on, ad);
DBG(_n(" ON-SIGNAL at x=%d y=%d z=%d ad=%d\n"), _X, _Y, _Z, ad);
/// return to starting XY position
/// magic constant, lowers min_z after searchZ to obtain more dense data in scan
const pos_i16_t lower_z = 72;
xyzcal_lineXYZ_to(x0, y0, _Z - lower_z, 200, 0);
return true;
}
z -= 400;
@ -972,14 +970,10 @@ bool xyzcal_find_bed_induction_sensor_point_xy(void){
//@size=258
DBG(_n("xyzcal_find_bed_induction_sensor_point_xy x=%ld y=%ld z=%ld\n"), count_position[X_AXIS], count_position[Y_AXIS], count_position[Z_AXIS]);
st_synchronize();
///< magic constant, lowers min_z after searchZ to obtain more dense data in scan
const pos_i16_t lower_z = 72;
xyzcal_meassure_enter();
if (xyzcal_searchZ()){
xyzcal_lineXYZ_to(_X, _Y, _Z - lower_z, 200, 0);
if (xyzcal_searchZ())
ret = xyzcal_scan_and_process();
}
xyzcal_meassure_leave();
return ret;
}

View File

@ -139,6 +139,7 @@
# 12 Feb 2021, 3d-gussner, Add MK404-build.sh
# 13 Feb 2021, 3d-gussner, Indentations
# 13 Feb 2021, 3d-gussner, MK404 improvements like "flash" MK3, MK3S languages files to MK404 xflash.
# 27 Feb 2021, 3d-gussner, Add './lang-community.sh' and update exits
#### Start check if OSTYPE is supported
OS_FOUND=$( command -v uname)
@ -240,7 +241,7 @@ if ! type gawk > /dev/null; then
echo "$(tput setaf 1)Missing 'gawk' which is important to run this script"
echo "install it with the command $(tput setaf 2)'sudo apt-get install gawk'."
#sudo apt-get update && apt-get install gawk
exit 4
exit 5
fi
fi
@ -281,10 +282,10 @@ echo ""
#Check if build exists and creates it if not
if [ ! -d "../PF-build-dl" ]; then
mkdir ../PF-build-dl || exit 5
mkdir ../PF-build-dl || exit 6
fi
cd ../PF-build-dl || exit 6
cd ../PF-build-dl || exit 7
BUILD_ENV_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
# Check if PF-build-env-<version> exists and downloads + creates it if not
@ -301,13 +302,13 @@ if [ $TARGET_OS == "windows" ]; then
if [ ! -f "arduino-$ARDUINO_ENV-windows.zip" ]; then
echo "$(tput setaf 6)Downloading Windows 32/64-bit Arduino IDE portable...$(tput setaf 2)"
sleep 2
wget https://downloads.arduino.cc/arduino-$ARDUINO_ENV-windows.zip || exit 7
wget https://downloads.arduino.cc/arduino-$ARDUINO_ENV-windows.zip || exit 8
echo "$(tput sgr 0)"
fi
if [[ ! -d "../PF-build-env-$BUILD_ENV/$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor" && ! -e "../PF-build-env-$BUILD_ENV/arduino-$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor.txt" ]]; then
echo "$(tput setaf 6)Unzipping Windows 32/64-bit Arduino IDE portable...$(tput setaf 2)"
sleep 2
unzip arduino-$ARDUINO_ENV-windows.zip -d ../PF-build-env-$BUILD_ENV || exit 7
unzip arduino-$ARDUINO_ENV-windows.zip -d ../PF-build-env-$BUILD_ENV || exit 8
mv ../PF-build-env-$BUILD_ENV/arduino-$ARDUINO_ENV ../PF-build-env-$BUILD_ENV/$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor
echo "# arduino-$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor" >> ../PF-build-env-$BUILD_ENV/arduino-$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor.txt
echo "$(tput sgr0)"
@ -485,37 +486,36 @@ while getopts v:l:d:b:o:c:p:n:m:g:?h flag
#
# '?' 'h' argument usage and help
if [ "$help_flag" == "1" ] ; then
echo "***************************************"
echo "* PF-build.sh Version: 1.0.6-Build_33 *"
echo "***************************************"
echo "Arguments:"
echo "$(tput setaf 2)-v$(tput sgr0) Variant '$(tput setaf 2)All$(tput sgr0)' or variant file name"
echo "$(tput setaf 2)-l$(tput sgr0) Languages '$(tput setaf 2)ALL$(tput sgr0)' for multi language or '$(tput setaf 2)EN_ONLY$(tput sgr0)' for English only"
echo "$(tput setaf 2)-d$(tput sgr0) Devel build '$(tput setaf 2)GOLD$(tput sgr0)', '$(tput setaf 2)RC$(tput sgr0)', '$(tput setaf 2)BETA$(tput sgr0)', '$(tput setaf 2)ALPHA$(tput sgr0)', '$(tput setaf 2)DEBUG$(tput sgr0)', '$(tput setaf 2)DEVEL$(tput sgr0)' and '$(tput setaf 2)UNKNOWN$(tput sgr0)'"
echo "$(tput setaf 2)-b$(tput sgr0) Build/commit number '$(tput setaf 2)Auto$(tput sgr0)' needs git or a number"
echo "$(tput setaf 2)-o$(tput sgr0) Output '$(tput setaf 2)1$(tput sgr0)' force or '$(tput setaf 2)0$(tput sgr0)' block output and delays"
echo "$(tput setaf 2)-c$(tput sgr0) Do not clean up lang build'$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-p$(tput sgr0) Keep Configuration_prusa.h '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-n$(tput sgr0) New fresh build '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-m$(tput sgr0) Start MK404 sim '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes '$(tput setaf 2)2$(tput sgr0)' with MMU2"
echo "$(tput setaf 2)-g$(tput sgr0) Start MK404 grafics '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' lite '$(tput setaf 2)2$(tput sgr0)' fancy"
echo "$(tput setaf 2)-?$(tput sgr0) Help"
echo "$(tput setaf 2)-h$(tput sgr0) Help"
echo
echo "Brief USAGE:"
echo " $(tput setaf 2)./PF-build.sh$(tput sgr0) [-v] [-l] [-d] [-b] [-o] [-c] [-p] [-n] [-m]"
echo
echo "Example:"
echo " $(tput setaf 2)./PF-build.sh -v All -l ALL -d GOLD$(tput sgr0)"
echo " Will build all variants as multi language and final GOLD version"
echo
echo " $(tput setaf 2) ./PF-build.sh -v 1_75mm_MK3S-EINSy10a-E3Dv6full.h -b Auto -l ALL -d GOLD -o 1 -c 1 -p 1 -n 1$(tput sgr0)"
echo " Will build MK3S multi language final GOLD firmware "
echo " with current commit count number and output extra information,"
echo " not delete lang build temporary files, keep Configuration_prusa.h and build with new fresh build folder."
echo
exit
echo "***************************************"
echo "* PF-build.sh Version: 1.0.6-Build_33 *"
echo "***************************************"
echo "Arguments:"
echo "$(tput setaf 2)-v$(tput sgr0) Variant '$(tput setaf 2)All$(tput sgr0)' or variant file name"
echo "$(tput setaf 2)-l$(tput sgr0) Languages '$(tput setaf 2)ALL$(tput sgr0)' for multi language or '$(tput setaf 2)EN_ONLY$(tput sgr0)' for English only"
echo "$(tput setaf 2)-d$(tput sgr0) Devel build '$(tput setaf 2)GOLD$(tput sgr0)', '$(tput setaf 2)RC$(tput sgr0)', '$(tput setaf 2)BETA$(tput sgr0)', '$(tput setaf 2)ALPHA$(tput sgr0)', '$(tput setaf 2)DEBUG$(tput sgr0)', '$(tput setaf 2)DEVEL$(tput sgr0)' and '$(tput setaf 2)UNKNOWN$(tput sgr0)'"
echo "$(tput setaf 2)-b$(tput sgr0) Build/commit number '$(tput setaf 2)Auto$(tput sgr0)' needs git or a number"
echo "$(tput setaf 2)-o$(tput sgr0) Output '$(tput setaf 2)1$(tput sgr0)' force or '$(tput setaf 2)0$(tput sgr0)' block output and delays"
echo "$(tput setaf 2)-c$(tput sgr0) Do not clean up lang build'$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-p$(tput sgr0) Keep Configuration_prusa.h '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-n$(tput sgr0) New fresh build '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes"
echo "$(tput setaf 2)-m$(tput sgr0) Start MK404 sim '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' yes '$(tput setaf 2)2$(tput sgr0)' with MMU2"
echo "$(tput setaf 2)-g$(tput sgr0) Start MK404 grafics '$(tput setaf 2)0$(tput sgr0)' no '$(tput setaf 2)1$(tput sgr0)' lite '$(tput setaf 2)2$(tput sgr0)' fancy"
echo "$(tput setaf 2)-?$(tput sgr0) Help"
echo "$(tput setaf 2)-h$(tput sgr0) Help"
echo
echo "Brief USAGE:"
echo " $(tput setaf 2)./PF-build.sh$(tput sgr0) [-v] [-l] [-d] [-b] [-o] [-c] [-p] [-n] [-m]"
echo
echo "Example:"
echo " $(tput setaf 2)./PF-build.sh -v All -l ALL -d GOLD$(tput sgr0)"
echo " Will build all variants as multi language and final GOLD version"
echo
echo " $(tput setaf 2) ./PF-build.sh -v 1_75mm_MK3S-EINSy10a-E3Dv6full.h -b Auto -l ALL -d GOLD -o 1 -c 1 -p 1 -n 1$(tput sgr0)"
echo " Will build MK3S multi language final GOLD firmware "
echo " with current commit count number and output extra information,"
echo " not delete lang build temporary files, keep Configuration_prusa.h and build with new fresh build folder."
echo
exit 14
fi
#
@ -806,9 +806,9 @@ do
fi
#Check if compiler flags are set to Prusa specific needs for the rambo board.
# if [ $TARGET_OS == "windows" ]; then
# RAMBO_PLATFORM_FILE="PrusaResearchRambo/avr/platform.txt"
# fi
#if [ $TARGET_OS == "windows" ]; then
#RAMBO_PLATFORM_FILE="PrusaResearchRambo/avr/platform.txt"
#fi
#### End of Prepare building
@ -873,6 +873,8 @@ do
# build languages
echo "$(tput setaf 3)"
./lang-build.sh || exit 32
# build community languages
./lang-community.sh || exit 33
# Combine compiled firmware with languages
./fw-build.sh || exit 33
cp not_tran.txt not_tran_$VARIANT.txt
@ -884,9 +886,9 @@ do
if [ "$MOTHERBOARD" = "BOARD_EINSY_1_0a" ]; then
echo "$(tput setaf 2)Copying multi language firmware for MK3/Einsy board to PF-build-hex folder$(tput sgr 0)"
# Make a copy of "lang.bin" for MK404 MK3 and MK3S
if [ ! -z "$mk404_flag" ]; then
cp -f lang.bin $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin
fi
#if [ ! -z "$mk404_flag" ]; then
#cp -f lang.bin $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin
#fi
# End of "lang.bin" for MK3 and MK3S copy
cp -f firmware.hex $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.hex
else
@ -975,43 +977,46 @@ echo "more information how to flash firmware https://www.prusa3d.com/drivers/ $(
# Check/compile MK404 sim
if [ ! -z "$mk404_flag" ]; then
./MK404-build.sh
./MK404-build.sh
# For Prusa MK2, MK2.5/S
if [ "$MOTHERBOARD" == "BOARD_RAMBO_MINI_1_3" ]; then
if [ "$MOTHERBOARD" == "BOARD_RAMBO_MINI_1_3" ]; then
PRINTER="${PRINTER}_mR13"
elif [ "$mk404_flag" == "2" ]; then # Check if MMU2 is selected only for MK3/S
else
if [[ "$mk404_flag" == "2" || "$mk404_flag" == "MMU2" || "$mk404_flag" == "MMU2S" ]]; then # Check if MMU2 is selected only for MK3/S
PRINTER="${PRINTER}MMU2"
fi
fi
fi
# Run MK404 with grafics
if [ ! -z "$graphics_flag" ]; then
if [ ! -z "$graphics_flag" ]; then
MK404_options="--colour-extrusion --extrusion Quad_HR -g "
if [ "$graphics_flag" == "1" ]; then
if [[ "$graphics_flag" == "1" || "$graphics_flag" == "lite" ]]; then
MK404_options="${MK404_options}lite"
else
elif [[ "$graphics_flag" == "2" || "$graphics_flag" == "fancy" ]]; then
MK404_options="${MK404_options}fancy"
else
echo "$(tput setaf 1)Unsupported MK404 graphics option $graphics_flag$(tput sgr 0)"
fi
fi
fi
# Output some useful data
echo "Printer: $PRINTER"
echo "Options: $MK404_options"
echo "Printer: $PRINTER"
echo "Options: $MK404_options"
# Change to MK404 build folder
cd ../MK404/master/build
cd ../MK404/master/build
# Copy language bin file for MK3 and MK3S to xflash
if [ -f $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin ]; then
echo "Copy 'FW$FW-Build$BUILD-$VARIANT-lang.bin' to 'Prusa_${PRINTER}_xflash.bin'"
dd if=/dev/zero bs=1 count=262145 | tr "\000" "\377" >Prusa_${PRINTER}_xflash.bin
dd if=$SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin of=Prusa_${PRINTER}_xflash.bin conv=notrunc
fi
#if [ -f $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin ]; then
#echo "Copy 'FW$FW-Build$BUILD-$VARIANT-lang.bin' to 'Prusa_${PRINTER}_xflash.bin'"
#dd if=/dev/zero bs=1 count=262145 | tr "\000" "\377" >Prusa_${PRINTER}_xflash.bin
#dd if=$SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-lang.bin of=Prusa_${PRINTER}_xflash.bin conv=notrunc
#fi
# Start MK404
# default with serial output and terminal to manipulate it via terminal
./MK404 Prusa_$PRINTER -s --terminal $MK404_options -f $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.hex
./MK404 Prusa_$PRINTER -s --terminal $MK404_options -f $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.hex
fi
#### End of MK404 Simulator

View File

@ -38,4 +38,5 @@ export ARDUINO=$BUILD_ENV_PATH
cd $SCRIPT_PATH/lang
./lang-build.sh || exit 10
./fw-build.sh || exit 11
./lang-community.sh || exit 11
./fw-build.sh || exit 12

194
lang/Add_new_language.md Normal file
View File

@ -0,0 +1,194 @@
# How-to add a new language to Prusa Firmware
We will use Dutch as an example here.
## Prepare Prusa Firmware
QR = palceholder for language in upper case
qr = placehodler for language in lower case
AB = palceholder for hexadecial
Files needs to be modified
- `../Firmware/language.h`
In section `/** @name Language codes (ISO639-1)*/` add the new `#define LANG_CODE_QR 0xABAB //!<'qr'`following ISO639-1 convention for QR.
https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
Example:
`#define LANG_CODE_NL 0x6e6c //!<'nl'` where the hex value `0x6e6c` is in ascii `nl`
- `../Firmware/language.c`
In section `const char* lang_get_name_by_code(uint16_t code)` add `case LANG_CODE_NL: return _n("Language");`
Example:
`case LANG_CODE_NL: return _n("Nederlands");` Where `Language` is native spoken version, here `Nederlands` (Netherlands) or `Vlaams` (Belgium). This will be displayed on the LCD menu.
- `../lang/lang-add.sh`
In section `cat lang_add.txt | sed 's/^/"/;s/$/"/' | while read new_s; do` add `insert_qr "$new_s" 'qr'`where qr
Example:
`insert_qr "$new_s" 'nl'` with qr value `nl`for Dutch
- `../lang/lang-build.sh`
In section `#returns hexadecial data for lang code` add a case `*qr*) echo '0x71\0x72'`
Example:
`*nl*) echo '\x6c\x6e' ;;` !!! IMPORTANT that the hex values are switched so 'nl' is here in 'ln' !!!
In generate "all" section add `generate_binary 'qr'
Example:
`generate_binary 'nl'`
- `../lang/lang-check.py`
Add in `help` the new language `qr`
Example:
From `help="Check lang file (en|cs|de|es|fr|it|pl)")` to `help="Check lang file (en|cs|de|es|fr|nl|it|pl)")`
- In `../lang/lang-clean.sh`
In section echo `"lang-clean.sh started" >&2` add `clean_lang qr`
Example:
`clean_lang nl`
- `../lang/lang-export.sh`
In section `# if 'all' is selected, script will generate all po files and also pot file` add `./lang-export.sh qr`
Example:
`./lang-export.sh nl`
In section ` # language name in english` add `*qr*) echo "Language-in-English" ;;`
Example:
`*nl*) echo "Dutch" ;;`
- `../lang/lang-import.sh`
In section `#replace in languages translation` add new rule set for the language.
As the LCD screen doesn't not support äöüßéè and other special characters, it makes sense to "normalize" these.
Example:
```
#replace in dutch translation according to https://nl.wikipedia.org/wiki/Accenttekens_in_de_Nederlandse_spelling
if [ "$LNG" = "nl" ]; then
#replace 'ë' with 'e'
sed -i 's/\xc3\xab/e/g' $LNG'_filtered.po'
#replace 'ï' with 'i'
sed -i 's/\xc3\xaf/i/g' $LNG'_filtered.po'
#replace 'é' with 'e'
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
#replace 'è' with 'e' (left)
sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po'
#replace 'ö' with 'o' (left)
sed -i 's/\xc3\xb6/o/g' $LNG'_filtered.po'
#replace 'ê' with 'e' (left)
sed -i 's/\xc3\xaa/e/g' $LNG'_filtered.po'
#replace 'ü' with 'u' (left)
sed -i 's/\xc3\xbc/u/g' $LNG'_filtered.po'
#replace 'ç' with 'c' (left)
sed -i 's/\xc3\xa7/c/g' $LNG'_filtered.po'
#replace 'á' with 'a' (left)
sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po'
#replace 'à' with 'a' (left)
sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po'
#replace 'ä' with 'a' (left)
sed -i 's/\xc3\xa4/a/g' $LNG'_filtered.po'
#replace 'û' with 'u' (left)
sed -i 's/\xc3\xbc/u/g' $LNG'_filtered.po'
#replace 'î' with 'i' (left)
sed -i 's/\xc3\xae/i/g' $LNG'_filtered.po'
#replace 'í' with 'i' (left)
sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po'
#replace 'ô' with 'o' (left)
sed -i 's/\xc3\xb4/o/g' $LNG'_filtered.po'
#replace 'ú' with 'u' (left)
sed -i 's/\xc3\xba/u/g' $LNG'_filtered.po'
#replace 'ñ' with 'n' (left)
sed -i 's/\xc3\xb1/n/g' $LNG'_filtered.po'
#replace 'â' with 'a' (left)
sed -i 's/\xc3\xa2/a/g' $LNG'_filtered.po'
#replace 'Å' with 'A' (left)
sed -i 's/\xc3\x85/A/g' $LNG'_filtered.po'
fi
```
- `../lang/fw-build.sh`
In section `#update _SEC_LANG in binary file if language is selected` add
```
if [ -e lang_qr.bin ]; then
echo -n " Language-in-English : " >&2
./update_lang.sh qr 2>./update_lang_qr.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
```
Example:
```
if [ -e lang_nl.bin ]; then
echo -n " Dutch : " >&2
./update_lang.sh nl 2>./update_lang_nl.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
```
In section `#create binary file with all languages` add `if [ -e lang_qr.bin ]; then cat lang_qr.bin >> lang.bin; fi`
Example:
`if [ -e lang_nl.bin ]; then cat lang_nl.bin >> lang.bin; fi`
- `../lang/fw-clean.sh`
In section `echo "fw-clean.sh started" >&2` add
```
rm_if_exists firmware_qr.hex
...
...
rm_if_exists update_lang_qr.out
```
Example:
`rm_if_exists firmware_nl.hex`
and
`rm_if_exists update_lang_nl.out`
## Prepare language part
To prepare the acutal language translation files we need create the `lang_en_qr.txt` file.
1. Copy and `lang_en.txt` as `lang_en_qr.txt`
2. run `../lang/lang-export.sh`
3. copy `../lang/po/Firmware_qr.po` file to `../lang/po/new/qr.po`
4. translate all messages using POEdit or other tools.
5. use `lang/lang-import.sh qr` to generate `lang_en_qr.txt` from translated po files
6. move `../lang/po/new/lang_en_qr.txt` to `../lang/lang_en_qr.txt`
7. cleanup `../lang/po/new` folder by deleting
```
qr_filtered.po
qr_new.po
noasci.txt
```
##

View File

@ -163,6 +163,22 @@ else
./update_lang.sh pl 2>./update_lang_pl.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; finish 1; fi
fi
#Community language support
#Dutch
if [ -e lang_nl.bin ]; then
echo -n " Dutch : " >&2
./update_lang.sh nl 2>./update_lang_nl.out 1>/dev/null
if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
fi
#Use the 6 lines below as a template and replace 'qr' and 'New language'
#New language
# if [ -e lang_qr.bin ]; then
# echo -n " New language : " >&2
# ./update_lang.sh qr 2>./update_lang_qr.out 1>/dev/null
# if [ $? -eq 0 ]; then echo 'OK' >&2; else echo 'NG!' >&2; fi
# fi
# echo "skipped" >&2
fi
@ -174,6 +190,13 @@ if [ -e lang_es.bin ]; then cat lang_es.bin >> lang.bin; fi
if [ -e lang_fr.bin ]; then cat lang_fr.bin >> lang.bin; fi
if [ -e lang_it.bin ]; then cat lang_it.bin >> lang.bin; fi
if [ -e lang_pl.bin ]; then cat lang_pl.bin >> lang.bin; fi
#Community language support
# Dutch
if [ -e lang_nl.bin ]; then cat lang_nl.bin >> lang.bin; fi
#Use the 2 lines below as a template and replace 'qr'
## New language
#if [ -e lang_qr.bin ]; then cat lang_qr.bin >> lang.bin; fi
#convert lang.bin to lang.hex
echo -n " converting to hex..." >&2

View File

@ -45,9 +45,17 @@ rm_if_exists update_lang_de.out
rm_if_exists update_lang_es.out
rm_if_exists update_lang_fr.out
rm_if_exists update_lang_it.out
rm_if_exists update_lang_nl.out
rm_if_exists update_lang_pl.out
rm_if_exists lang.bin
rm_if_exists lang.hex
#Community language support
#Dutch
rm_if_exists firmware_nl.hex
#Use the 2 lines below as a template and replace 'qr'
##New language
#rm_if_exists firmware_qr.hex
echo -n "fw-clean.sh finished" >&2
if [ $result -eq 0 ]; then

View File

@ -66,6 +66,13 @@ cat lang_add.txt | sed 's/^/"/;s/$/"/' | while read new_s; do
insert_xx "$new_s" 'fr'
insert_xx "$new_s" 'it'
insert_xx "$new_s" 'pl'
#Community language support
#Dutch
insert_xx "$new_s" 'nl'
#Use the 2 lines below as a template and replace 'qr'
##New language
# insert_xx "$new_s" 'qr'
fi
done

View File

@ -43,6 +43,12 @@ lang_code_hex_data()
*fr*) echo '\x72\x66' ;;
*it*) echo '\x74\x69' ;;
*pl*) echo '\x6c\x70' ;;
#Community language support
#Dutch
*nl*) echo '\x6c\x6e' ;;
#Use the 2 lines below as a template and replace 'qr' and `\x71\x72`
##New language
# *qr*) echo '\x71\x72' ;;
esac
echo '??'
}
@ -135,6 +141,7 @@ if [ "$1" = "all" ]; then
generate_binary 'fr'
generate_binary 'it'
generate_binary 'pl'
#DO NOT add Community languages here !!!
else
generate_binary $1
fi

View File

@ -56,7 +56,7 @@ def main():
usage="$(prog)s lang")
parser.add_argument(
"lang", nargs='?', default="en", type=str,
help="Check lang file (en|cs|de|es|fr|it|pl)")
help="Check lang file (en|cs|de|es|fr|nl|it|pl)")
parser.add_argument(
"--no-warning", action="store_true",
help="Disable warnings")

View File

@ -46,6 +46,13 @@ clean_lang es
clean_lang fr
clean_lang it
clean_lang pl
#Community language support
#Dutch
clean_lang nl
#Use the 2 lines below as a template and replace 'qr'
##New language
#clean_lang_qr
echo -n "lang-clean.sh finished" >&2
if [ $result -eq 0 ]; then

53
lang/lang-community.sh Executable file
View File

@ -0,0 +1,53 @@
#!/bin/sh
#
# lang-community.sh - Community language support script
# Check community languages are defined in `config.h`
#
# Root path
if [ -z "$ROOT_PATH" ]; then
export ROOT_PATH=".."
fi
# Check community language NL = Dutch
COMMUNITY_LANG_NL=$(grep --max-count=1 "^#define COMMUNITY_LANG_NL" $ROOT_PATH/Firmware/config.h| cut -d '_' -f3 |cut -d ' ' -f1)
export NL=$COMMUNITY_LANG_NL
# Use the lines below as a template and replace 'QR' and 'new language'
# Check comminity language QR = new language
#COMMUNITY_LANG_QR=$(grep --max-count=1 "^#define COMMUNITY_LANG_QR" $ROOT_PATH/Firmware/config.h| cut -d '_' -f3 |cut -d ' ' -f1)
#export QR=$COMMUNITY_LANG_QR
#startup message
echo "lang-community.sh started" >&2
echo -n " Source code path: " >&2
if [ -e $ROOT_PATH ]; then echo 'OK' >&2; else echo 'NG!' >&2; _err=1; fi
echo " Found: " >&2
if [ "$COMMUNITY_LANG_NL" = "NL" ]; then
echo " $COMMUNITY_LANG_NL" >&2
echo
./lang-build.sh nl
fi
# Use the 5 lines below as a template and replace 'QR' and 'qr'
#if [ "$COMMUNITY_LANG_QR" = "QR" ]; then
# echo " $COMMUNITY_LANG_QR" >&2
# echo
# ./lang-build.sh qr
#fi
#exiting function
finish()
{
if [ $1 -eq 0 ]; then
echo "lang-community.sh finished with success" >&2
else
echo "lang-community.sh finished with errors!" >&2
fi
echo
exit $1
}
finish 0

View File

@ -22,6 +22,12 @@ if [ "$LNG" = "all" ]; then
./lang-export.sh fr
./lang-export.sh it
./lang-export.sh pl
#Community language support
#Dutch
./lang-export.sh nl
#Use the 2 lines below as a template and replace 'qr' and 'New language'
##New language
# ./lang-export.sh qr
exit 0
fi
@ -48,6 +54,12 @@ else
*fr*) echo "French" ;;
*it*) echo "Italian" ;;
*pl*) echo "Polish" ;;
#Community language support
#Dutch
*nl*) echo "Dutch" ;;
#Use the 2 lines below as a template and replace 'qr' and 'New language'
##New language
# *qr*) echo "New language" ;;
esac)
# unknown language - error
if [ -z "LNGNAME" ]; then

View File

@ -15,6 +15,7 @@ if [ "$LNG" = "all" ]; then
./lang-import.sh fr
./lang-import.sh it
./lang-import.sh pl
#DO NOT add Community languages here !!!
exit 0
fi
@ -40,51 +41,51 @@ sed -i 's/ \\n/ /g;s/\\n/ /g' $LNG'_filtered.po'
#replace in czech translation
if [ "$LNG" = "cz" ]; then
#replace 'ž' with 'z'
#replace 'ž' with 'z'
sed -i 's/\xc5\xbe/z/g' $LNG'_filtered.po'
#replace 'ì' with 'e'
#replace 'ì' with 'e'
sed -i 's/\xc4\x9b/e/g' $LNG'_filtered.po'
#replace 'í' with 'i'
#replace 'í' with 'i'
sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po'
#replace 'ø' with 'r'
#replace 'ø' with 'r'
sed -i 's/\xc5\x99/r/g' $LNG'_filtered.po'
#replace 'è' with 'c'
#replace 'è' with 'c'
sed -i 's/\xc4\x8d/c/g' $LNG'_filtered.po'
#replace 'á' with 'a'
#replace 'á' with 'a'
sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po'
#replace 'é' with 'e'
#replace 'é' with 'e'
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
fi
#replace in german translation https://en.wikipedia.org/wiki/German_orthography
if [ "$LNG" = "de" ]; then
#replace 'ä' with 'ae'
#replace 'ä' with 'ae'
sed -i 's/\xc3\xa4/ae/g' $LNG'_filtered.po'
#replace 'Ä' with 'Ae'
#replace 'Ä' with 'Ae'
sed -i 's/\xc3\x84/Ae/g' $LNG'_filtered.po'
#replace 'ü' with 'ue'
#replace 'ü' with 'ue'
sed -i 's/\xc3\xbc/ue/g' $LNG'_filtered.po'
#replace 'Ü' with 'Ue'
#replace 'Ü' with 'Ue'
sed -i 's/\xc3\x9c/Ue/g' $LNG'_filtered.po'
#replace 'ö' with 'oe'
#replace 'ö' with 'oe'
sed -i 's/\xc3\xb6/oe/g' $LNG'_filtered.po'
#replace 'Ö' with 'Oe'
#replace 'Ö' with 'Oe'
sed -i 's/\xc3\x96/Oe/g' $LNG'_filtered.po'
#replace 'ß' with 'ss'
#replace 'ß' with 'ss'
sed -i 's/\xc3\x9f/ss/g' $LNG'_filtered.po'
fi
#replace in spain translation
if [ "$LNG" = "es" ]; then
#replace 'á' with 'a'
#replace 'á' with 'a'
sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po'
#replace '¿' with '?'
#replace '¿' with '?'
sed -i 's/\xc2\xbf/?/g' $LNG'_filtered.po'
#replace 'ó' with 'o'
#replace 'ó' with 'o'
sed -i 's/\xc3\xb3/o/g' $LNG'_filtered.po'
#replace 'é' with 'e'
#replace 'é' with 'e'
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
#replace 'í' with 'i'
#replace 'í' with 'i'
sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po'
#replace '!' with '!'
sed -i 's/\xc2\xa1/!/g' $LNG'_filtered.po'
@ -94,40 +95,82 @@ fi
#replace in french translation https://en.wikipedia.org/wiki/French_orthography
if [ "$LNG" = "fr" ]; then
#replace 'á' with 'a' (right)
#replace 'á' with 'a' (right)
sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po'
#replace 'Á' with 'A' (right)
#replace 'Á' with 'A' (right)
sed -i 's/\xc3\x81/A/g' $LNG'_filtered.po'
#replace 'à' with 'a' (left)
#replace 'à' with 'a' (left)
sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po'
#replace 'À' with 'A' (left)
#replace 'À' with 'A' (left)
sed -i 's/\xc3\x80/A/g' $LNG'_filtered.po'
#replace 'é' with 'e' (right)
#replace 'é' with 'e' (right)
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
#replace 'É' with 'E' (right)
#replace 'É' with 'E' (right)
sed -i 's/\xc3\x89/E/g' $LNG'_filtered.po'
#replace 'è' with 'e' (left)
#replace 'è' with 'e' (left)
sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po'
#replace 'È' with 'E' (left)
#replace 'È' with 'E' (left)
sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po'
fi
#replace in italian translation
if [ "$LNG" = "it" ]; then
#replace 'é' with 'e' (left)
#replace 'é' with 'e' (left)
sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po'
#replace 'á' with 'a' (left)
#replace 'á' with 'a' (left)
sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po'
#replace 'ó' with 'o' (left)
#replace 'ó' with 'o' (left)
sed -i 's/\xc3\xb2/o/g' $LNG'_filtered.po'
#replace 'ú' with 'u' (left)
#replace 'ú' with 'u' (left)
sed -i 's/\xc3\xb9/u/g' $LNG'_filtered.po'
#replace 'é' with 'e'
#replace 'é' with 'e'
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
#replace 'É' with 'E' (left)
#replace 'É' with 'E' (left)
sed -i 's/\xc3\x88/E/g' $LNG'_filtered.po'
fi
#replace in dutch translation according to https://nl.wikipedia.org/wiki/Accenttekens_in_de_Nederlandse_spelling
if [ "$LNG" = "nl" ]; then
#replace 'ë' with 'e'
sed -i 's/\xc3\xab/e/g' $LNG'_filtered.po'
#replace 'ï' with 'i'
sed -i 's/\xc3\xaf/i/g' $LNG'_filtered.po'
#replace 'é' with 'e'
sed -i 's/\xc3\xa9/e/g' $LNG'_filtered.po'
#replace 'è' with 'e' (left)
sed -i 's/\xc3\xa8/e/g' $LNG'_filtered.po'
#replace 'ö' with 'o' (left)
sed -i 's/\xc3\xb6/o/g' $LNG'_filtered.po'
#replace 'ê' with 'e' (left)
sed -i 's/\xc3\xaa/e/g' $LNG'_filtered.po'
#replace 'ü' with 'u' (left)
sed -i 's/\xc3\xbc/u/g' $LNG'_filtered.po'
#replace 'ç' with 'c' (left)
sed -i 's/\xc3\xa7/c/g' $LNG'_filtered.po'
#replace 'á' with 'a' (left)
sed -i 's/\xc3\xa1/a/g' $LNG'_filtered.po'
#replace 'à' with 'a' (left)
sed -i 's/\xc3\xa0/a/g' $LNG'_filtered.po'
#replace 'ä' with 'a' (left)
sed -i 's/\xc3\xa4/a/g' $LNG'_filtered.po'
#replace 'û' with 'u' (left)
sed -i 's/\xc3\xbc/u/g' $LNG'_filtered.po'
#replace 'î' with 'i' (left)
sed -i 's/\xc3\xae/i/g' $LNG'_filtered.po'
#replace 'í' with 'i' (left)
sed -i 's/\xc3\xad/i/g' $LNG'_filtered.po'
#replace 'ô' with 'o' (left)
sed -i 's/\xc3\xb4/o/g' $LNG'_filtered.po'
#replace 'ú' with 'u' (left)
sed -i 's/\xc3\xba/u/g' $LNG'_filtered.po'
#replace 'ñ' with 'n' (left)
sed -i 's/\xc3\xb1/n/g' $LNG'_filtered.po'
#replace 'â' with 'a' (left)
sed -i 's/\xc3\xa2/a/g' $LNG'_filtered.po'
#replace 'Å' with 'A' (left)
sed -i 's/\xc3\x85/A/g' $LNG'_filtered.po'
fi
#replace in polish translation
#if [ "$LNG" = "pl" ]; then
#fi

View File

@ -175,6 +175,9 @@
#MSG_DATE c=17 r=1
"Date:"
#MSG_COMMUNITY_MADE c=18
"Community made"
#MSG_DISABLE_STEPPERS
"Disable steppers"

View File

@ -234,6 +234,10 @@
"Date:"
"Datum:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Vypnout motory"

View File

@ -234,6 +234,10 @@
"Date:"
"Datum:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Motoren aus"

View File

@ -234,6 +234,10 @@
"Date:"
"Fecha:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Apagar motores"

View File

@ -234,6 +234,10 @@
"Date:"
"Date:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Desactiver moteurs"

View File

@ -234,6 +234,10 @@
"Date:"
"Data:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Disabilita motori"

1480
lang/lang_en_nl.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -234,6 +234,10 @@
"Date:"
"Data:"
#MSG_COMMUNITY_MADE c=18
"Community made"
"\x00"
#MSG_DISABLE_STEPPERS
"Disable steppers"
"Wylacz silniki"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1867
lang/po/Firmware_nl.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1842
lang/po/new/nl.po Normal file

File diff suppressed because it is too large Load Diff

View File

@ -4,22 +4,22 @@
- Build firmware
- using `build.sh`
- using `PF-build.sh` with a `break` before `# build languages`
- using `PF-build.sh` with a parameter `-c 1` to keep lang build files after compiling
- change to `lang` folder
- check if lang scripts being able to run with `config.sh`
- if you get `Arduino main folder: NG` message change in `config.sh` `export ARDUINO=C:/arduino-1.8.5` to `export ARDUINO=<Path to your Arduino IDE folder>`
-example: `export ARDUINO=D:/Github/Prusa-Firmware/PF-build-env-1.0.6/windows-64`
- run `lang-build.sh en` to create english `lang_en.tmp`, `lang_en.dat` and `lang_en.bin` files
- change in `fw-build.sh` `IGNORE_MISSING_TEXT=1` to `IGNORE_MISSING_TEXT=0` so it stops with error and generates `not_used.txt` and `not_tran.txt`
- change in `fw-build.sh` `IGNORE_MISSING_TEXT=1` to `IGNORE_MISSING_TEXT=0` so it stops with error and generates `not_used<variant>.txt` and `not_tran<variant>.txt`
- run modified `fw-build.sh`
- `not_tran.txt` should be reviewed and added as these are potential missing translations
- copy `not_tran.txt` as `lang_add.txt`
- `not_tran<variant>.txt` should be reviewed and added as these are potential missing translations
- copy `not_tran<variant>.txt` as `lang_add.txt`
- check if there are things you don't want to translate or must be modifed
- als check that the strings do not start with `spaces` as the scripts doesn't handle these well at this moment.
- run `lang-add.sh lang_add.txt` to add the missing translations to `lang_en.txt` and `lang_en_??.txt`
- `not_used.txt` should only contain mesages that aren't used in this variant like MK2.5 vs MK3
- `not_used<variant>.txt` should only contain messages that aren't used in this variant like MK2.5/S vs MK3/S
- run `fw-clean.sh` to cleanup firmware related files
- delete `not_used.txt` and `not_tran.txt`
- delete `not_used<variant>.txt` and `not_tran<variant>.txt`
- run `lang-clean.sh` to cleanup language related files
- run `lang-export.sh all` to create PO files for translation these are stored in `/lang/po` folder
- Send them to translators and reviewers or
@ -30,13 +30,12 @@
- run `lang-import.sh <language code (iso639-1)>` for each newly translated language
- script improvement to import "all" and other things would be great.
- Double check if something is missing or faulty
- run `lang-build.sh` to to create `lang_en.tmp/.dat/.bin` and `lang_en_??.tmp/.dat/.bin` files
- run `fw-build.sh` and check if there are still some messages in `not_tran.txt` that need attention
- run `PF-build.sh -v all -n 1 -c 1` to compile for all variants files
- check if there are still some messages in `not_tran<variant>.txt` that need attention
- After approval
- run `fw-clean.sh` to cleanup firmware related files
- run `lang-clean.sh` to cleanup language related files
- change in `fw-build.sh` back to `IGNORE_MISSING_TEXT=1`
- remove `break` from `PF-build.sh` script if that has been modified
- build your firmware with `build.sh`, `PF-build.sh` or how you normally do it.
- Check/Test firmware on printer