Browse Source

SPI Flash data compression (#18879)

Victor Oliveira 3 years ago
parent
commit
04b12dde49
No account linked to committer's email address

+ 317
- 0
Marlin/src/lcd/extui/lib/mks_ui/SPIFlashStorage.cpp View File

@@ -0,0 +1,317 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+
23
+#include "../../../../inc/MarlinConfigPre.h"
24
+
25
+#if HAS_TFT_LVGL_UI
26
+
27
+#include "SPIFlashStorage.h"
28
+
29
+uint8_t SPIFlashStorage::::m_pageData[SPI_FLASH_PageSize];
30
+uint32_t SPIFlashStorage::::m_currentPage;
31
+uint16_t SPIFlashStorage::::m_pageDataUsed;
32
+uint32_t SPIFlashStorage::::m_startAddress;
33
+
34
+#if HAS_SPI_FLASH_COMPRESSION
35
+
36
+  uint8_t SPIFlashStorage::m_compressedData[SPI_FLASH_PageSize];
37
+  uint16_t SPIFlashStorage::m_compressedDataUsed;
38
+
39
+  template <typename T>
40
+  static uint32_t rle_compress(T *output, uint32_t outputLength, T *input, uint32_t inputLength, uint32_t& inputProcessed) {
41
+    uint32_t count = 0, out = 0, index, i;
42
+    T pixel;
43
+    //32767 for uint16_t
44
+    //127 for uint16_t
45
+    //calculated at compile time
46
+    constexpr T max = (0xFFFFFFFF >> (8 * (4 - sizeof(T)))) / 2;
47
+
48
+    inputProcessed = 0;
49
+    while (count < inputLength && out < outputLength) {
50
+      index = count;
51
+      pixel = input[index++];
52
+      while (index < inputLength && index - count < max && input[index] == pixel)
53
+        index++;
54
+      if (index - count == 1) {
55
+        /*
56
+         * Failed to "replicate" the current pixel. See how many to copy.
57
+         * Avoid a replicate run of only 2-pixels after a literal run. There
58
+         * is no gain in this, and there is a risK of loss if the run after
59
+         * the two identical pixels is another literal run. So search for
60
+         * 3 identical pixels.
61
+         */
62
+        while (index < inputLength && index - count < max && (input[index] != input[index - 1] || (index > 1 && input[index] != input[index - 2])))
63
+          index++;
64
+        /*
65
+         * Check why this run stopped. If it found two identical pixels, reset
66
+         * the index so we can add a run. Do this twice: the previous run
67
+         * tried to detect a replicate run of at least 3 pixels. So we may be
68
+         * able to back up two pixels if such a replicate run was found.
69
+         */
70
+        while (index < inputLength && input[index] == input[index - 1])
71
+          index--;
72
+        // If the output buffer could overflow, stop at the remaining bytes
73
+        NOMORE(index, count + outputLength - out - 1);
74
+        output[out++] = (uint16_t)(count - index);
75
+        for (i = count; i < index; i++)
76
+          output[out++] = input[i];
77
+      }
78
+      else {
79
+        // Need at least more 2 spaces
80
+        if (out > outputLength - 2) break;
81
+        output[out++] = (uint16_t)(index - count);
82
+        output[out++] = pixel;
83
+      }
84
+      count = index;
85
+    }
86
+    inputProcessed = count;
87
+
88
+    // Padding
89
+    if (out == outputLength - 1) output[out++] = 0;
90
+
91
+    return out;
92
+  }
93
+
94
+  template <typename UT, typename T>
95
+  static uint32_t rle_uncompress(UT *output, uint32_t outputLength, UT *input, uint32_t inputLength, uint32_t &outputFilled) {
96
+    T count;
97
+    UT i;
98
+    uint32_t processedBytes = 0;
99
+    outputFilled = 0;
100
+
101
+    while (outputLength > 0 && inputLength > 0) {
102
+      processedBytes++;
103
+      count = static_cast<T>(*input++);
104
+      inputLength--;
105
+      if (count > 0) { // Replicate run
106
+        for (i = 0; i < count && outputLength > i; i++)
107
+          output[i] = *input;
108
+        outputFilled += i;
109
+        // If copy incomplete, change the input buffer to start with remaining data in the next call
110
+        if (i < count) {
111
+          // Change to process the difference in the next call
112
+          *(input - 1) = static_cast<UT>(count - i);
113
+          return processedBytes - 1;
114
+        }
115
+        input++;
116
+        inputLength--;
117
+        processedBytes++;
118
+      }
119
+      else if (count < 0) { // literal run
120
+        count = static_cast<T>(-count);
121
+        // Copy, validating if the output have enough space
122
+        for (i = 0; i < count && outputLength > i; i++)
123
+          output[i] = input[i];
124
+        outputFilled += i;
125
+        // If copy incomplete, change the input buffer to start with remaining data in the next call
126
+        if (i < count) {
127
+          input[i - 1] = static_cast<UT>((count - i) * -1);
128
+          // Back one
129
+          return processedBytes + i - 1;
130
+        }
131
+        input += count;
132
+        inputLength -= count;
133
+        processedBytes += count;
134
+      }
135
+      output += count;
136
+      outputLength -= count;
137
+    }
138
+
139
+    return processedBytes;
140
+  }
141
+
142
+#endif // HAS_SPI_FLASH_COMPRESSION
143
+
144
+void SPIFlashStorage::beginWrite(uint32_t startAddress) {
145
+  m_pageDataUsed = 0;
146
+  m_currentPage = 0;
147
+  m_startAddress = startAddress;
148
+  #if HAS_SPI_FLASH_COMPRESSION
149
+    // Restart the compressed buffer, keep the pointers of the uncompressed buffer
150
+    m_compressedDataUsed = 0;
151
+  #endif
152
+}
153
+
154
+
155
+void SPIFlashStorage::endWrite() {
156
+  // Flush remaining data
157
+  #if HAS_SPI_FLASH_COMPRESSION
158
+    if (m_compressedDataUsed > 0) {
159
+      flushPage();
160
+      savePage(m_compressedData);
161
+    }
162
+  #else
163
+    if (m_pageDataUsed > 0) flushPage();
164
+  #endif
165
+}
166
+
167
+void SPIFlashStorage::savePage(uint8_t* buffer) {
168
+  W25QXX.SPI_FLASH_BufferWrite(buffer, m_startAddress + (SPI_FLASH_PageSize * m_currentPage), SPI_FLASH_PageSize);
169
+
170
+  // Test env
171
+  // char fname[256];
172
+  // snprintf(fname, sizeof(fname), "./pages/page-%03d.data", m_currentPage);
173
+  // FILE *fp = fopen(fname, "wb");
174
+  // fwrite(buffer, 1, m_compressedDataUsed, fp);
175
+  // fclose(fp);
176
+}
177
+
178
+void SPIFlashStorage::loadPage(uint8_t* buffer) {
179
+  W25QXX.SPI_FLASH_BufferRead(buffer, m_startAddress + (SPI_FLASH_PageSize * m_currentPage), SPI_FLASH_PageSize);
180
+
181
+  // Test env
182
+  // char fname[256];
183
+  // memset(buffer, 0, SPI_FLASH_PageSize);
184
+  // snprintf(fname, sizeof(fname), "./pages/page-%03d.data", m_currentPage);
185
+  // FILE *fp = fopen(fname, "rb");
186
+  // if (fp != NULL) {
187
+  //     fread(buffer, 1, SPI_FLASH_PageSize, fp);
188
+  //     fclose(fp);
189
+  // }
190
+}
191
+
192
+void SPIFlashStorage::flushPage() {
193
+  #if HAS_SPI_FLASH_COMPRESSION
194
+    // Work com with compressed in memory
195
+    uint32_t inputProcessed;
196
+    uint32_t compressedSize = rle_compress<uint16_t>((uint16_t *)(m_compressedData + m_compressedDataUsed), compressedDataFree() / 2, (uint16_t *)m_pageData, m_pageDataUsed / 2, inputProcessed) * 2;
197
+    inputProcessed *= 2;
198
+    m_compressedDataUsed += compressedSize;
199
+
200
+    // Space remaining in the compressed buffer?
201
+    if (compressedDataFree() > 0) {
202
+      // Free the uncompressed buffer
203
+      m_pageDataUsed = 0;
204
+      return;
205
+    }
206
+
207
+    // Part of the m_pageData was compressed, so ajust the pointers, freeing what was processed, shift the buffer
208
+    // TODO: To avoid this copy, use a circular buffer
209
+    memmove(m_pageData, m_pageData + inputProcessed, m_pageDataUsed - inputProcessed);
210
+    m_pageDataUsed -= inputProcessed;
211
+
212
+    // No? So flush page with compressed data!!
213
+    uint8_t *buffer = m_compressedData;
214
+  #else
215
+    uint8_t *buffer = m_pageData;
216
+  #endif
217
+
218
+  savePage(buffer);
219
+
220
+  #if HAS_SPI_FLASH_COMPRESSION
221
+    // Restart the compressed buffer, keep the pointers of the uncompressed buffer
222
+    m_compressedDataUsed = 0;
223
+  #elif
224
+    m_pageDataUsed = 0;
225
+  #endif
226
+  m_currentPage++;
227
+}
228
+
229
+void SPIFlashStorage::readPage() {
230
+  #if HAS_SPI_FLASH_COMPRESSION
231
+    if (compressedDataFree() == 0) {
232
+      loadPage(m_compressedData);
233
+      m_currentPage++;
234
+      m_compressedDataUsed = 0;
235
+    }
236
+
237
+    // Need to uncompress data
238
+    if (pageDataFree() == 0) {
239
+      m_pageDataUsed = 0;
240
+      uint32_t outpuProcessed = 0;
241
+      uint32_t inputProcessed = rle_uncompress<uint16_t, int16_t>((uint16_t *)(m_pageData + m_pageDataUsed), pageDataFree() / 2, (uint16_t *)(m_compressedData + m_compressedDataUsed), compressedDataFree() / 2, outpuProcessed);
242
+      inputProcessed *= 2;
243
+      outpuProcessed *= 2;
244
+      if (outpuProcessed < pageDataFree()) {
245
+        m_pageDataUsed = SPI_FLASH_PageSize - outpuProcessed;
246
+        // TODO: To avoid this copy, use a circular buffer
247
+        memmove(m_pageData + m_pageDataUsed, m_pageData, outpuProcessed);
248
+      }
249
+
250
+      m_compressedDataUsed += inputProcessed;
251
+    }
252
+  #else
253
+    loadPage(m_pageData);
254
+    m_pageDataUsed = 0;
255
+    m_currentPage++;
256
+  #endif
257
+}
258
+
259
+uint16_t SPIFlashStorage::inData(uint8_t* data, uint16_t size) {
260
+  // Don't write more than we can
261
+  NOMORE(size, pageDataFree());
262
+  memcpy(m_pageData + m_pageDataUsed, data, size);
263
+  m_pageDataUsed += size;
264
+  return size;
265
+}
266
+
267
+void SPIFlashStorage::writeData(uint8_t* data, uint16_t size) {
268
+  // Flush a page if needed
269
+  if (pageDataFree() == 0) flushPage();
270
+
271
+  while (size > 0) {
272
+    uint16_t written = inData(data, size);
273
+    size -= written;
274
+    // Need to write more? Flush page and continue!
275
+    if (size > 0) {
276
+      flushPage();
277
+      data += written;
278
+    }
279
+  }
280
+}
281
+
282
+void SPIFlashStorage::beginRead(uint32_t startAddress) {
283
+  m_startAddress = startAddress;
284
+  m_currentPage = 0;
285
+  // Nothing in memory now
286
+  m_pageDataUsed = SPI_FLASH_PageSize;
287
+  #if HAS_SPI_FLASH_COMPRESSION
288
+    m_compressedDataUsed = sizeof(m_compressedData);
289
+  #endif
290
+}
291
+
292
+uint16_t SPIFlashStorage::outData(uint8_t* data, uint16_t size) {
293
+  // Don't read more than we have
294
+  NOMORE(size > pageDataFree());
295
+  memcpy(data, m_pageData + m_pageDataUsed, size);
296
+  m_pageDataUsed += size;
297
+  return size;
298
+}
299
+
300
+void SPIFlashStorage::readData(uint8_t* data, uint16_t size) {
301
+  // Read a page if needed
302
+  if (pageDataFree() == 0) readPage();
303
+
304
+  while (size > 0) {
305
+    uint16_t read = outData(data, size);
306
+    size -= read;
307
+    // Need to write more? Flush page and continue!
308
+    if (size > 0) {
309
+      readPage();
310
+      data += read;
311
+    }
312
+  }
313
+}
314
+
315
+SPIFlashStorage SPIFlash;
316
+
317
+#endif // HAS_TFT_LVGL_UI

+ 108
- 0
Marlin/src/lcd/extui/lib/mks_ui/SPIFlashStorage.h View File

@@ -0,0 +1,108 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
4
+ *
5
+ * Based on Sprinter and grbl.
6
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
7
+ *
8
+ * This program is free software: you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation, either version 3 of the License, or
11
+ * (at your option) any later version.
12
+ *
13
+ * This program is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
+ * GNU General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU General Public License
19
+ * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
+ *
21
+ */
22
+#pragma once
23
+
24
+#include "W25Qxx.h"
25
+
26
+#define HAS_SPI_FLASH_COMPRESSION 1
27
+
28
+/**
29
+ * This class manages and optimizes SPI Flash data storage,
30
+ * keeping an internal buffer to write and save full SPI flash
31
+ * pages as needed.
32
+ *
33
+ * Since the data is always in the buffer, the class is also
34
+ * able to support fast on-the-fly RLE compression/decompression.
35
+ *
36
+ * In testing with the current LVGL_UI it compacts 2.9MB of icons
37
+ * (which have lots of runs) down to 370kB!!! As a result the UI
38
+ * refresh rate becomes faster and now all LVGL UI can fit into a
39
+ * tiny 2MB SPI Flash, such as the Chitu Board.
40
+ *
41
+ * == Usage ==
42
+ *
43
+ * Writing:
44
+ *
45
+ * The class keeps an internal buffer that caches data until it
46
+ * fits into a full SPI Flash page. Each time the buffer fills up
47
+ * the page is saved to SPI Flash. Sequential writes are optimal.
48
+ *
49
+ *    SPIFlashStorage.beginWrite(myStartAddress);
50
+ *    while (there is data to write)
51
+ *      SPIFlashStorage.addData(myBuffer, bufferSize);
52
+ *    SPIFlashStorage.endWrite(); // Flush remaining buffer data
53
+ *
54
+ * Reading:
55
+ *
56
+ * When reading, it loads a full page from SPI Flash at once and
57
+ * keeps it in a private SRAM buffer. Data is loaded as needed to
58
+ * fullfill requests. Sequential reads are optimal.
59
+ *
60
+ *    SPIFlashStorage.beginRead(myStartAddress);
61
+ *    while (there is data to read)
62
+ *      SPIFlashStorage.readData(myBuffer, bufferSize);
63
+ *
64
+ * Compression:
65
+ *
66
+ * The biggest advantage of this class is the RLE compression.
67
+ * With compression activated a second buffer holds the compressed
68
+ * data, so when writing data, as this buffer becomes full it is
69
+ * flushed to SPI Flash.
70
+ *
71
+ * The same goes for reading: A compressed page is read from SPI
72
+ * flash, and the data is uncompressed as needed to provide the
73
+ * requested amount of data.
74
+ */
75
+class SPIFlashStorage {
76
+public:
77
+  // Write operation
78
+  static void beginWrite(uint32_t startAddress);
79
+  static void endWrite();
80
+  static void writeData(uint8_t* data, uint16_t size);
81
+
82
+  static // Read operation
83
+  static void beginRead(uint32_t startAddress);
84
+  static void readData(uint8_t* data, uint16_t size);
85
+
86
+  static uint32_t getCurrentPage() { return m_currentPage; }
87
+
88
+private:
89
+  static void flushPage();
90
+  static void savePage(uint8_t* buffer);
91
+  static void loadPage(uint8_t* buffer);
92
+  static void readPage();
93
+  static uint16_t inData(uint8_t* data, uint16_t size);
94
+  static uint16_t outData(uint8_t* data, uint16_t size);
95
+
96
+  static uint8_t m_pageData[SPI_FLASH_PageSize];
97
+  static uint32_t m_currentPage;
98
+  static uint16_t m_pageDataUsed;
99
+  static inline uint16_t pageDataFree() { return SPI_FLASH_PageSize - m_pageDataUsed; }
100
+  static uint32_t m_startAddress;
101
+  #if HAS_SPI_FLASH_COMPRESSION
102
+    static uint8_t m_compressedData[SPI_FLASH_PageSize];
103
+    static uint16_t m_compressedDataUsed;
104
+    static inline uint16_t compressedDataFree() { return SPI_FLASH_PageSize - m_compressedDataUsed; }
105
+  #endif
106
+};
107
+
108
+extern SPIFlashStorage SPIFlash;

+ 60
- 36
Marlin/src/lcd/extui/lib/mks_ui/pic_manager.cpp View File

@@ -23,16 +23,17 @@
23 23
 
24 24
 #if HAS_TFT_LVGL_UI
25 25
 
26
-#include "../../../../MarlinCore.h"
27
-
28 26
 #include "string.h"
29
-
30 27
 #include "pic_manager.h"
31
-#include "W25Qxx.h"
32
-#include "../../../../sd/cardreader.h"
33 28
 #include "draw_ready_print.h"
34 29
 #include "mks_hardware_test.h"
35 30
 
31
+#include "SPIFlashStorage.h"
32
+#include "W25Qxx.h"
33
+
34
+#include "../../../../MarlinCore.h"
35
+#include "../../../../sd/cardreader.h"
36
+
36 37
 extern uint16_t DeviceCode;
37 38
 extern unsigned char bmp_public_buf[17 * 1024];
38 39
 
@@ -205,11 +206,11 @@ static char assets[][LONG_FILENAME_LENGTH] = {
205 206
 };
206 207
 
207 208
 #if HAS_SPI_FLASH_FONT
208
-  static char fonts[][LONG_FILENAME_LENGTH] = {
209
-    "FontUNIGBK.bin",
210
-  };
209
+  static char fonts[][LONG_FILENAME_LENGTH] = { "FontUNIGBK.bin" };
211 210
 #endif
212 211
 
212
+static uint8_t currentFlashPage = 0;
213
+
213 214
 uint32_t lv_get_pic_addr(uint8_t *Pname) {
214 215
   uint8_t Pic_cnt;
215 216
   uint8_t i, j;
@@ -217,6 +218,8 @@ uint32_t lv_get_pic_addr(uint8_t *Pname) {
217 218
   uint32_t tmp_cnt = 0;
218 219
   uint32_t addr = 0;
219 220
 
221
+  currentFlashPage = 0;
222
+
220 223
   #if ENABLED(MARLIN_DEV_MODE)
221 224
     SERIAL_ECHOLNPAIR("Getting picture SPI Flash Address: ", (const char*)Pname);
222 225
   #endif
@@ -371,6 +374,10 @@ uint8_t public_buf[512];
371 374
     return -1;
372 375
   }
373 376
 
377
+  #if ENABLED(MARLIN_DEV_MODE)
378
+    static uint32_t totalSizes = 0, totalCompressed = 0;
379
+  #endif
380
+
374 381
   #define ASSET_TYPE_ICON       0
375 382
   #define ASSET_TYPE_LOGO       1
376 383
   #define ASSET_TYPE_TITLE_LOGO 2
@@ -398,43 +405,52 @@ uint8_t public_buf[512];
398 405
     pfileSize = file.fileSize();
399 406
     totalSizeLoaded += pfileSize;
400 407
     if (assetType == ASSET_TYPE_LOGO) {
401
-      while (1) {
408
+      do {
402 409
         pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
403
-        Pic_Logo_Write((uint8_t *)fn, public_buf, pbr); //
404
-        if (pbr < BMP_WRITE_BUF_LEN) break;
405
-      }
410
+        Pic_Logo_Write((uint8_t *)fn, public_buf, pbr);
411
+      } while (pbr >= BMP_WRITE_BUF_LEN);
406 412
     }
407 413
     else if (assetType == ASSET_TYPE_TITLE_LOGO) {
408
-      while (1) {
414
+      do {
409 415
         pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
410
-        Pic_TitleLogo_Write((uint8_t *)fn, public_buf, pbr); //
411
-        if (pbr < BMP_WRITE_BUF_LEN) break;
412
-      }
416
+        Pic_TitleLogo_Write((uint8_t *)fn, public_buf, pbr);
417
+      } while (pbr >= BMP_WRITE_BUF_LEN);
413 418
     }
414 419
     else if (assetType == ASSET_TYPE_G_PREVIEW) {
415
-      while (1) {
420
+      do {
416 421
         pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
417
-        default_view_Write(public_buf, pbr); //
418
-        if (pbr < BMP_WRITE_BUF_LEN) break;
419
-      }
422
+        default_view_Write(public_buf, pbr);
423
+      } while (pbr >= BMP_WRITE_BUF_LEN);
420 424
     }
421 425
     else if (assetType == ASSET_TYPE_ICON) {
422 426
       Pic_Write_Addr = Pic_Info_Write((uint8_t *)fn, pfileSize);
423
-      while (1) {
424
-        pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
425
-        W25QXX.SPI_FLASH_BufferWrite(public_buf, Pic_Write_Addr, pbr);
426
-        Pic_Write_Addr += pbr;
427
-        if (pbr < BMP_WRITE_BUF_LEN) break;
428
-      }
427
+      SPIFlash.beginWrite(Pic_Write_Addr);
428
+      #if HAS_SPI_FLASH_COMPRESSION
429
+        do {
430
+          pbr = file.read(public_buf, SPI_FLASH_PageSize);
431
+          TERN_(MARLIN_DEV_MODE, totalSizes += pbr);
432
+          SPIFlash.writeData(public_buf, SPI_FLASH_PageSize);
433
+        } while (pbr >= SPI_FLASH_PageSize);
434
+      #else
435
+        do {
436
+          pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
437
+          W25QXX.SPI_FLASH_BufferWrite(public_buf, Pic_Write_Addr, pbr);
438
+          Pic_Write_Addr += pbr;
439
+        } while (pbr >= BMP_WRITE_BUF_LEN);
440
+      #endif
441
+      #if ENABLED(MARLIN_DEV_MODE)
442
+        SERIAL_ECHOLNPAIR("Space used: ", fn, " - ", (SPIFlash.getCurrentPage() + 1) * SPI_FLASH_PageSize / 1024, "KB");
443
+        totalCompressed += (SPIFlash.getCurrentPage() + 1) * SPI_FLASH_PageSize;
444
+      #endif
445
+      SPIFlash.endWrite();
429 446
     }
430 447
     else if (assetType == ASSET_TYPE_FONT) {
431 448
       Pic_Write_Addr = UNIGBK_FLASH_ADDR;
432
-      while (1) {
449
+      do {
433 450
         pbr = file.read(public_buf, BMP_WRITE_BUF_LEN);
434 451
         W25QXX.SPI_FLASH_BufferWrite(public_buf, Pic_Write_Addr, pbr);
435 452
         Pic_Write_Addr += pbr;
436
-        if (pbr < BMP_WRITE_BUF_LEN) break;
437
-      }
453
+      } while (pbr >= BMP_WRITE_BUF_LEN);
438 454
     }
439 455
 
440 456
     file.close();
@@ -459,13 +475,13 @@ uint8_t public_buf[512];
459 475
       disp_assets_update_progress("Reading files...");
460 476
       dir_t d;
461 477
       while (dir.readDir(&d, card.longFilename) > 0) {
462
-        // if we dont get a long name, but gets a short one, try it
478
+        // If we dont get a long name, but gets a short one, try it
463 479
         if (card.longFilename[0] == 0 && d.name[0] != 0)
464 480
           dosName2LongName((const char*)d.name, card.longFilename);
465 481
         if (card.longFilename[0] == 0) continue;
466 482
         if (card.longFilename[0] == '.') continue;
467 483
 
468
-        uint8_t a = arrayFindStr(assets, COUNT(assets), card.longFilename);
484
+        int8_t a = arrayFindStr(assets, COUNT(assets), card.longFilename);
469 485
         if (a >= 0 && a < COUNT(assets)) {
470 486
           uint8_t assetType = ASSET_TYPE_ICON;
471 487
           if (strstr(assets[a], "_logo"))
@@ -482,9 +498,8 @@ uint8_t public_buf[512];
482 498
 
483 499
         #if HAS_SPI_FLASH_FONT
484 500
           a = arrayFindStr(fonts, COUNT(fonts), card.longFilename);
485
-          if (a >= 0 && a < COUNT(fonts)) {
501
+          if (a >= 0 && a < COUNT(fonts))
486 502
             loadAsset(dir, d, fonts[a], ASSET_TYPE_FONT);
487
-          }
488 503
         #endif
489 504
       }
490 505
       dir.rename(&root, bakPath);
@@ -496,11 +511,13 @@ uint8_t public_buf[512];
496 511
       W25QXX.SPI_FLASH_BufferRead(&pic_counter, PIC_COUNTER_ADDR, 1);
497 512
       SERIAL_ECHOLNPAIR("Total assets loaded: ", pic_counter);
498 513
     #endif
514
+
515
+    SERIAL_ECHOLNPAIR("Total Uncompressed: ", totalSizes, ", Compressed: ", totalCompressed);
499 516
   }
500 517
 
501 518
   #if HAS_SPI_FLASH_FONT
502 519
     void spi_flash_read_test() { W25QXX.SPI_FLASH_BufferRead(public_buf, UNIGBK_FLASH_ADDR, BMP_WRITE_BUF_LEN); }
503
-  #endif // HAS_SPI_FLASH_FONT
520
+  #endif
504 521
 
505 522
 #endif // SDSUPPORT
506 523
 
@@ -531,8 +548,15 @@ void Pic_Read(uint8_t *Pname, uint8_t *P_Rbuff) {
531 548
 }
532 549
 
533 550
 void lv_pic_test(uint8_t *P_Rbuff, uint32_t addr, uint32_t size) {
534
-  W25QXX.init(SPI_QUARTER_SPEED);
535
-  W25QXX.SPI_FLASH_BufferRead((uint8_t *)P_Rbuff, addr, size);
551
+  #if HAS_SPI_FLASH_COMPRESSION
552
+    if (currentFlashPage == 0)
553
+      SPIFlash.beginRead(addr);
554
+    SPIFlash.readData(P_Rbuff, size);
555
+    currentFlashPage++;
556
+  #else
557
+    W25QXX.init(SPI_QUARTER_SPEED);
558
+    W25QXX.SPI_FLASH_BufferRead((uint8_t *)P_Rbuff, addr, size);
559
+  #endif
536 560
 }
537 561
 
538 562
 #if HAS_SPI_FLASH_FONT

+ 2
- 2
Marlin/src/lcd/extui/lib/mks_ui/pic_manager.h View File

@@ -63,7 +63,7 @@ extern "C" { /* C-declarations for C++ */
63 63
 #define DEFAULT_VIEW_MAX_SIZE           (200*200*2)
64 64
 #define FLASH_VIEW_MAX_SIZE             (200*200*2)
65 65
 
66
-#define PER_PIC_MAX_SPACE_TFT35         (32*1024)
66
+#define PER_PIC_MAX_SPACE_TFT35         (9*1024)
67 67
 #define PER_PIC_MAX_SPACE_TFT32         (16*1024)
68 68
 #define PER_FONT_MAX_SPACE              (16*1024)
69 69
 
@@ -88,7 +88,7 @@ extern "C" { /* C-declarations for C++ */
88 88
   #define PIC_OTHER_SIZE_ADDR_TFT32     0x5EE000
89 89
 
90 90
   // font
91
-  #define FONTINFOADDR                  0x183000 // 6M -- font addr
91
+  #define FONTINFOADDR                  0x150000 // 6M -- font addr
92 92
   #define UNIGBK_FLASH_ADDR            (FONTINFOADDR+4096) // 4*1024
93 93
 
94 94
 #else

+ 2
- 2
Marlin/src/pins/stm32f1/pins_CHITU3D_V5.h View File

@@ -150,10 +150,10 @@
150 150
 #define SPI_FLASH_SIZE 0x200000                   // 2MB
151 151
 
152 152
 #if HAS_TFT_LVGL_UI
153
-  #define HAS_SPI_FLASH_FONT 0
153
+  #define HAS_SPI_FLASH_FONT 1
154 154
   #define HAS_GCODE_PREVIEW 1
155 155
   #define HAS_GCODE_DEFAULT_VIEW_IN_FLASH 0
156
-  #define HAS_LANG_SELECT_SCREEN 0
156
+  #define HAS_LANG_SELECT_SCREEN 1
157 157
   #define HAS_BAK_VIEW_IN_FLASH 0
158 158
   #define HAS_LOGO_IN_FLASH 0
159 159
 

Loading…
Cancel
Save