Skip to content

Commit

Permalink
Support new style Anycubic Chiron TFT (MarlinFirmware#21597)
Browse files Browse the repository at this point in the history
  • Loading branch information
SwiftNick authored Apr 19, 2021
1 parent 59fd642 commit d5143c2
Show file tree
Hide file tree
Showing 7 changed files with 480 additions and 228 deletions.
25 changes: 25 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1617,6 +1617,31 @@
#endif
#endif // HAS_DGUS_LCD

//
// Additional options for AnyCubic Chiron TFT displays
//
#if ENABLED(ANYCUBIC_LCD_CHIRON)
// By default the type of panel is automatically detected.
// Enable one of these options if you know the panel type.
//#define CHIRON_TFT_STANDARD
//#define CHIRON_TFT_NEW

// Enable the longer Anycubic powerup startup tune
//#define AC_DEFAULT_STARTUP_TUNE

/**
* Display Folders
* By default the file browser lists all G-code files (including those in subfolders) in a flat list.
* Enable this option to display a hierarchical file browser.
*
* NOTES:
* - Without this option it helps to enable SDCARD_SORT_ALPHA so files are sorted before/after folders.
* - When used with the "new" panel, folder names will also have '.gcode' appended to their names.
* This hack is currently required to force the panel to show folders.
*/
#define AC_SD_FOLDER_VIEW
#endif

//
// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
//
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -2443,6 +2443,10 @@ static_assert(hbm[Z_AXIS] >= 0, "HOMING_BUMP_MM.Z must be greater than or equal
#error "GRAPHICAL_TFT_UPSCALE must be 2, 3, or 4."
#endif

#if BOTH(CHIRON_TFT_STANDARD, CHIRON_TFT_NEW)
#error "Please select only one of CHIRON_TFT_STANDARD or CHIRON_TFT_NEW."
#endif

/**
* Some boards forbid the use of -1 Native USB
*/
Expand Down
272 changes: 183 additions & 89 deletions Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,139 +26,233 @@
* Extensible_UI implementation for Anycubic Chiron
* Written By Nick Wells, 2020 [https://github.com/SwiftNick]
* (not affiliated with Anycubic, Ltd.)
*
* The AC panel wants files in block of 4 and can only display a flat list
* This library allows full folder traversal or flat file display and supports both standerd and new style panels.
*
* ## Old Style TFT panel
* Supported chars {}[]-+=_"$%^&*()~<>|
* Max display length 22 chars
* Max path len 29 chars
* (DOS 8.3 filepath max 29chars)
* (long filepath Max 22)
*
* ## New TFT Panel Format file display format
* Supported chars {}[]-+=_!"$%^&*()~<>\|
* Max display length 26 chars
* Max path len 29 chars
* (DOS 8.3 filepath must end '.GCO')
* (long filepath must end '.gcode')
*
*/

/***************************************************************************
* The AC panel wants files in block of 4 and can only display a flat list *
* This library allows full folder traversal. *
***************************************************************************/

#include "../../../../inc/MarlinConfigPre.h"

#if ENABLED(ANYCUBIC_LCD_CHIRON)

#include "FileNavigator.h"
#include "chiron_tft.h"

using namespace ExtUI;

#define DEBUG_OUT ACDEBUG(AC_FILE)
#include "../../../../core/debug_out.h"

namespace Anycubic {

FileNavigator filenavigator;
FileNavigator filenavigator;
FileList FileNavigator::filelist; // Instance of the Marlin file API
uint16_t FileNavigator::lastpanelindex;
uint16_t FileNavigator::currentindex; // override the panel request
uint8_t FileNavigator::currentfolderdepth;
uint16_t FileNavigator::currentfolderindex[MAX_FOLDER_DEPTH]; // track folder pos for iteration
char FileNavigator::currentfoldername[MAX_PATH_LEN + 1]; // Current folder path

FileNavigator::FileNavigator() { reset(); }

void FileNavigator::reset() {
DEBUG_ECHOLNPGM("reset()");
currentfoldername[0] = '\0';
currentfolderdepth = 0;
currentindex = 0;
lastpanelindex = 0;
ZERO(currentfolderindex)

// Start at root folder
while (!filelist.isAtRootDir()) filelist.upDir();
refresh();
}

void FileNavigator::refresh() { filelist.refresh(); }

FileList FileNavigator::filelist; // Instance of the Marlin file API
char FileNavigator::currentfoldername[MAX_PATH_LEN]; // Current folder path
uint16_t FileNavigator::lastindex;
uint8_t FileNavigator::folderdepth;
uint16_t FileNavigator::currentindex; // override the panel request
void FileNavigator::changeDIR(const char *folder) {
if (currentfolderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
DEBUG_ECHOLNPAIR("FD:" , folderdepth, " FP:",currentindex, " currentfolder:", currentfoldername, " enter:", folder);
currentfolderindex[currentfolderdepth] = currentindex;
strcat(currentfoldername, folder);
strcat(currentfoldername, "/");
filelist.changeDir(folder);
currentfolderdepth++;
currentindex = 0;
}

FileNavigator::FileNavigator() { reset(); }
void FileNavigator::upDIR() {
DEBUG_ECHOLNPAIR("upDIR() from D:", currentfolderdepth, " N:", currentfoldername);
if (!filelist.isAtRootDir()) {
filelist.upDir();
currentfolderdepth--;
currentindex = currentfolderindex[currentfolderdepth]; // restore last position in the folder
filelist.seek(currentindex); // restore file information
}

void FileNavigator::reset() {
// Remove the child folder from the stored path
if (currentfolderdepth == 0)
currentfoldername[0] = '\0';
folderdepth = 0;
currentindex = 0;
lastindex = 0;
// Start at root folder
while (!filelist.isAtRootDir()) filelist.upDir();
refresh();
else {
const char *pos = strchr(currentfoldername, '/');
*(pos + 1) = '\0';
}
}

void FileNavigator::refresh() { filelist.refresh(); }
void FileNavigator::skiptofileindex(uint16_t skip) {
if (skip == 0) return;
while (skip > 0) {
if (filelist.seek(currentindex)) {
DEBUG_ECHOLNPAIR("CI:", currentindex, " FD:", currentfolderdepth, " N:", skip, " ", filelist.longFilename());
if (!filelist.isDir()) {
skip--;
currentindex++;
}
else
changeDIR(filelist.shortFilename());
} // valid file
if (currentindex == filelist.count()) {
if (currentfolderdepth > 0) {
upDIR();
currentindex++;
}
else break; // end of root folder
} // end of folder
} // files needed
// No more files available.
}

void FileNavigator::getFiles(uint16_t index) {
uint8_t files = 4;
if (index == 0) currentindex = 0;
#if ENABLED(AC_SD_FOLDER_VIEW) // SD Folder navigation

void FileNavigator::getFiles(uint16_t index, panel_type_t paneltype, uint8_t filesneeded) {
if (index == 0) currentindex = 0;
// Each time we change folder we reset the file index to 0 and keep track
// of the current position as the TFT panel isnt aware of folders trees.
// of the current position, since the TFT panel isn't aware of folder trees.
if (index > 0) {
--currentindex; // go back a file to take account of the .. added to the root.
if (index > lastindex)
currentindex += files;
--currentindex; // go back a file to take account of the .. we added to the root.
if (index > lastpanelindex)
currentindex += filesneeded;
else
currentindex = currentindex < 4 ? 0 : currentindex - files;
currentindex = currentindex < 4 ? 0 : currentindex - filesneeded;
}
lastindex = index;
lastpanelindex = index;

#if ACDEBUG(AC_FILE)
SERIAL_ECHOLNPAIR("index=", index, " currentindex=", currentindex);
#endif
DEBUG_ECHOLNPAIR("index=", index, " currentindex=", currentindex);

if (currentindex == 0 && folderdepth > 0) { // Add a link to go up a folder
TFTSer.println("<<");
TFTSer.println("..");
files--;
if (currentindex == 0 && currentfolderdepth > 0) { // Add a link to go up a folder
// The new panel ignores entries that don't end in .GCO or .gcode so add and pad them.
if (paneltype == AC_panel_new) {
TFTSer.println("<<.GCO");
Chiron.SendtoTFTLN(PSTR(".. .gcode"));
}
else {
TFTSer.println("<<");
TFTSer.println("..");
}
filesneeded--;
}

for (uint16_t seek = currentindex; seek < currentindex + files; seek++) {
for (uint16_t seek = currentindex; seek < currentindex + filesneeded; seek++) {
if (filelist.seek(seek)) {
sendFile();
#if ACDEBUG(AC_FILE)
SERIAL_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'\n");
#endif
sendFile(paneltype);
DEBUG_ECHOLNPAIR("-", seek, " '", filelist.longFilename(), "' '", currentfoldername, "", filelist.shortFilename(), "'");
}
}
}

void FileNavigator::sendFile() {
// send the file and folder info to the panel
// this info will be returned when the file is selected
// Permitted special characters in file name -_*#~
// Panel can display 22 characters per line
void FileNavigator::sendFile(panel_type_t paneltype) {
if (filelist.isDir()) {
//TFTSer.print(currentfoldername);
TFTSer.println(filelist.shortFilename());
TFTSer.print(filelist.shortFilename());
TFTSer.println("/");
// Add mandatory tags for new panel otherwise lines are ignored.
if (paneltype == AC_panel_new) {
TFTSer.print(filelist.shortFilename());
TFTSer.println(".GCO");
TFTSer.print(filelist.shortFilename());
TFTSer.write('/');
// Make sure we fill all 29 chars of the display line to clear the text buffer otherwise the last line is still visible
for (int8_t i = strlen(filelist.shortFilename()); i < 19; i++)
TFTSer.write(' ');
TFTSer.println(".gcode");
}
else {
TFTSer.println(filelist.shortFilename());
TFTSer.print(filelist.shortFilename());
TFTSer.write('/');
TFTSer.println();
}
}
else {
// Logical Name
else { // Not DIR
TFTSer.write('/');
if (folderdepth > 0) TFTSer.print(currentfoldername);

if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
TFTSer.println(filelist.shortFilename());
TFTSer.print(filelist.longFilename());

// Display Name
TFTSer.println(filelist.longFilename());
// Make sure we fill all 29 chars of the display line to clear the text buffer otherwise the last line is still visible
if (paneltype == AC_panel_new)
for (int8_t i = strlen(filelist.longFilename()); i < 26; i++)
TFTSer.write(' ');

TFTSer.println();
}
}
void FileNavigator::changeDIR(char *folder) {
#if ACDEBUG(AC_FILE)
SERIAL_ECHOLNPAIR("currentfolder: ", currentfoldername, " New: ", folder);
#endif
if (folderdepth >= MAX_FOLDER_DEPTH) return; // limit the folder depth
strcat(currentfoldername, folder);
strcat(currentfoldername, "/");
filelist.changeDir(folder);
refresh();
folderdepth++;
currentindex = 0;
}
} // AC_SD_FOLDER_VIEW

void FileNavigator::upDIR() {
filelist.upDir();
refresh();
folderdepth--;
currentindex = 0;
// Remove the last child folder from the stored path
if (folderdepth == 0) {
currentfoldername[0] = '\0';
#else // Flat file list

void FileNavigator::getFiles(uint16_t index, panel_type_t paneltype, uint8_t filesneeded) {
DEBUG_ECHOLNPAIR("getFiles() I:", index," L:", lastpanelindex);
// if we're searching backwards, jump back to start and search forward
if (index < lastpanelindex) {
reset();
skiptofileindex(index);
}
else {
char *pos = nullptr;
for (uint8_t f = 0; f < folderdepth; f++)
pos = strchr(currentfoldername, '/');
lastpanelindex = index;

*(pos + 1) = '\0';
}
#if ACDEBUG(AC_FILE)
SERIAL_ECHOLNPAIR("depth: ", folderdepth, " currentfoldername: ", currentfoldername);
#endif
while (filesneeded > 0) {
if (filelist.seek(currentindex)) {
if (!filelist.isDir()) {
sendFile(paneltype);
filesneeded--;
currentindex++;
}
else
changeDIR(filelist.shortFilename());
} // valid file

if (currentindex == filelist.count()) {
if (currentfolderdepth > 0) {
upDIR();
currentindex++;
}
else break; // end of root folder
} // end of folder
} // files needed
// No more files available.
}

char* FileNavigator::getCurrentFolderName() { return currentfoldername; }
}
void FileNavigator::sendFile(panel_type_t paneltype) {
TFTSer.write('/');
if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
TFTSer.println(filelist.shortFilename());
if (currentfolderdepth > 0) TFTSer.print(currentfoldername);
TFTSer.println(filelist.longFilename());
DEBUG_ECHOLNPAIR("/", currentfoldername, "", filelist.shortFilename(), " ", filelist.longFilename());
}

#endif // Flat file list

} // Anycubic namespace

#endif // ANYCUBIC_LCD_CHIRON
17 changes: 8 additions & 9 deletions Marlin/src/lcd/extui/lib/anycubic_chiron/FileNavigator.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,21 @@ namespace Anycubic {

class FileNavigator {
public:
FileNavigator();
void reset();
void getFiles(uint16_t, panel_type_t, uint8_t filesneeded=4);
void upDIR();
void changeDIR(const char *);
void sendFile(panel_type_t);
void refresh();
void skiptofileindex(uint16_t);
static void reset();
static void getFiles(uint16_t, panel_type_t, uint8_t filesneeded=4);
static void upDIR();
static void changeDIR(const char *);
static void sendFile(panel_type_t);
static void refresh();
static void skiptofileindex(uint16_t);

static FileList filelist;
private:
static uint16_t lastpanelindex;
static uint16_t currentindex;
static uint8_t currentfolderdepth;
static uint16_t currentfolderindex[MAX_FOLDER_DEPTH];
static char currentfoldername[MAX_PATH_LEN];
static char currentfoldername[MAX_PATH_LEN + 1];
};

extern FileNavigator filenavigator;
Expand Down
Loading

0 comments on commit d5143c2

Please sign in to comment.