Skip to content

Commit

Permalink
main: RTOS demos & Lua runner from SD card
Browse files Browse the repository at this point in the history
  • Loading branch information
and3rson committed Mar 8, 2024
1 parent 19d6bd1 commit e29e03d
Show file tree
Hide file tree
Showing 49 changed files with 608 additions and 397 deletions.
14 changes: 0 additions & 14 deletions firmware/main/bak/demos.h

This file was deleted.

33 changes: 25 additions & 8 deletions firmware/main/src/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,33 @@ App::App(const char *name, uint16_t x, uint16_t y, uint16_t w, uint16_t h) : nam
}

void App::start() {
xTaskCreate(
[](void *app) {
App *a = (App *)app;
a->run();
},
name, 4096, this, 1, NULL
);
Serial.println("Starting app " + String(name));
xTaskCreate(_run, name, 32768, this, 1, &taskHandle);
}

void App::_run(void *data) {
App *app = (App *)data;
app->run();
if (app->getState() != eTaskState::eDeleted) {
// App might have been stopped by itself. If not, stop it, or we'll get panic from FreeRTOS kernel.
app->stop();
}
}

void App::suspend() {
// TODO: Check if the task is already suspended
Serial.println("Suspending app " + String(name) + " (state = " + String(getState()) + ")");
vTaskSuspend(taskHandle);
}

void App::resume() {
// TODO: Check if the task is already running
Serial.println("Resuming app " + String(name) + " (state = " + String(getState()) + ")");
vTaskResume(taskHandle);
}

void App::stop() {
Serial.println("Stopping app " + String(name) + " (state = " + String(getState()) + ")");
vTaskDelete(taskHandle);
}

Expand All @@ -42,12 +49,19 @@ App::~App() {
}
void App::queueDraw() {
// Swap the front and back canvases
// Serial.println("Queuing draw for " + String(name) + ", canvas address = " + String((uint32_t)canvas));
xSemaphoreTake(backCanvasMutex, portMAX_DELAY);
lilka::Canvas *temp = canvas;
canvas = backCanvas;
backCanvas = temp;
xSemaphoreGive(backCanvasMutex);
dirty = true;
// uint64_t now = micros();
// Too slow...
// memcpy(
// canvas->getFramebuffer(), backCanvas->getFramebuffer(), canvas->width() * canvas->height() * 2
// ); // TODO: Hard-coded 2 bytes per pixel
// Serial.println("Copy took " + String(micros() - now) + "us");
xSemaphoreGive(backCanvasMutex);
taskYIELD();
}

Expand All @@ -72,5 +86,8 @@ void App::releaseBackCanvas() {
}

eTaskState App::getState() {
if (taskHandle == NULL) {
return eTaskState::eInvalid;
}
return eTaskGetState(taskHandle);
}
5 changes: 2 additions & 3 deletions firmware/main/src/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class App {
void suspend();
void resume();
void stop();
static void _run(void *data);
virtual void run() = 0;
void queueDraw();
bool needsRedraw();
Expand All @@ -24,10 +25,8 @@ class App {

eTaskState getState();

lilka::Canvas *backCanvas;

protected:
lilka::Canvas *canvas;
lilka::Canvas *backCanvas;

private:
const char *name;
Expand Down
11 changes: 5 additions & 6 deletions firmware/main/src/appmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,15 @@ void AppManager::loop() {
xSemaphoreTake(mutex, portMAX_DELAY);

// Draw panel
panel->acquireBackCanvas();
if (panel->needsRedraw()) {
Serial.println("Redrawing panel");
panel->acquireBackCanvas();
lilka::display.draw16bitRGBBitmap(
panel->backCanvas->x(), panel->backCanvas->y(), panel->backCanvas->getFramebuffer(),
panel->backCanvas->width(), panel->backCanvas->height()
);
panel->releaseBackCanvas();
panel->markClean();
}
panel->releaseBackCanvas();

// Check if top app has finished
App *topApp = apps.back();
Expand All @@ -78,15 +77,15 @@ void AppManager::loop() {
}

// Draw top app
topApp->acquireBackCanvas();
if (topApp->needsRedraw()) {
Serial.println("Redrawing " + String(topApp->getName()));
topApp->acquireBackCanvas();
lilka::display.draw16bitRGBBitmap(
topApp->backCanvas->x(), topApp->backCanvas->y(), topApp->backCanvas->getFramebuffer(),
topApp->backCanvas->width(), topApp->backCanvas->height()
);
topApp->releaseBackCanvas();
topApp->markClean();
}
topApp->releaseBackCanvas();

xSemaphoreGive(mutex);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <lilka.h>
#include "ball.h"

void demo_ball(lilka::Canvas *canvas) {
BallApp::BallApp() : App("Ball") {}

void BallApp::run() {
float x = (float)canvas->width() / 2;
float y = (float)canvas->height() / 4;
float xVelo = 320, yVelo = 0;
Expand All @@ -10,8 +12,6 @@ void demo_ball(lilka::Canvas *canvas) {
while (1) {
float delta = (millis() - prevRenderTime) / 1000.0;

canvas->fillScreen(canvas->color565(0, 0, 0));

yVelo += gravity * delta;
x += xVelo * delta;
y += yVelo * delta;
Expand All @@ -26,7 +26,6 @@ void demo_ball(lilka::Canvas *canvas) {
y = y < radius ? radius : canvas->height() - radius;
}

canvas->fillCircle(x, y, radius, canvas->color565(255, 200, 0));
lilka::State state = lilka::controller.getState();
if (state.a.justPressed) {
return;
Expand All @@ -40,9 +39,13 @@ void demo_ball(lilka::Canvas *canvas) {
xVelo = 500;
}

canvas->fillScreen(canvas->color565(0, 0, 0));
canvas->fillCircle(x, y, radius, canvas->color565(255, 200, 0));
// Calculate FPS
canvas->setCursor(16, 32);
canvas->println("FPS: " + String(1000 / (millis() - prevRenderTime)));

prevRenderTime = millis();
queueDraw();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

#include "app.h"

class HUDApp : public App {
class BallApp : public App {
public:
HUDApp();
BallApp();
void run();
};
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include <lilka.h>
#include "disk.h"

void demo_disc(lilka::Canvas *canvas) {
DiskApp::DiskApp() : App("Disk") {}

void DiskApp::run() {
float x = random(16, canvas->width() - 16);
float y = random(16, canvas->height() - 16);
float xDir = 3;
float yDir = 3;
int16_t radius = 16;
uint64_t prevRenderTime = millis();
while (1) {
canvas->fillScreen(canvas->color565(0, 0, 0));
x += xDir;
y += yDir;
bool hit = false;
Expand All @@ -26,15 +27,15 @@ void demo_disc(lilka::Canvas *canvas) {
xDir = xDirNew;
yDir = yDirNew;
}
canvas->drawCircle(x, y, radius, 0xFFFF);
if (lilka::controller.getState().a.justPressed) {
return;
}

// Calculate FPS
canvas->fillScreen(canvas->color565(0, 0, 0));
canvas->drawCircle(x, y, radius, 0xFFFF);
canvas->setCursor(16, 32);
canvas->println("FPS: " + String(1000 / (millis() - prevRenderTime)));
prevRenderTime = millis();
vTaskDelay(0);
queueDraw();
}
}
9 changes: 9 additions & 0 deletions firmware/main/src/apps/demos/disk.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "app.h"

class DiskApp : public App {
public:
DiskApp();
void run();
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include <lilka.h>
#include "epilepsy.h"

void demo_epilepsy(lilka::Canvas *canvas) {
EpilepsyApp::EpilepsyApp() : App("Epilepsy") {}

void EpilepsyApp::run() {
while (1) {
float time = millis() / 1000.0;
float size = sin(time * PI * 1.5) * LILKA_DISPLAY_WIDTH;
Expand All @@ -20,6 +22,7 @@ void demo_epilepsy(lilka::Canvas *canvas) {
};
canvas->fillTriangle(points[0][0], points[0][1], points[1][0], points[1][1], points[2][0], points[2][1], color);
canvas->fillTriangle(points[0][0], points[0][1], points[2][0], points[2][1], points[3][0], points[3][1], color);
queueDraw();

if (lilka::controller.getState().a.justPressed) {
return;
Expand Down
9 changes: 9 additions & 0 deletions firmware/main/src/apps/demos/epilepsy.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "app.h"

class EpilepsyApp : public App {
public:
EpilepsyApp();
void run();
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include <lilka.h>

#include "letris.h"
#include "letris_splash.h"

#define BLOCK_SIZE 10
Expand Down Expand Up @@ -173,7 +172,9 @@ class Field {
lilka::Canvas *canvas;
};

void demo_letris(lilka::Canvas *canvas) {
LetrisApp::LetrisApp() : App("Letris") {}

void LetrisApp::run() {
// Створюємо поле та фігуру
Field field(canvas);
Shape shape(canvas);
Expand Down Expand Up @@ -239,7 +240,7 @@ void demo_letris(lilka::Canvas *canvas) {
fastDrop = true;
nextMove = 0;
}
// Чи може фігура рухатися в горизонтально?
// Чи може фігура рухатися горизонтально?
if (field.willCollide(&shape, dx, 0)) {
// Ні, фігура зіткнеться зі стіною. Змінюємо напрямок руху на 0
dx = 0;
Expand All @@ -250,6 +251,7 @@ void demo_letris(lilka::Canvas *canvas) {
field.draw();
shape.draw();
nextShape.draw(true);
queueDraw();
// Відображаємо зміни на екрані
// lilka::display.renderCanvas(canvas);
}
Expand All @@ -269,5 +271,15 @@ void demo_letris(lilka::Canvas *canvas) {

// Гра закінчилася. Виводимо повідомлення на екран
// TODO: FreeRTOS experiment
lilka::ui_alert(canvas, "Game over", "Гру завершено!\nТи намагався. :)");
// lilka::ui_alert(canvas, "Game over", "Гру завершено!\nТи намагався. :)");
lilka::Alert alert("Game over", "Гру завершено!\nТи намагався. :)");
alert.draw(canvas);
queueDraw();
while (1) {
alert.update();
if (alert.isDone()) {
break;
}
taskYIELD();
}
}
9 changes: 9 additions & 0 deletions firmware/main/src/apps/demos/letris.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include "app.h"

class LetrisApp : public App {
public:
LetrisApp();
void run();
};
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void DemoLines::run() {
canvas->drawLine(x1, y1, x2, y2, color);
queueDraw();
if (lilka::controller.getState().a.justPressed) {
vTaskDelete(NULL);
stop();
return;
}
vTaskDelay(30 / portTICK_PERIOD_MS);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#ifndef DEMO_LINES_H
#define DEMO_LINES_H
#pragma once

#include "app.h"
#include "lilka.h"
Expand All @@ -9,5 +8,3 @@ class DemoLines : public App {
DemoLines();
void run();
};

#endif //DEMO_LINES_H
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
#include <Arduino.h>
#include <Wire.h>

#include <lilka.h>
#include "scan_i2c.h"

void demo_scan_i2c(lilka::Canvas *canvas) {
ScanI2CApp::ScanI2CApp() : App("I2C Scanner") {}

void ScanI2CApp::run() {
Wire.begin(9, 10, 100000);

canvas->fillScreen(canvas->color565(0, 0, 0));
canvas->setTextBound(4, 0, LILKA_DISPLAY_WIDTH - 8, LILKA_DISPLAY_HEIGHT);
canvas->setCursor(4, 48);

canvas->println("Starting I2C scan...");
queueDraw();

uint8_t found = 0;
for (uint16_t address = 1; address <= 127; address++) {
Expand All @@ -30,10 +32,11 @@ void demo_scan_i2c(lilka::Canvas *canvas) {

canvas->println("I2C scan done.");
canvas->printf("Found %d devices.", found);
queueDraw();

Wire.end();

while (!lilka::controller.getState().a.justPressed) {
delay(10);
taskYIELD();
}
}
Loading

0 comments on commit e29e03d

Please sign in to comment.