Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store firmware path when running firmwares from SD card #10

Merged
merged 5 commits into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/keira/features.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Keira підтримує запуск другорядних прошивок з
- Вам не потрібно щоразу перепрошивати Лілку, щоб випробувати другорядні прошивки: просто скопіюйте їх на SD-картку.
- Ви можете ділитися своїми скомпільованими прошивками (у вигляді ``.bin``-файлів) з іншими користувачами Лілки, без необхідності відправляти їм весь код вашої власної прошивки.

Найяскравіший приклад використання цієї функції - запуск Doom. Достатньо скопіювати в корінь SD-карти файли ``doom.bin`` і ``doom.wad`` (або ``doom1.wad``), і ви зможете грати в Doom!
Найяскравіший приклад використання цієї функції - запуск Doom. Достатньо скопіювати на SD-карту файли ``doom.bin`` і ``doom.wad`` (або ``doom1.wad``), і ви зможете грати в Doom!

.. note:: Щоб отримати ``doom.bin``, вам потрібно скомпілювати прошивку, що знаходиться в папці ``firmware/doom``, і тоді скопіювати файл ``doom.bin`` на SD-картку.

Expand Down
4 changes: 2 additions & 2 deletions docs/keira/lua/reference/lilka.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

Ви повинні визначити її в своєму коді, якщо ви хочете використовувати її для оновлення вашої програми.

.. lua:function:: render()
.. lua:function:: draw()

Ця функція автоматично викликається після `lilka.update`. Тут відбувається відображення графіки.

Expand All @@ -32,4 +32,4 @@
.. lua:autoclass:: lilka

.. Does not work with aliases... So we have to copy-paste the stuff above.
.. :members: init, update, render
.. :members: init, update, draw
19 changes: 16 additions & 3 deletions firmware/doom/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,22 @@ void setup() {
char arg[] = "doomgeneric";
char arg2[] = "-iwad";
char arg3[64];

// Get firmware arg
String firmwareFile = lilka::multiboot.getFirmwarePath();
lilka::serial_log("Firmware file: %s\n", firmwareFile.c_str());
String firmwareDir;
if (firmwareFile.length()) {
// Get directory from firmware file
int lastSlash = firmwareFile.lastIndexOf('/');
firmwareDir = firmwareFile.substring(0, lastSlash);
} else {
firmwareDir = "/";
}

bool found = false;
// Find the wad file
File root = SD.open("/");
// Find the WAD file
File root = SD.open(firmwareDir.c_str());
File file;
while ((file = root.openNextFile())) {
if (file.isDirectory()) {
Expand All @@ -118,7 +131,7 @@ void setup() {
name.toLowerCase();
lilka::serial_log("Checking file: %s\n", name.c_str());
if (name.startsWith("doom") && name.endsWith(".wad")) {
strcpy(arg3, (String("/sd/") + file.name()).c_str());
strcpy(arg3, (String("/sd") + firmwareDir + "/" + file.name()).c_str());
lilka::serial_log("Found .WAD file: %s\n", arg3);
found = true;
file.close();
Expand Down
2 changes: 1 addition & 1 deletion firmware/keira/sdcard/counter/counter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ state.counter = state.counter + 1
display.fill_screen(display.color565(64, 0, 64))
display.set_cursor(0, 64)
display.print('Лічильник запусків\nпрограми: ', state.counter)
display.render()
display.queue_draw()
util.sleep(0.5)
7 changes: 3 additions & 4 deletions firmware/keira/sdcard/test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,11 @@ for i = 10, 1, -1 do
local y = math.random(280 - 64)
display.draw_image(face, x, y)

display.render()
display.queue_draw()

util.sleep(0.25)
end

-- Now, we want to draw random lines & faces really fast directly to display, without any buffering!
display.set_buffered(false)

local key = controller.get_state()
while not key.a.just_pressed do
local x1 = math.random(240)
Expand All @@ -34,5 +31,7 @@ while not key.a.just_pressed do
local y = math.random(280 - 64)
display.draw_image(face, x, y)

display.queue_draw()

key = controller.get_state()
end
9 changes: 5 additions & 4 deletions firmware/keira/src/apps/launcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void LauncherApp::sdBrowserMenu(String path) {
queueDraw();
}
int16_t index = menu.getCursor();
if (index >= numEntries - 1) break;
if (index == numEntries) break;
if (entries[index].type == lilka::EntryType::ENT_DIRECTORY) {
sdBrowserMenu(path + entries[index].name + "/");
} else {
Expand Down Expand Up @@ -229,15 +229,16 @@ void LauncherApp::selectFile(String path) {
alert("Помилка", "Ця операція потребує Лілку 2.0");
return;
#else
lilka::ProgressDialog dialog("Завантаження", path + "\n\nПочинаємо...");
dialog.draw(canvas);
queueDraw();
int error;
error = lilka::multiboot.start(path);
if (error) {
alert("Помилка", String("Етап: 1\nКод: ") + error);
return;
}
lilka::ProgressDialog dialog(
"Завантаження", path + "\nРозмір: " + String(lilka::multiboot.getBytesTotal()) + " Б"
);
dialog.setMessage(path + "\n\nРозмір: " + String(lilka::multiboot.getBytesTotal()) + " Б");
dialog.draw(canvas);
queueDraw();
while ((error = lilka::multiboot.process()) > 0) {
Expand Down
2 changes: 1 addition & 1 deletion sdk/addons/lualilka/library/lilka.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ lilka = {}
---Ця функція автоматично викликається після `lilka.update`. Тут відбувається відображення графіки.
---
---Ви повинні визначити її в своєму коді, якщо ви хочете використовувати її для малювання вашої програми.
---@alias lilka.render fun()
---@alias lilka.draw fun()

return lilka
2 changes: 1 addition & 1 deletion sdk/addons/lualilka/library/state.lua
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@
--- display.fill_screen(display.color565(64, 0, 64))
--- display.set_cursor(0, 64)
--- display.print('Лічильник запусків\nпрограми: ', state.counter)
--- display.render()
--- display.queue_draw()
--- util.sleep(0.5)
state = {}
40 changes: 34 additions & 6 deletions sdk/lib/lilka/src/lilka/multiboot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int MultiBoot::start(String path) {
ota_partition = esp_ota_get_next_update_partition(current_partition); // get ota1 (we're in ota0 now)
if (ota_partition == NULL) {
serial_err("Failed to get next OTA partition");
return -3;
return -4;
}
serial_log(
"OTA partition: %s, type: %d, subtype: %d, size: %d",
Expand All @@ -137,7 +137,21 @@ int MultiBoot::start(String path) {
esp_err_t err = esp_ota_begin(ota_partition, bytesTotal, &ota_handle);
if (err != ESP_OK) {
serial_err("Failed to begin OTA: %d", err);
return -4;
return -5;
}

// Write path to last 256 bytes of the OTA partition
size_t partition_size = ota_partition->size;
size_t offset = partition_size - 256;
String arg = path;
// Remove "/sd" prefix
// TODO: Maybe we should use absolute path (including "/sd")?
if (arg.startsWith("/sd/")) {
arg = arg.substring(3);
}
if (esp_partition_write(ota_partition, offset, arg.c_str(), arg.length() + 1) != ESP_OK) {
serial_err("Failed to write arg to OTA partition");
return -6;
}

return 0;
Expand All @@ -159,13 +173,12 @@ int MultiBoot::process() {
esp_err_t err = esp_ota_write(ota_handle, buf, len);
if (err != ESP_OK) {
serial_err("Failed to write OTA: %d", err);
return -5;
return -7;
}

bytesWritten += len;
}

serial_log("Written %d bytes", bytesWritten);
return bytesWritten;
}

Expand Down Expand Up @@ -193,14 +206,14 @@ int MultiBoot::finishAndReboot() {
esp_err_t err = esp_ota_end(ota_handle);
if (err != ESP_OK) {
serial_err("Failed to end OTA: %d", err);
return -6;
return -8;
}

// Перевстановлення активного розділу на OTA-розділ (його буде запущено лише один раз, після чого активним залишиться основний розділ).
err = esp_ota_set_boot_partition(ota_partition);
if (err != ESP_OK) {
serial_err("Failed to set boot partition: %d", err);
return -7;
return -9;
}

// Запуск нової прошивки.
Expand All @@ -209,6 +222,21 @@ int MultiBoot::finishAndReboot() {
return 0; // unreachable
}

String MultiBoot::getFirmwarePath() {
size_t partition_size = current_partition->size;
size_t offset = partition_size - 256;
char buf[256];
if (esp_partition_read(current_partition, offset, buf, sizeof(buf)) != ESP_OK) {
serial_err("Failed to read firmware path from current partition");
return "";
}
if (static_cast<uint8_t>(buf[0]) == 0xFF) {
serial_err("Firmware path is not set");
return "";
}
return String(buf);
}

MultiBoot multiboot;

} // namespace lilka
2 changes: 2 additions & 0 deletions sdk/lib/lilka/src/lilka/multiboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ class MultiBoot {
/// \return <0 - у разі помилки. В разі успіху цей метод не повертається, оскільки пристрій перезавантажується.
int finishAndReboot();

String getFirmwarePath();

private:
String path;
FILE* file;
Expand Down
Loading