├── .gitignore ├── LICENSE ├── README.md ├── examples ├── Dduino32 │ └── Dduino32.ino └── Wristband32 │ └── Wristband32.ino ├── images ├── click.jpg ├── flashing.jpg ├── select.jpg └── update_finished.jpg ├── keywords.txt ├── library.json ├── library.properties └── src ├── DstikeUpdater.cpp ├── DstikeUpdater.h ├── io ├── display.cpp ├── display.h ├── gpio.cpp ├── gpio.h ├── sd.cpp └── sd.h ├── memory ├── flasher.cpp ├── flasher.h ├── updater_file_list_mgmt.cpp └── updater_file_list_mgmt.h └── updater_file_list ├── updater_cursor.cpp ├── updater_cursor.h ├── updater_file_list.cpp ├── updater_file_list.h ├── updater_file_node.cpp └── updater_file_node.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Stefan Kremser 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DstikeUpdater OLED 2 | ESP32 OLED SD Updater Library for DSTIKE Boards 3 | 4 | ## Supported Devices 5 | 6 | This library is made for the **DSTIKE D-duino-32 Final** and **DSTIKE ESP32 Watch DevKit OLED**. 7 | 8 | But it can also run on other boards that fulfill these requirements: 9 | - ESP32 SoC 10 | - OLED display (SSD1306 or SH1106) with 128x64 pixel 11 | - Up, down and select buttons as [input pullup](https://www.arduino.cc/en/Tutorial/InputPullupSerial) 12 | - SD card slot connected to the SD/MMC pins (check [this example](https://github.com/espressif/arduino-esp32/blob/master/libraries/SD_MMC/examples/SDMMC_Test/SDMMC_Test.ino)) 13 | 14 | ## Installation 15 | 16 | 1) Click [Download Zip](https://github.com/spacehuhn/DstikeUpdater/archive/master.zip) to download the source code from GitHub. 17 | 2) Unzip and rename the Folder name to "DstikeUpdater". 18 | 3) Paste it in your library folder (usually located somewhere at documents/Arduino/libraries). 19 | 4) Restart the Arduino IDE. 20 | 21 | 5) Install the OLED library using the same steps, from [ThingPulse/esp8266-oled-ssd1306](https://github.com/ThingPulse/esp8266-oled-ssd1306) 22 | 23 | ## Usage 24 | 25 | ### Arduino IDE 26 | 1) Include the library `#include ` 27 | 2) In the begin of `void setup()` add `DstikeUpdater::run()` 28 | 29 | Example for DSTIKE D-duino-32 Final: 30 | ```c++ 31 | #include // Include updater library 32 | 33 | // Pin definitions 34 | #define BUTTON_UP 32 35 | #define BUTTON_DOWN 25 36 | #define BUTTON_SELECT 33 37 | #define OLED_SDA 26 38 | #define OLED_SCK 27 39 | 40 | void setup() { 41 | // Run updater 42 | DstikeUpdater::runSH1106(OLED_SDA, OLED_SCK, BUTTON_UP, BUTTON_DOWN, BUTTON_SELECT); 43 | 44 | // ... 45 | } 46 | 47 | void loop() { 48 | // ... 49 | } 50 | ``` 51 | 52 | Definition of the `run` method: 53 | ```c++ 54 | static void run(OLEDDisplay & display, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 55 | static void runSH1106(int sda, int sck, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 56 | static void runSSD1306(int sda, int sck, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 57 | ``` 58 | 59 | `UPDATER_PATH` defaults to `"/update"`. 60 | `LOADING_DELAY` defaults to `3500`. 61 | 62 | ### Dev. Board 63 | 64 | 1) Get a micro SD card and format it to FAT32 65 | 2) Create the `update` folder in root 66 | 3) Move your `*.bin` files in the `update` folder (`SD:\update\yourfile.bin`) 67 | 4) Power up your board 68 | 5) Press a button in the first 3 seconds to start the updater 69 | 6) Select a file to flash it 70 | 71 | ![Click to start updater](images/click.jpg) 72 | 73 | ![Selecting file](images/select.jpg) 74 | 75 | ![Flashing file](images/flashing.jpg) 76 | 77 | ![Update finished](images/update_finished.jpg) 78 | 79 | ## License 80 | 81 | This software is licensed under the MIT License. See the [license file](LICENSE) for details. 82 | -------------------------------------------------------------------------------- /examples/Dduino32/Dduino32.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // #define UPDATER_PATH "/update" // folder where bin files are located 5 | // #define LOADING_DELAY 3500 // time to press button at startup 6 | 7 | /****** DSTIKE dduino-32 SD ******/ 8 | #define BUTTON_UP 32 9 | #define BUTTON_DOWN 25 10 | #define BUTTON_SELECT 33 11 | #define OLED_SDA 26 12 | #define OLED_SCK 27 13 | 14 | SH1106Wire display(0x3c, OLED_SDA, OLED_SCK); 15 | 16 | void setup() { 17 | DstikeUpdater::run(display, BUTTON_UP, BUTTON_DOWN, BUTTON_SELECT /*,UPDATER_PATH, LOADING_DELAY*/); 18 | } 19 | 20 | void loop() { 21 | display.clear(); 22 | display.drawString(0, 0, "Test Sketch"); 23 | display.display(); 24 | delay(1000); 25 | } -------------------------------------------------------------------------------- /examples/Wristband32/Wristband32.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // #define UPDATER_PATH "/update" // folder where bin files are located 5 | // #define LOADING_DELAY 3500 // time to press button at startup 6 | 7 | /****** DSTIKE Wristband ******/ 8 | #define BUTTON_UP 19 9 | #define BUTTON_DOWN 5 10 | #define BUTTON_SELECT 18 11 | #define OLED_SDA 17 12 | #define OLED_SCK 16 13 | 14 | SH1106Wire display(0x3c, OLED_SDA, OLED_SCK); 15 | 16 | void setup() { 17 | DstikeUpdater::run(display, BUTTON_UP, BUTTON_DOWN, BUTTON_SELECT /*,UPDATER_PATH, LOADING_DELAY*/); 18 | } 19 | 20 | void loop() { 21 | display.clear(); 22 | display.drawString(0, 0, "Test Sketch"); 23 | display.display(); 24 | delay(1000); 25 | } -------------------------------------------------------------------------------- /images/click.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacehuhn/DstikeUpdater/c871a7b521d60aadf0e70c6e88ecfcf6fb859d57/images/click.jpg -------------------------------------------------------------------------------- /images/flashing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacehuhn/DstikeUpdater/c871a7b521d60aadf0e70c6e88ecfcf6fb859d57/images/flashing.jpg -------------------------------------------------------------------------------- /images/select.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacehuhn/DstikeUpdater/c871a7b521d60aadf0e70c6e88ecfcf6fb859d57/images/select.jpg -------------------------------------------------------------------------------- /images/update_finished.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/spacehuhn/DstikeUpdater/c871a7b521d60aadf0e70c6e88ecfcf6fb859d57/images/update_finished.jpg -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For DstikeUpdater 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | DstikeUpdater KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | # DstikeUpdater 16 | run KEYWORD2 17 | runSH1106 KEYWORD2 18 | runSSD1306 KEYWORD2 19 | 20 | ####################################### 21 | # Instances (KEYWORD2) 22 | ####################################### 23 | 24 | ####################################### 25 | # Constants (LITERAL1) 26 | ####################################### 27 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DstikeUpdater", 3 | "version": "1.0.0", 4 | "keywords": "esp32, dstike, update, sd, oled", 5 | "description": "ESP32 OLED SD Updater Library for DSTIKE Boards", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/spacehuhn/DstikeUpdater.git" 9 | }, 10 | "authors": [ 11 | { 12 | "name": "Stefan Kremser, Spacehuhn", 13 | "email": "arduinolib@spacehuhn.com", 14 | "url": "https://spacehuhn.com" 15 | } 16 | ], 17 | "frameworks": "arduino", 18 | "platforms": "espressif32" 19 | } 20 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=DstikeUpdater 2 | version=1.0.0 3 | author=Stefan Kremser 4 | maintainer=Stefan Kremser 5 | sentence=ESP32 OLED SD Updater Library for DSTIKE Boards 6 | paragraph=Select which .bin file to flash on startup 7 | category=Other 8 | url=https://github.com/spacehuhn/DstikeUpdater 9 | architectures=esp32 10 | includes=DstikeUpdater.h 11 | -------------------------------------------------------------------------------- /src/DstikeUpdater.cpp: -------------------------------------------------------------------------------- 1 | #include "DstikeUpdater.h" 2 | 3 | // Including things here, so they are not accessible from outside 4 | #include "memory/updater_file_list_mgmt.h" // get_u_file_list(), get_file_path() 5 | #include "memory/flasher.h" // flash_bin() 6 | #include "io/gpio.h" // init_buttons(), pressed(), pressed_any() 7 | #include "io/sd.h" // init_sd(), get_sd_fs() 8 | #include "io/display.h" // init_display() 9 | 10 | // ========== INTERNAL ========== // 11 | void display_u_file_list(OLEDDisplay& display, u_file_list* list, u_cursor* cursor) { 12 | if (list && cursor) { 13 | int i = 0; 14 | int j = 0; 15 | u_file_node* n = list->begin; 16 | 17 | // go to page of cursor 18 | while (n && i < cursor->page * 4) { 19 | n = n->next; 20 | ++i; 21 | } 22 | 23 | // draw entries 24 | while (n && j < 4) { 25 | String entry_str(j == cursor->pos ? '>' : ' '); 26 | entry_str += String(n->name); 27 | 28 | draw_string(display, j, entry_str); 29 | n = n->next; 30 | ++i; 31 | ++j; 32 | } 33 | 34 | display_show(display); 35 | } 36 | } 37 | 38 | bool loading_screen(OLEDDisplay& display, int up, int down, int select, unsigned long loading_time) { 39 | unsigned long start_time = millis(); 40 | unsigned long end_time = start_time + loading_time; 41 | 42 | while (millis() < end_time) { 43 | if (pressed_any(up, down, select)) return true; 44 | 45 | draw_bar(display, (millis() - start_time) / (loading_time/128)); 46 | display_show(display); 47 | 48 | delay(50); 49 | } 50 | 51 | return false; 52 | } 53 | 54 | bool update_u_cursor(u_cursor* cursor, int up, int down, int entries_per_page) { 55 | if (pressed(up)) { 56 | u_cursor_up(cursor, entries_per_page); 57 | return true; 58 | } 59 | 60 | if (pressed(down)) { 61 | u_cursor_down(cursor, entries_per_page); 62 | return true; 63 | } 64 | 65 | return false; 66 | } 67 | 68 | // ========== EXTERNAL ========== // 69 | void DstikeUpdater::run(OLEDDisplay& display, int up, int down, int select, const char* path, int loadingDelay) { 70 | init_display(display); // Initialize display 71 | init_buttons(up, down, select); // Initialize buttons as INPUT_PULLUP 72 | 73 | display_clear(display); 74 | draw_headline(display); 75 | 76 | // Check if SD is connected 77 | if (!init_sd()) { // Initialize SD/MMC Card 78 | draw_no_sd(display); 79 | draw_loading_bar(display, loadingDelay); 80 | display_clear(display); 81 | 82 | return; 83 | } 84 | 85 | draw_update(display); 86 | display_show(display); 87 | 88 | // Show loading screen and check for button press 89 | if (!loading_screen(display, up, down, select, loadingDelay)) { 90 | display_clear(display); 91 | return; 92 | }; 93 | 94 | fs::FS& fs = get_sd_fs(); 95 | u_file_list* fl = get_u_file_list(fs, path); // load all bin files into a list 96 | u_cursor * c = create_u_cursor(fl); // create a cursor 97 | 98 | // show file list on display 99 | display_clear(display); 100 | draw_headline(display); 101 | display_u_file_list(display, fl, c); 102 | display_show(display); 103 | 104 | // Wait until buttons are released 105 | while (pressed_any(up, down, select)) delay(10); 106 | 107 | // run updater 108 | bool running = true; 109 | const char* file_path = NULL; 110 | 111 | while (running) { 112 | // Up and Down 113 | if (update_u_cursor(c, up, down, 4)) { 114 | display_clear(display); 115 | draw_headline(display); 116 | display_u_file_list(display, fl, c); 117 | display_show(display); 118 | delay(200); 119 | } 120 | 121 | // Select 122 | if (pressed(select)) { 123 | file_path = get_file_path(c, 4); 124 | 125 | if (strcmp(file_path, "Cancel") == 0) { 126 | running = false; 127 | 128 | display_clear(display); 129 | draw_headline(display); 130 | draw_canceled(display); 131 | draw_loading_bar(display, loadingDelay); 132 | display_show(display); 133 | } else { 134 | display_clear(display); 135 | draw_headline(display); 136 | draw_flashing(display); 137 | display_show(display); 138 | 139 | draw_string_f(display, 1, flash_bin(fs, file_path)); 140 | draw_rebooting(display); 141 | draw_loading_bar(display, loadingDelay); 142 | 143 | ESP.restart(); 144 | } 145 | } 146 | } 147 | 148 | // free memory of file list and cursor 149 | delete_u_file_list(fl); 150 | delete_u_cursor(c); 151 | 152 | display_clear(display); 153 | } 154 | 155 | void DstikeUpdater::runSH1106(int sda, int sck, int up, int down, int select, const char* path, int loadingDelay) { 156 | SH1106Wire display(0x3c, sda, sck); 157 | 158 | run(display, up, down, select, path, loadingDelay); 159 | display.end(); 160 | } 161 | 162 | void DstikeUpdater::runSSD1306(int sda, int sck, int up, int down, int select, const char* path, int loadingDelay) { 163 | SSD1306 display(0x3c, sda, sck); 164 | 165 | run(display, up, down, select, path, loadingDelay); 166 | display.end(); 167 | } -------------------------------------------------------------------------------- /src/DstikeUpdater.h: -------------------------------------------------------------------------------- 1 | #ifndef DstikeUpdater_h 2 | #define DstikeUpdater_h 3 | 4 | #include // OLED 5 | #include // OLED 6 | 7 | #ifndef UPDATER_PATH 8 | #define UPDATER_PATH "/update" 9 | #endif // ifndef BUTTON_SELECT 10 | 11 | #ifndef LOADING_DELAY 12 | #define LOADING_DELAY 3500 13 | #endif // ifndef BUTTON_SELECT 14 | 15 | #define DSTIKE_UPDATER_V_1_0_0 16 | 17 | class DstikeUpdater { 18 | public: 19 | static void run(OLEDDisplay& display, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 20 | static void runSH1106(int sda, int sck, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 21 | static void runSSD1306(int sda, int sck, int up, int down, int select, const char* path = UPDATER_PATH, int loadingDelay = LOADING_DELAY); 22 | }; 23 | #endif // ifndef DstikeUpdater_h -------------------------------------------------------------------------------- /src/io/display.cpp: -------------------------------------------------------------------------------- 1 | #include "display.h" 2 | 3 | // [ ===== Init ===== ] // 4 | bool init_display(OLEDDisplay& display) { 5 | display.init(); 6 | display.flipScreenVertically(); 7 | display.setFont(ArialMT_Plain_10); 8 | 9 | display_clear(display); 10 | display_show(display); 11 | 12 | return true; 13 | } 14 | 15 | // [ ===== Show ===== ] // 16 | void display_show(OLEDDisplay& display) { 17 | display.display(); 18 | } 19 | 20 | // [ ===== Clear ===== ] // 21 | void display_clear(OLEDDisplay& display) { 22 | display.clear(); 23 | } 24 | 25 | // [ ===== Headline ===== ] // 26 | void draw_headline(OLEDDisplay& display) { 27 | display.drawString(0, 0, F("[ ==== SD UPDATE ==== ] ")); 28 | display.drawLine(0, 13, 128, 13); 29 | display_show(display); 30 | } 31 | 32 | // [ ===== String ===== ] // 33 | void draw_string(OLEDDisplay& display, int row, const String& str) { 34 | display.drawString(0, 14 + (row*12), str); 35 | } 36 | 37 | // [ ===== String_F ===== ] // 38 | void draw_string_f(OLEDDisplay& display, int row, const __FlashStringHelper* str) { 39 | display.drawString(0, 14 + (row*12), str); 40 | } 41 | 42 | // [ ===== BAR ===== ] // 43 | void draw_bar(OLEDDisplay& display, int len) { 44 | display.drawLine(0, 62, len, 62); 45 | display.drawLine(0, 63, len, 63); 46 | } 47 | 48 | // [ ===== N0 SD ===== ] // 49 | void draw_no_sd(OLEDDisplay& display) { 50 | draw_string_f(display, 0, F("No SD detected :(")); 51 | draw_string_f(display, 1, F("Loading default...")); 52 | } 53 | 54 | // [ ===== Update ===== ] // 55 | void draw_update(OLEDDisplay& display) { 56 | draw_string_f(display, 0, F("Click to update")); 57 | } 58 | 59 | // [ ===== Canceled ===== ] // 60 | void draw_canceled(OLEDDisplay& display) { 61 | draw_string_f(display, 0, F("Canceled Update")); 62 | draw_string_f(display, 1, F("Resuming programm...")); 63 | } 64 | 65 | // [ ===== Flashing ===== ] // 66 | void draw_flashing(OLEDDisplay& display) { 67 | draw_string_f(display, 0, F("Flashing...")); 68 | } 69 | 70 | // [ ===== Rebooting ===== ] // 71 | void draw_rebooting(OLEDDisplay& display) { 72 | draw_string_f(display, 2, F("Rebooting...")); 73 | } 74 | 75 | // [ ===== Loading Bar ===== ] // 76 | void draw_loading_bar(OLEDDisplay& display, unsigned long loading_time) { 77 | unsigned long start_time = millis(); 78 | unsigned long end_time = start_time + loading_time; 79 | 80 | while (millis() < end_time) { 81 | draw_bar(display, (millis() - start_time) / (loading_time/128)); 82 | display.display(); 83 | delay(50); 84 | } 85 | } -------------------------------------------------------------------------------- /src/io/display.h: -------------------------------------------------------------------------------- 1 | #ifndef display_h 2 | #define display_h 3 | 4 | #include // OLED 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif /* ifdef __cplusplus */ 9 | 10 | bool init_display(OLEDDisplay& display); 11 | 12 | void display_show(OLEDDisplay& display); 13 | void display_clear(OLEDDisplay& display); 14 | 15 | void draw_headline(OLEDDisplay& display); 16 | 17 | void draw_string(OLEDDisplay& display, int row, const String& str); 18 | void draw_string_f(OLEDDisplay& display, int row, const __FlashStringHelper* str); 19 | 20 | void draw_bar(OLEDDisplay& display, int len); 21 | void draw_invalid_path(OLEDDisplay& display); 22 | void draw_no_sd(OLEDDisplay& display); 23 | void draw_update(OLEDDisplay& display); 24 | void draw_canceled(OLEDDisplay& display); 25 | void draw_flashing(OLEDDisplay& display); 26 | void draw_rebooting(OLEDDisplay& display); 27 | void draw_loading_bar(OLEDDisplay& display, unsigned long loading_time); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif /* ifdef __cplusplus */ 32 | 33 | #endif /* ifndef sd_h */ -------------------------------------------------------------------------------- /src/io/gpio.cpp: -------------------------------------------------------------------------------- 1 | #include "gpio.h" 2 | #include "Arduino.h" // pinMode(), digitalRead() 3 | 4 | void init_buttons(int up, int down, int select) { 5 | pinMode(up, INPUT_PULLUP); 6 | pinMode(down, INPUT_PULLUP); 7 | pinMode(select, INPUT_PULLUP); 8 | } 9 | 10 | bool pressed(int pin) { 11 | return digitalRead(pin) == LOW; 12 | } 13 | 14 | bool pressed_any(int up, int down, int select) { 15 | return pressed(up) || pressed(down) || pressed(select); 16 | } -------------------------------------------------------------------------------- /src/io/gpio.h: -------------------------------------------------------------------------------- 1 | #ifndef gpio_h 2 | #define gpio_h 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif /* ifdef __cplusplus */ 7 | 8 | void init_buttons(int up, int down, int select); 9 | bool pressed(int pin); 10 | bool pressed_any(int up, int down, int select); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif /* ifdef __cplusplus */ 15 | 16 | #endif /* ifndef gpio_h */ -------------------------------------------------------------------------------- /src/io/sd.cpp: -------------------------------------------------------------------------------- 1 | #include "sd.h" 2 | 3 | fs::FS& get_sd_fs() { 4 | return SD_MMC; 5 | } 6 | 7 | bool init_sd() { 8 | if (!SD_MMC.begin()) return false; 9 | if (SD_MMC.cardType() == CARD_NONE) return false; 10 | 11 | return true; 12 | } -------------------------------------------------------------------------------- /src/io/sd.h: -------------------------------------------------------------------------------- 1 | #ifndef sd_h 2 | #define sd_h 3 | 4 | #include // File System 5 | #include // SD/MMC Card 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif /* ifdef __cplusplus */ 10 | 11 | fs::FS& get_sd_fs(); 12 | bool init_sd(); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif /* ifdef __cplusplus */ 17 | 18 | #endif /* ifndef sd_h */ -------------------------------------------------------------------------------- /src/memory/flasher.cpp: -------------------------------------------------------------------------------- 1 | #include "flasher.h" 2 | 3 | const __FlashStringHelper* flash_bin(fs::FS& fs, const char* path) { 4 | File bin = fs.open(path); 5 | 6 | if (!bin) { 7 | bin.close(); 8 | return F("File could not be opened"); 9 | } 10 | 11 | if (bin.isDirectory()) { 12 | bin.close(); 13 | return F("File is a directory"); 14 | } 15 | 16 | size_t updateSize = bin.size(); 17 | Stream& updateSource = bin; 18 | 19 | if (!Update.begin(updateSize)) { 20 | bin.close(); 21 | return F("Not enough space to update"); 22 | } 23 | 24 | size_t written = Update.writeStream(updateSource); 25 | 26 | if (!Update.end()) { 27 | bin.close(); 28 | return F("Error"); // Update.getError(); 29 | } 30 | 31 | if (!Update.isFinished()) { 32 | bin.close(); 33 | return F("Couldn't finish update"); 34 | } 35 | 36 | bin.close(); 37 | return F("Update finished"); 38 | } -------------------------------------------------------------------------------- /src/memory/flasher.h: -------------------------------------------------------------------------------- 1 | #ifndef flasher_h 2 | #define flasher_h 3 | 4 | #include // File System 5 | #include // Update 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif /* ifdef __cplusplus */ 10 | 11 | const __FlashStringHelper* flash_bin(fs::FS& fs, const char* path); 12 | 13 | #ifdef __cplusplus 14 | } 15 | #endif /* ifdef __cplusplus */ 16 | 17 | #endif /* ifndef flasher_h */ -------------------------------------------------------------------------------- /src/memory/updater_file_list_mgmt.cpp: -------------------------------------------------------------------------------- 1 | #include "updater_file_list_mgmt.h" 2 | 3 | u_file_list* get_u_file_list(fs::FS& fs, const char* path) { 4 | u_file_list* list = create_u_file_list(); 5 | File dir = fs.open(path); 6 | 7 | if (!dir) return list; 8 | 9 | u_file_node* tmp_file = create_u_file_node("Cancel"); 10 | list->begin = tmp_file; 11 | list->end = tmp_file; 12 | list->size++; 13 | 14 | File f = dir.openNextFile(); 15 | 16 | while (f) { 17 | if (!f.isDirectory() && (strcmp(strrchr(f.name(), '.'), ".bin") == 0)) { 18 | tmp_file = create_u_file_node(f.name()); 19 | list->end->next = tmp_file; 20 | list->end = tmp_file; 21 | list->size++; 22 | } 23 | 24 | f = dir.openNextFile(); 25 | } 26 | 27 | return list; 28 | } 29 | 30 | const char* get_file_path(u_cursor* cursor, int entries_per_page) { 31 | if (cursor && cursor->list) { 32 | u_file_node* tmp_node = cursor->list->begin; 33 | int i = 0; 34 | int j = 0; 35 | 36 | while (tmp_node && i < cursor->page * entries_per_page) { 37 | tmp_node = tmp_node->next; 38 | ++i; 39 | } 40 | 41 | while (tmp_node && j < cursor->pos) { 42 | tmp_node = tmp_node->next; 43 | ++j; 44 | } 45 | 46 | if (tmp_node) return tmp_node->path; 47 | } 48 | return NULL; 49 | } -------------------------------------------------------------------------------- /src/memory/updater_file_list_mgmt.h: -------------------------------------------------------------------------------- 1 | #ifndef updater_file_list_mgmt_h 2 | #define updater_file_list_mgmt_h 3 | 4 | #include // File System 5 | 6 | #include "updater_file_list/updater_file_node.h" 7 | #include "updater_file_list/updater_file_list.h" 8 | #include "updater_file_list/updater_cursor.h" 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif /* ifdef __cplusplus */ 13 | 14 | u_file_list* get_u_file_list(fs::FS& fs, const char* path); 15 | const char* get_file_path(u_cursor* cursor, int entries_per_page); 16 | 17 | #ifdef __cplusplus 18 | } 19 | #endif /* ifdef __cplusplus */ 20 | 21 | #endif /* ifndef updater_file_list_mgmt_h */ -------------------------------------------------------------------------------- /src/updater_file_list/updater_cursor.cpp: -------------------------------------------------------------------------------- 1 | #include "updater_cursor.h" 2 | 3 | u_cursor* create_u_cursor(u_file_list* l) { 4 | if (!l) return NULL; 5 | u_cursor* c = (u_cursor*)malloc(sizeof(u_cursor)); 6 | c->page = 0; 7 | c->pos = 0; 8 | c->list = l; 9 | return c; 10 | } 11 | 12 | void delete_u_cursor(u_cursor* c) { 13 | free(c); 14 | } 15 | 16 | void u_cursor_up(u_cursor* cursor, int entries_per_page) { 17 | if (cursor && ((cursor->page > 0) || (cursor->pos > 0))) { 18 | cursor->pos--; 19 | if (cursor->pos < 0) { 20 | cursor->pos = entries_per_page - 1; 21 | cursor->page--; 22 | } 23 | } 24 | } 25 | 26 | void u_cursor_down(u_cursor* cursor, int entries_per_page) { 27 | if (cursor && cursor->list && (cursor->page * entries_per_page + cursor->pos < cursor->list->size - 1)) { 28 | cursor->pos++; 29 | if (cursor->pos >= entries_per_page) { 30 | cursor->pos = 0; 31 | cursor->page++; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/updater_file_list/updater_cursor.h: -------------------------------------------------------------------------------- 1 | #ifndef updater_cursor_h 2 | #define updater_cursor_h 3 | 4 | #include 5 | #include "updater_file_list/updater_file_list.h" 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif /* ifdef __cplusplus */ 10 | 11 | typedef struct u_cursor { 12 | int page; 13 | int pos; 14 | struct u_file_list* list; 15 | } u_cursor; 16 | 17 | u_cursor* create_u_cursor(u_file_list* l); 18 | void delete_u_cursor(u_cursor* c); 19 | void u_cursor_up(u_cursor* cursor, int entries_per_page); 20 | void u_cursor_down(u_cursor* cursor, int entries_per_page); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif /* ifdef __cplusplus */ 25 | 26 | #endif /* ifndef updater_cursor_h */ -------------------------------------------------------------------------------- /src/updater_file_list/updater_file_list.cpp: -------------------------------------------------------------------------------- 1 | #include "updater_file_list.h" 2 | 3 | u_file_list* create_u_file_list() { 4 | u_file_list* l = (u_file_list*)malloc(sizeof(u_file_list)); 5 | 6 | l->begin = NULL; 7 | l->end = NULL; 8 | l->size = 0; 9 | return l; 10 | } 11 | 12 | void delete_u_file_list(u_file_list* l) { 13 | if (l) { 14 | delete_u_file_node(l->begin); 15 | free(l); 16 | } 17 | } -------------------------------------------------------------------------------- /src/updater_file_list/updater_file_list.h: -------------------------------------------------------------------------------- 1 | #ifndef updater_file_list_h 2 | #define updater_file_list_h 3 | 4 | 5 | #include 6 | #include "updater_file_list/updater_file_node.h" 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif /* ifdef __cplusplus */ 11 | 12 | typedef struct u_file_list { 13 | struct u_file_node* begin; 14 | struct u_file_node* end; 15 | int size; 16 | } u_file_list; 17 | 18 | u_file_list* create_u_file_list(); 19 | void delete_u_file_list(u_file_list* l); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif /* ifdef __cplusplus */ 24 | 25 | #endif /* ifndef updater_file_list_h */ -------------------------------------------------------------------------------- /src/updater_file_list/updater_file_node.cpp: -------------------------------------------------------------------------------- 1 | #include "updater_file_node.h" 2 | 3 | u_file_node* create_u_file_node(const char* path) { 4 | u_file_node* n = (u_file_node*)malloc(sizeof(u_file_node)); 5 | 6 | char* name = strrchr(path, '/'); 7 | 8 | if (!name) name = (char*)path; 9 | 10 | n->name = (char*)malloc(strlen(name) + 1); 11 | n->path = (char*)malloc(strlen(path) + 1); 12 | n->next = NULL; 13 | 14 | strcpy(n->name, name); 15 | strcpy(n->path, path); 16 | 17 | return n; 18 | } 19 | 20 | void delete_u_file_node(u_file_node* n) { 21 | if (n) { 22 | free(n->name); 23 | free(n->path); 24 | delete_u_file_node(n->next); 25 | free(n); 26 | } 27 | } -------------------------------------------------------------------------------- /src/updater_file_list/updater_file_node.h: -------------------------------------------------------------------------------- 1 | #ifndef updater_file_node_h 2 | #define updater_file_node_h 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif /* ifdef __cplusplus */ 10 | 11 | typedef struct u_file_node { 12 | char * name; 13 | char * path; 14 | struct u_file_node* next; 15 | } u_file_node; 16 | 17 | u_file_node* create_u_file_node(const char* path); 18 | void delete_u_file_node(u_file_node* n); 19 | 20 | #ifdef __cplusplus 21 | } 22 | #endif /* ifdef __cplusplus */ 23 | 24 | #endif /* ifndef updater_file_node_h */ --------------------------------------------------------------------------------