|
| 1 | +--- |
| 2 | +title: GIGA Display Shield emWin Guide |
| 3 | +description: 'Learn to display RAW Images on the GIGA Display from USB Storage.' |
| 4 | +author: Pedro Sousa Lima |
| 5 | +tags: [Display, USB] |
| 6 | +--- |
| 7 | + |
| 8 | +## Introduction |
| 9 | + |
| 10 | +This guide explores how to read and display raw RGB565 images from a USB drive onto an Arduino GIGA Display. This project enables you to list files from a USB drive, select an image, and render i. |
| 11 | + |
| 12 | + |
| 13 | + |
| 14 | +## Hardware Requirements |
| 15 | + |
| 16 | +- [Arduino GIGA R1 WiFi](https://store.arduino.cc/products/giga-r1-wifi) |
| 17 | +- [Arduino GIGA Display Shield](https://store.arduino.cc/products/giga-display-shield) |
| 18 | +- USB mass storage device (formatted with FAT32) |
| 19 | + |
| 20 | +## Software Requirements |
| 21 | + |
| 22 | +- **USBHostMbed5** (for USB host functionality) |
| 23 | +- **FATFileSystem** (to read files from USB) |
| 24 | +- **ArduinoH7Video** and **ArduinoGraphics** (for handling display rendering) |
| 25 | + |
| 26 | +## Features |
| 27 | + |
| 28 | +- Lists all files in the `/usb/` directory. |
| 29 | +- Allows users to select an image via the Serial Monitor. |
| 30 | +- Automatically reads and displays an **800x480 RGB565** image. |
| 31 | +- Clears the display upon request. |
| 32 | + |
| 33 | +## Preparing Your Image |
| 34 | + |
| 35 | +To ensure your image is in the correct format (800x480, 16-bit RGB565), you can use an online converter such as the [**LVGL Image Converter**](https://lvgl.io/tools/imageconverter). Select **RGB565** as the output format and set the resolution to 800x480 before saving the file to your USB drive. Make sure the USB drive is formatted for FAT32. |
| 36 | + |
| 37 | +## Code Breakdown |
| 38 | + |
| 39 | +### Setting Up USB Host and Display |
| 40 | + |
| 41 | +The USB host is initialized, enabling support for mass storage devices. The display is also set up using the `Arduino_H7_Video` class. |
| 42 | + |
| 43 | +```cpp |
| 44 | +USBHostMSD msd; |
| 45 | +mbed::FATFileSystem usb("usb"); |
| 46 | +Arduino_H7_Video Display(800, 480, GigaDisplayShield); |
| 47 | +``` |
| 48 | +
|
| 49 | +### Listing Files on USB Storage |
| 50 | +
|
| 51 | +Once mounted, the USB drive is scanned for available files: |
| 52 | +
|
| 53 | +```cpp |
| 54 | +void listRootDirectory() { |
| 55 | + fileCount = 0; |
| 56 | + DIR* dir = opendir("/usb/"); |
| 57 | + if (!dir) return; |
| 58 | + while (true) { |
| 59 | + struct dirent* entry = readdir(dir); |
| 60 | + if (!entry || fileCount >= MAX_FILES) break; |
| 61 | + strncpy(fileNames[fileCount], entry->d_name, MAX_NAME_LEN - 1); |
| 62 | + fileCount++; |
| 63 | + } |
| 64 | + closedir(dir); |
| 65 | +} |
| 66 | +``` |
| 67 | + |
| 68 | +### Selecting an Image via Serial Input |
| 69 | + |
| 70 | +Users can enter a file number in the Serial Monitor to select an image for display. |
| 71 | + |
| 72 | +```cpp |
| 73 | +void handleUserInput() { |
| 74 | + if (Serial.available() > 0) { |
| 75 | + int sel = Serial.parseInt(); |
| 76 | + if (sel >= 1 && sel <= fileCount) { |
| 77 | + char path[256]; |
| 78 | + snprintf(path, sizeof(path), "/usb/%s", fileNames[sel - 1]); |
| 79 | + displayRawRowByRow(path); |
| 80 | + } |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +### Reading and Displaying RAW Images |
| 86 | + |
| 87 | +The file is read row-by-row (800 pixels per row, 2 bytes per pixel). If the entire image (800x480 pixels) were loaded into memory at once, it would require approximately 768 KB of RAM (800 \* 480 \* 2 bytes). However, by processing only one row at a time (800 * 2 bytes), the memory usage is reduced to just `1.6 KB`, making this approach much more efficient and feasible for devices with restricted memory (like GIGA). This approach minimizes memory usage by processing smaller chunks of the image at one time, avoiding large allocations that may exceed available RAM (512 KB for the GIGA). |
| 88 | +To manage this efficiently, we use `malloc()` and `free()` for dynamic memory allocation, ensuring that only the necessary amount of RAM is used rather than pre-allocating a large buffer. This approach helps optimize memory use while preventing fragmentation. |
| 89 | +Similarly, `fopen()` and `fclose()` are used for file management. `fopen()` allows us to open the image file and read data as needed, rather than loading everything at once. `fclose()` ensures that the file is properly closed after reading, freeing up system resources and preventing potential memory leaks. |
| 90 | + |
| 91 | + |
| 92 | +```cpp |
| 93 | +bool displayRawRowByRow(const char* path) { |
| 94 | + FILE* f = fopen(path, "rb"); |
| 95 | + if (!f) return false; |
| 96 | + |
| 97 | + uint8_t* rowBuffer = (uint8_t*) malloc(IMG_WIDTH * 2); |
| 98 | + if (!rowBuffer) { |
| 99 | + fclose(f); |
| 100 | + return false; |
| 101 | + } |
| 102 | + |
| 103 | + Display.beginDraw(); |
| 104 | + for (int y = 0; y < IMG_HEIGHT; y++) { |
| 105 | + fread(rowBuffer, 1, IMG_WIDTH * 2, f); |
| 106 | + Image rowImage(ENCODING_RGB16, rowBuffer, IMG_WIDTH, 1); |
| 107 | + Display.image(rowImage, 0, y); |
| 108 | + } |
| 109 | + Display.endDraw(); |
| 110 | + |
| 111 | + free(rowBuffer); |
| 112 | + fclose(f); |
| 113 | + return true; |
| 114 | +} |
| 115 | +``` |
| 116 | +
|
| 117 | +### Clearing the Display |
| 118 | +
|
| 119 | +Users can reset the display by entering `clear` in the Serial Monitor. |
| 120 | +
|
| 121 | +```cpp |
| 122 | +void forceScreenClear() { |
| 123 | + Display.beginDraw(); |
| 124 | + Display.fill(0x0000); // Fill with black |
| 125 | + Display.endDraw(); |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +### Full code |
| 130 | + |
| 131 | +^C |
| 132 | + |
| 133 | +### Conclusion |
| 134 | + |
| 135 | +This project demonstrates how to read and display **16-bit RGB565 images** from a USB drive onto the Arduino GIGA Display. The row-by-row approach optimizes memory usage while ensuring smooth rendering. This technique is useful for **digital signage, interactive kiosks, and embedded GUI projects**. |
| 136 | + |
| 137 | + |
0 commit comments