Skip to content

Commit

Permalink
Fix bugs in the file selector screen and icon not being displayed cor…
Browse files Browse the repository at this point in the history
…rectly
  • Loading branch information
X-Ryl669 committed Dec 27, 2020
1 parent 66fc496 commit 790b5fe
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 7 deletions.
181 changes: 177 additions & 4 deletions Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ int8_t curDirLever = 0;
LIST_FILE list_file;
DIR_OFFSET dir_offset[10];

extern uint8_t public_buf[512];
extern char public_buf_m[100];

uint8_t sel_id = 0;
Expand Down Expand Up @@ -349,8 +350,180 @@ int ascii2dec_test(char *ascii) {
return result;
}

void lv_gcode_file_read(uint8_t *data_buf) {
static int gcode_file_read(uint8_t *data_buf, uint32_t & position) {
struct refill
{
char buf[200];
uint32_t available;
uint32_t rpos;
uint32_t remain() const { return available - rpos; }
bool need(uint32_t amount) {
if (!card.isFileOpen()) return false;
if (amount > sizeof(buf)) return false;
int toread = amount - remain();
if (toread <= 0) return true; // It's available already
available -= rpos;
memmove(buf, &buf[rpos], available);
rpos = 0;
card.read(&buf[available], toread);
available += toread;
return true;
}
char * head(uint32_t fetchqty) {
if (fetchqty + rpos > available && !need(fetchqty)) return 0;
rpos += fetchqty;
return &buf[rpos - fetchqty];
}
void revert(uint32_t qty) {
if (qty < rpos) rpos -= qty;
else rpos = 0;
}

refill() : available(0), rpos(0) {}
};

const size_t amountToRead = 200;
uint16_t count = 0;
// We don't call setIndex in the loop below since it's seeking the file and card.read does not update the position
// So instead we keep track of the read position by ourself
uint32_t fileSize = card.getFileSize();

// Clear the buffer with background color
memset(data_buf, 0, amountToRead);

refill tmp;
static bool rescaledOdd = false;
uint32_t prevPosition = position;

if (position < 208) { // This is 400 bytes of hexadecimal data + strlen(;simage;)
// Step 1 here, let's find the beginning of the file's data

// Prefetch a lot of data at once
if (!tmp.need(200)) {
card.closefile();
return -1;
}

char * p = tmp.head(1);
bool skipSearchNL = true; // First search, we just skip new line
while(card.isFileOpen() && position < fileSize) {
if (!skipSearchNL) {
// Find next new line
while (p && (*p != '\r' && *p != '\n') && position < fileSize) { p = tmp.head(1); position++; }
if (!p) return -2; // Nothing can be done here
// Check if it's followed by a ';'
p = tmp.head(1);
}
if (p && *p != ';') { skipSearchNL = false; continue; }
position++;

// Check if we have a simage available now
p = tmp.head(7);
if (!p) return -3;
if (memcmp(p, "simage:", 7) == 0) { position += 7; break; }
if (memcmp(p, "gimage;", 7) == 0) return 1;

// Not found, let's continue searching
tmp.revert(7);
}
if (!p) return -4;
}
// Now we should be on data, let's read as many as required
// Step 2
bool rescaleBy2 = false;
while (count < amountToRead && position < fileSize)
{
char * p = tmp.head(2);
if (!p) return -5;

if (p[0] == '\r' || p[1] == '\r' || p[0] == '\n' || p[1] == '\n')
{
// End of line, let's check the exit condition here
if (p[1] != '\n' && p[1] != '\r') tmp.revert(1);
p = tmp.head(8);
if (!p || memcmp(p, ";;gimage", 8) == 0) {
// Step 3
position += 2;
return 1;
}
if (memcmp(p, "M10086 ;", 8) == 0) {
// Here we have a problem. This is called for lines of 200 bytes, so 100 pixels (with 16bit / pixels)
// Yet, the files above are only 50x50 so we can't just use that and expect it'll work
// We might need to resize the output, but this is only a guess since the image size is not in the header (why ?)
// So toggle the resize flag if we only processed half the width yet
if (count == amountToRead / 2) {
rescaleBy2 = true;
break;
}
position += 9;
// tmp.need(200); // Each line is 208 bytes long so it's perfectly safe now to fetch a complete line, or is it ?
continue;
}
}
data_buf[count++] = (char)(ascii2dec_test(&p[0]) << 4 | ascii2dec_test(&p[1]));
position += 2;
}
if (rescaleBy2) {
// We received a 50x50 icon and we were queried for a 100x50 icon, so resize the data now
// We have to progress backward to avoid overwriting what we just converted
uint16_t * db = (uint16_t*)data_buf;
for (int i = count - 1; i > 0; i-= 2) {
db[i] = db[i/2];
db[i-1] = db[i/2];
}
// We need to re-decode the same line next time we are called, so let's remember it
if (!rescaledOdd) position = prevPosition;
rescaledOdd ^= true;
}

return 0;
}

void lv_gcode_file_read(uint8_t *data_buf, uint32_t unreliable_pos) {
/* Example file content:
--boundary_.oOo._F2003otnPwbPRz13/F4h0s+GUovex2zD
Content-Disposition: form-data; name="file"; filename="SP_Mutter.gcode"
;simage:00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
M10086 ;00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
M10086 ;00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
M10086 ;00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
[...]
M10086 ;
;;gimage:0000000000000000000000000000000000000000000000000000000000000000000000000
[...]
M10086 ;
;FLAVOR:Marlin
;TIME:1384
[...]
*/
// The idea is to fetch the small image (simage) from the comments
// We'll be called multiple times without any possible storage :-/

// So we have 3 steps to parse here
// Step 1: Find the first "\r;simage:" code (drop any byte read meanwhile)
// Step 2: Extract all image data until end of line and skip header (`M10086 ;`) until we find a ';;' marker
// Step 3: Skip ';;' marker and end/close the file here

// Step 1 can only happen on first call, when card.file.curPosition() is 0
// We *must* make progress to reach a simage/M10086 section so that next call will not be inside the header
// Between call, we must be into the data itself (it's much easier this way)
#if ENABLED(SDSUPPORT)
uint32_t position = card.getIndex();
int res = gcode_file_read(data_buf, position);
if (res >= 0)
card.setIndex(position);
else card.closefile();

// Fix the background color if required
uint16_t * db = (uint16_t *)data_buf;
for (size_t i = 0; i < 200 / sizeof(*db); i++)
if (db[i] == 0x0000) db[i] = LV_COLOR_BACKGROUND.full;
#endif



#if ENABLED(SDSUPPORT) && 0
uint16_t i = 0, j = 0, k = 0;
uint16_t row_1 = 0;
bool ignore_start = true;
Expand Down Expand Up @@ -395,7 +568,8 @@ void lv_gcode_file_read(uint8_t *data_buf) {
void lv_close_gcode_file() {TERN_(SDSUPPORT, card.closefile());}

void lv_gcode_file_seek(uint32_t pos) {
card.setIndex(pos);
// Don't seek. We don't care, since the parser will find its way in the file anyway and it breaks the logic if being seeked
//card.setIndex(pos);
}

void cutFileName(char *path, int len, int bytePerLine, char *outStr) {
Expand All @@ -421,8 +595,7 @@ void cutFileName(char *path, int len, int bytePerLine, char *outStr) {
strIndex2 = (char *)strrchr(tmpFile, '.');
#endif

beginIndex = (strIndex1 != 0
) ? strIndex1 + 1 : tmpFile;
beginIndex = (strIndex1 != 0) ? strIndex1 + 1 : tmpFile;

if (strIndex2 == 0 || (strIndex1 > strIndex2)) { // not gcode file
#if _LFN_UNICODE
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/lcd/extui/lib/mks_ui/draw_print_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extern LIST_FILE list_file;
extern void disp_gcode_icon(uint8_t file_num);
extern void lv_draw_print_file(void);
extern uint32_t lv_open_gcode_file(char *path);
extern void lv_gcode_file_read(uint8_t *data_buf);
extern void lv_gcode_file_read(uint8_t *data_buf, uint32_t file_pos);
extern void lv_close_gcode_file();
extern void cutFileName(char *path, int len, int bytePerLine, char *outStr);
extern int ascii2dec_test(char *ascii);
Expand Down
4 changes: 2 additions & 2 deletions Marlin/src/lcd/extui/lib/mks_ui/tft_lvgl_configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ lv_fs_res_t sd_close_cb (lv_fs_drv_t * drv, void * file_p) {

lv_fs_res_t sd_read_cb (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t btr, uint32_t * br) {
if (btr == 200) {
lv_gcode_file_read((uint8_t *)buf);
lv_gcode_file_read((uint8_t *)buf, *(uint32_t*)file_p);
*br = 200;
}
else if (btr == 4) {
Expand All @@ -416,7 +416,7 @@ lv_fs_res_t sd_read_cb (lv_fs_drv_t * drv, void * file_p, void * buf, uint32_t b
}

lv_fs_res_t sd_seek_cb(lv_fs_drv_t * drv, void * file_p, uint32_t pos) {
sd_read_addr_offset = sd_read_base_addr + (pos - 4) / 200 * 409;
sd_read_addr_offset = sd_read_base_addr + (pos - 4) / 200 * 409; // This is wrong, at least for my file since there are 2 M10086 headers per line
lv_gcode_file_seek(sd_read_addr_offset);
return LV_FS_RES_OK;
}
Expand Down

0 comments on commit 790b5fe

Please sign in to comment.