This commit is contained in:
2025-07-28 09:39:13 +02:00
parent 474a0b2a43
commit ab32731f4d
35 changed files with 6157 additions and 210 deletions

View File

@@ -9,5 +9,5 @@ idf_component_register(SRCS
src/shutdowner.cpp
src/buttons.cpp
src/power_helper.cpp
PRIV_REQUIRES spi_flash esp_driver_i2c driver
PRIV_REQUIRES spi_flash esp_driver_i2c driver sdk-esp
INCLUDE_DIRS "include")

View File

@@ -11,10 +11,30 @@ class DispTools {
public:
static DispTools& get();
void clear();
bool get_pixel(int x, int y);
void set_pixel(int x, int y);
void reset_pixel(int x, int y);
void clear() {
for (int y = 0; y < DISP_HEIGHT; y++) {
for (int x = 0; x < DISP_WIDTH; x++) {
disp_frame[y][x] = 1;
}
}
}
bool get_pixel(int x, int y) {
// if (x < 0 || x >= DISP_WIDTH || y < 0 || y >= DISP_HEIGHT)
// assert(false);
return disp_frame[y][x];
}
void reset_pixel(int x, int y) {
// if (x < 0 || x >= DISP_WIDTH || y < 0 || y >= DISP_HEIGHT)
// assert(false);
disp_frame[y][x] = true;
}
void set_pixel(int x, int y) {
// if (x < 0 || x >= DISP_WIDTH || y < 0 || y >= DISP_HEIGHT)
// assert(false);
//
disp_frame[y][x] = false;
}
void draw_rectangle(int x1, int y1, int x2, int y2);
void draw_line(int x1, int y1, int x2, int y2);
void draw_circle(int x, int y, int r);

View File

@@ -12,6 +12,9 @@
#include <array>
#include <bitset>
#include "Surface.hpp"
#include "Window.hpp"
class SMD {
public:
using disp_line_t = std::bitset<400>;
@@ -41,4 +44,27 @@ private:
std::array<uint8_t, kLineBytes> prep_line(const SMD::disp_line_t& line);
};
class SMDSurface : public Surface<SMDSurface, BwPixel>, public StandardEventQueue<SMDSurface> {
public:
SMDSurface(EventLoop* loop);
~SMDSurface() override;
void draw_pixel_impl(unsigned x, unsigned y, const BwPixel& pixel);
void clear_impl();
int get_width_impl() const;
int get_height_impl() const;
template<typename T>
EventHandlingResult handle(const T& event) {
return _window->handle(event);
}
EventHandlingResult handle(SurfaceResizeEvent event);
};
#endif // DISPLAY_HPP

View File

@@ -13,16 +13,6 @@ DispTools& DispTools::get() {
return disp_tools;
}
void DispTools::clear() {
for (int y = 0; y < DISP_HEIGHT; y++) {
for (int x = 0; x < DISP_WIDTH; x++) {
disp_frame[y][x] = 1;
}
}
}
bool DispTools::get_pixel(int x, int y) { return disp_frame[y][x]; }
void DispTools::reset_pixel(int x, int y) { disp_frame[y][x] = true; }
void DispTools::set_pixel(int x, int y) { disp_frame[y][x] = false; }
void DispTools::draw_rectangle(int x1, int y1, int x2, int y2) {
int dy = y2 - y1;
while (std::abs(dy) > 0) {

View File

@@ -9,6 +9,8 @@
#include <driver/gpio.h>
#include "driver/spi_master.h"
#include "disp_tools.hpp"
// This solution is attributed to Rich Schroeppel in the Programming Hacks section
// TODO: Why does the device flag not work?
unsigned char reverse_bits3(unsigned char b) { return (b * 0x0202020202ULL & 0x010884422010ULL) % 0x3ff; }
@@ -68,3 +70,24 @@ void SMD::draw(const disp_frame_t& frame) {
ESP_ERROR_CHECK(spi_device_transmit(_spi, &t));
}
}
void SMDSurface::draw_pixel_impl(unsigned x, unsigned y, const BwPixel& pixel) {
if (pixel.on)
DispTools::get().set_pixel(x, y);
else
DispTools::get().reset_pixel(x, y);
}
void SMDSurface::clear_impl() { DispTools::get().clear(); }
int SMDSurface::get_width_impl() const { return DISP_WIDTH; }
int SMDSurface::get_height_impl() const { return DISP_HEIGHT; }
EventHandlingResult SMDSurface::handle(SurfaceResizeEvent event) { return _window->handle(event); }
SMDSurface::SMDSurface(EventLoop* loop) :
Surface<SMDSurface, BwPixel>(),
EventQueue<SMDSurface, KeyboardEvent, SurfaceEvent, SurfaceResizeEvent>(loop, this) {}
SMDSurface::~SMDSurface() {}

View File

@@ -33,13 +33,19 @@
#include <spi_global.hpp>
#include <string>
#include <thread>
#include "GridWindow.hpp"
#include "TextWindow.hpp"
#include "display.hpp"
FbTty tty;
extern "C" void app_main() {
esp_pm_config_t pm_config = {
.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ, .min_freq_mhz = 16, .light_sleep_enable = true};
// ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
ESP_ERROR_CHECK(esp_pm_configure(&pm_config));
printf("Hello world!\n");
// TODO: Where to put that?
ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
@@ -58,7 +64,7 @@ extern "C" void app_main() {
SMD::get();
SMD::get().clear();
DispTools::get().clear();
DispTools::get().draw_line(0, 0, 400, 240);
DispTools::get().draw_line(0, 0, 399, 239);
DispTools::get().draw_circle(100, 100, 20);
DispTools::get().draw_to_display();
tty.putstr("Hello\nworld!");
@@ -68,21 +74,59 @@ extern "C" void app_main() {
int lastmove = 0;
EventLoop loop;
SMDSurface surface(&loop);
surface.set_window<GridWindow<SMDSurface, BwPixel, 2, 2>>();
GridWindow<SMDSurface, BwPixel, 2, 2>* window =
static_cast<GridWindow<SMDSurface, BwPixel, 2, 2>*>(surface.get_window());
window->set_window<TextWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, std::string>>(0, 0, &loop, "hello");
window->set_window<TextWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, std::string>>(0, 1, &loop, "hello1");
window->set_window<GridWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, 2, 2>>(1, 0);
GridWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, 2, 2>* window2 =
static_cast<GridWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, 2, 2>*>(
window->get_subsurface(1, 0).get_window());
window->set_window<TextWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, std::string>>(1, 1, &loop, "hello3");
window2->set_window<TextWindow<SubSurface<SubSurface<SMDSurface, BwPixel>, BwPixel>, BwPixel, std::string>>(
0, 0, &loop, "hello2");
window2->set_window<TextWindow<SubSurface<SubSurface<SMDSurface, BwPixel>, BwPixel>, BwPixel, std::string>>(
0, 1, &loop, "hello4");
window2->set_window<TextWindow<SubSurface<SubSurface<SMDSurface, BwPixel>, BwPixel>, BwPixel, std::string>>(
1, 0, &loop, "hello5");
window2->set_window<TextWindow<SubSurface<SubSurface<SMDSurface, BwPixel>, BwPixel>, BwPixel, std::string>>(
1, 1, &loop, "hello6");
auto* tl_text = static_cast<TextWindow<SubSurface<SMDSurface, BwPixel>, BwPixel, std::string>*>(
window->get_subsurface(0, 0).get_window());
surface.handle(SurfaceResizeEvent{DISP_WIDTH, DISP_HEIGHT});
std::thread loop_thread{[&] { loop.run([&] { DispTools::get().draw_to_display(); }); }};
uint8_t old_pressed = 0;
while (true) {
// SMD::clear();
// printf("Voltage: %f\n", BatMon::get_voltage());
DispTools::get().clear();
tty.reset();
// DispTools::get().clear();
// tty.reset();
uint8_t pressed = Buttons::get().get_pressed();
if (pressed & BTN_LEFT)
rx -= 5;
if (pressed & BTN_DOWN)
ry += 5;
if (pressed & BTN_UP)
ry -= 5;
if (pressed & BTN_RIGHT)
rx += 5;
if ((pressed & BTN_LEFT) && !(old_pressed & BTN_LEFT))
surface.push(KeyboardEvent{Key::Left});
if ((pressed & BTN_DOWN) && !(old_pressed & BTN_DOWN))
surface.push(KeyboardEvent{Key::Down});
if ((pressed & BTN_UP) && !(old_pressed & BTN_UP))
surface.push(KeyboardEvent{Key::Up});
if ((pressed & BTN_RIGHT) && !(old_pressed & BTN_RIGHT))
surface.push(KeyboardEvent{Key::Right});
if ((pressed & BTN_SELECT) && !(old_pressed & BTN_SELECT))
surface.push(KeyboardEvent{Key::Escape});
if ((pressed & BTN_START) && !(old_pressed & BTN_START))
surface.push(KeyboardEvent{Key::Enter});
old_pressed = pressed;
if (pressed == 0 && !PowerHelper::get().is_slow())
lastmove++;
@@ -97,26 +141,26 @@ extern "C" void app_main() {
}
bool slow = PowerHelper::get().is_slow();
tty.fmt("{:.1f}mA {:.1f}V {:.1f}mAh {}", BatMon::get().get_current(), BatMon::get().get_voltage(),
BatMon::get().get_charge(), slow ? "S" : "");
tl_text->push(TextUpdateEvent<std::string>(std::format("{:.1f}mA {:.1f}V {:.1f}mAh {}\n Buttons: {:08b}",
BatMon::get().get_current(), BatMon::get().get_voltage(),
BatMon::get().get_charge(), slow ? "S" : "", pressed)));
tty.fmt("Buttons: {:08b}", pressed);
if (rx < 30)
rx = 30;
if (rx > 370)
rx = 370;
if (ry < 30)
ry = 30;
if (ry > 210)
ry = 210;
// tty.fmt("Button: {}", pressed);
DispTools::get().draw_circle(rx, ry, 20);
// printf("Restarting in %d seconds...\n", i);
DispTools::get().draw_to_display();
// if (rx < 30)
// rx = 30;
// if (rx > 370)
// rx = 370;
// if (ry < 30)
// ry = 30;
// if (ry > 210)
// ry = 210;
// // tty.fmt("Button: {}", pressed);
// DispTools::get().draw_circle(rx, ry, 20);
// // printf("Restarting in %d seconds...\n", i);
// DispTools::get().draw_to_display();
PowerHelper::get().delay(10000, 30);
}
// printf("Restarting now.\n");
// fflush(stdout);
// esp_restart();
loop_thread.join();
}