diff --git a/release/files_common b/release/files_common index 91abab0de2..e38bc767ce 100644 --- a/release/files_common +++ b/release/files_common @@ -264,6 +264,7 @@ selfdrive/controls/lib/longitudinal_mpc_model/longitudinal_mpc.c selfdrive/hardware/__init__.py selfdrive/hardware/base.py +selfdrive/hardware/hw.h selfdrive/hardware/eon/__init__.py selfdrive/hardware/eon/apk.py selfdrive/hardware/eon/hardware.py diff --git a/selfdrive/hardware/hw.h b/selfdrive/hardware/hw.h new file mode 100644 index 0000000000..d646620dd9 --- /dev/null +++ b/selfdrive/hardware/hw.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +#include + +#ifdef QCOM +#define Hardware HardwareEon +#elif QCOM2 +#define Hardware HardwareTici +#else +#define Hardware HardwareNone +#endif + + +// no-op base hw class +class HardwareNone { +public: + static std::string get_os_version() { return "openpilot for PC"; }; + + static void reboot() {}; + static void poweroff() {}; + static void set_brightness(int percent) {}; +}; + +class HardwareEon : public HardwareNone { +public: + static std::string get_os_version() { + return "NEOS " + util::read_file("/VERSION"); + }; + + static void reboot() { std::system("reboot"); }; + static void poweroff() { std::system("LD_LIBRARY_PATH= svc power shutdown"); }; + static void set_brightness(int percent) { + std::ofstream brightness_control("/sys/class/leds/lcd-backlight/brightness"); + if (brightness_control.is_open()) { + brightness_control << (int)(percent * (255/100.)) << "\n"; + brightness_control.close(); + } + }; +}; + +class HardwareTici : public HardwareNone { +public: + static std::string get_os_version() { + return "AGNOS " + util::read_file("/VERSION"); + }; + + static void reboot() { std::system("sudo reboot"); }; + static void poweroff() { std::system("sudo poweroff"); }; + static void set_brightness(int percent) { + std::ofstream brightness_control("/sys/class/backlight/panel0-backlight/brightness"); + if (brightness_control.is_open()) { + brightness_control << (percent * (1023/100.)) << "\n"; + brightness_control.close(); + } + }; +}; + diff --git a/selfdrive/ui/android/ui.cc b/selfdrive/ui/android/ui.cc index 914d7d5b48..907a6e02ec 100644 --- a/selfdrive/ui/android/ui.cc +++ b/selfdrive/ui/android/ui.cc @@ -5,10 +5,11 @@ #include +#include "common/framebuffer.h" #include "common/util.h" #include "common/params.h" -#include "common/touch.h" #include "common/swaglog.h" +#include "common/touch.h" #include "common/watchdog.h" #include "ui.hpp" @@ -25,7 +26,7 @@ static void ui_set_brightness(UIState *s, int brightness) { } } -static void handle_display_state(UIState *s, bool user_input) { +static void handle_display_state(UIState *s, FrameBuffer *fb, bool user_input) { static int awake_timeout = 0; constexpr float accel_samples = 5*UI_FREQ; @@ -54,7 +55,7 @@ static void handle_display_state(UIState *s, bool user_input) { s->awake = should_wake; int display_mode = s->awake ? HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF; LOGW("setting display mode %d", display_mode); - s->fb->set_power(display_mode); + fb->set_power(display_mode); if (s->awake) { system("service call window 18 i32 1"); @@ -110,16 +111,18 @@ static void update_offroad_layout_state(UIState *s, PubMaster *pm) { int main(int argc, char* argv[]) { setpriority(PRIO_PROCESS, 0, -14); - SLSound sound; + SLSound sound; UIState uistate = {}; UIState *s = &uistate; + FrameBuffer fb = FrameBuffer("ui", 0, true, &s->fb_w, &s->fb_h); + ui_init(s); s->sound = &sound; TouchState touch = {0}; touch_init(&touch); - handle_display_state(s, true); + handle_display_state(s, &fb, true); PubMaster *pm = new PubMaster({"offroadLayout"}); @@ -157,7 +160,7 @@ int main(int argc, char* argv[]) { } // Don't waste resources on drawing in case screen is off - handle_display_state(s, touched == 1); + handle_display_state(s, &fb, touched == 1); if (!s->awake) { continue; } @@ -178,10 +181,10 @@ int main(int argc, char* argv[]) { // warn on sub 15fps LOGW("slow frame(%llu) time: %.2f", (s->sm)->frame, u2-u1); } - s->fb->swap(); + fb.swap(); } - handle_display_state(s, true); + handle_display_state(s, &fb, true); delete s->sm; delete pm; return 0; diff --git a/selfdrive/ui/qt/home.cc b/selfdrive/ui/qt/home.cc index c57c5b7a02..d617db8a3b 100644 --- a/selfdrive/ui/qt/home.cc +++ b/selfdrive/ui/qt/home.cc @@ -4,7 +4,6 @@ #include #include - #include #include #include @@ -17,6 +16,7 @@ #include "common/timing.h" #include "common/swaglog.h" #include "common/watchdog.h" +#include "selfdrive/hardware/hw.h" #include "home.hpp" #include "paint.hpp" @@ -26,7 +26,61 @@ #define BACKLIGHT_DT 0.25 #define BACKLIGHT_TS 2.00 -#define BACKLIGHT_OFFROAD 512 +#define BACKLIGHT_OFFROAD 50 + +// HomeWindow: the container for the offroad (OffroadHome) and onroad (GLWindow) UIs + +HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { + layout = new QGridLayout; + layout->setMargin(0); + + // onroad UI + glWindow = new GLWindow(this); + layout->addWidget(glWindow, 0, 0); + + // draw offroad UI on top of onroad UI + home = new OffroadHome(); + layout->addWidget(home, 0, 0); + + QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SLOT(setVisibility(bool))); + QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SIGNAL(offroadTransition(bool))); + QObject::connect(glWindow, SIGNAL(screen_shutoff()), this, SIGNAL(closeSettings())); + QObject::connect(this, SIGNAL(openSettings()), home, SLOT(refresh())); + + setLayout(layout); + setStyleSheet(R"( + * { + color: white; + } + )"); +} + +void HomeWindow::setVisibility(bool offroad) { + home->setVisible(offroad); +} + +void HomeWindow::mousePressEvent(QMouseEvent* e) { + UIState* ui_state = &glWindow->ui_state; + if (GLWindow::ui_state.scene.started && GLWindow::ui_state.scene.driver_view) { + Params().write_db_value("IsDriverViewEnabled", "0", 1); + return; + } + + glWindow->wake(); + + // Settings button click + if (!ui_state->sidebar_collapsed && settings_btn.ptInRect(e->x(), e->y())) { + emit openSettings(); + } + + // Vision click + if (ui_state->scene.started && (e->x() >= ui_state->viz_rect.x - bdr_s)) { + ui_state->sidebar_collapsed = !ui_state->sidebar_collapsed; + } +} + + +// OffroadHome: the offroad home page OffroadHome::OffroadHome(QWidget* parent) : QWidget(parent) { QVBoxLayout* main_layout = new QVBoxLayout(); @@ -109,7 +163,6 @@ void OffroadHome::refresh() { } if (alerts_widget->updateAvailable) { - // There is a new release alert_notification->setText("UPDATE"); } else { int alerts = alerts_widget->alerts.size(); @@ -135,55 +188,8 @@ void OffroadHome::refresh() { alert_notification->setStyleSheet(style); } -HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) { - layout = new QGridLayout; - layout->setMargin(0); - - // onroad UI - glWindow = new GLWindow(this); - layout->addWidget(glWindow, 0, 0); - - // draw offroad UI on top of onroad UI - home = new OffroadHome(); - layout->addWidget(home, 0, 0); - QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SLOT(setVisibility(bool))); - QObject::connect(glWindow, SIGNAL(offroadTransition(bool)), this, SIGNAL(offroadTransition(bool))); - QObject::connect(glWindow, SIGNAL(screen_shutoff()), this, SIGNAL(closeSettings())); - QObject::connect(this, SIGNAL(openSettings()), home, SLOT(refresh())); - setLayout(layout); - setStyleSheet(R"( - * { - color: white; - } - )"); -} - -void HomeWindow::setVisibility(bool offroad) { - home->setVisible(offroad); -} - -void HomeWindow::mousePressEvent(QMouseEvent* e) { - UIState* ui_state = &glWindow->ui_state; - if (GLWindow::ui_state.scene.started && GLWindow::ui_state.scene.driver_view) { - Params().write_db_value("IsDriverViewEnabled", "0", 1); - return; - } - - glWindow->wake(); - - // Settings button click - if (!ui_state->sidebar_collapsed && settings_btn.ptInRect(e->x(), e->y())) { - emit openSettings(); - } - - // Vision click - if (ui_state->scene.started && (e->x() >= ui_state->viz_rect.x - bdr_s)) { - ui_state->sidebar_collapsed = !ui_state->sidebar_collapsed; - } -} - static void handle_display_state(UIState* s, bool user_input) { - static int awake_timeout = 0; // Somehow this only gets called on program start + static int awake_timeout = 0; awake_timeout = std::max(awake_timeout - 1, 0); if (user_input || s->scene.ignition || s->scene.started) { @@ -194,17 +200,8 @@ static void handle_display_state(UIState* s, bool user_input) { } } -static void set_backlight(int brightness) { - try { - std::ofstream brightness_control("/sys/class/backlight/panel0-backlight/brightness"); - if (brightness_control.is_open()) { - brightness_control << brightness << "\n"; - brightness_control.close(); - } - } catch (std::exception& e) { - qDebug() << "Error setting brightness"; - } -} + +// GLWindow: the onroad UI GLWindow::GLWindow(QWidget* parent) : QOpenGLWidget(parent) { timer = new QTimer(this); @@ -217,7 +214,7 @@ GLWindow::GLWindow(QWidget* parent) : QOpenGLWidget(parent) { result += read_param(&brightness_m, "BRIGHTNESS_M", true); if (result != 0) { brightness_b = 10.0; - brightness_m = 1.0; + brightness_m = 0.1; } smooth_brightness = BACKLIGHT_OFFROAD; } @@ -235,6 +232,8 @@ void GLWindow::initializeGL() { std::cout << "OpenGL language version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << std::endl; ui_state.sound = &sound; + ui_state.fb_w = vwp_w; + ui_state.fb_h = vwp_h; ui_init(&ui_state); wake(); @@ -248,18 +247,23 @@ void GLWindow::backlightUpdate() { // Update brightness float k = (BACKLIGHT_DT / BACKLIGHT_TS) / (1.0f + BACKLIGHT_DT / BACKLIGHT_TS); - float clipped_brightness = ui_state.scene.started ? - std::min(1023.0f, (ui_state.scene.light_sensor * brightness_m) + brightness_b) : BACKLIGHT_OFFROAD; + float clipped_brightness = std::min(100.0f, (ui_state.scene.light_sensor * brightness_m) + brightness_b); + if (!ui_state.scene.started) { + clipped_brightness = BACKLIGHT_OFFROAD; + } smooth_brightness = clipped_brightness * k + smooth_brightness * (1.0f - k); int brightness = smooth_brightness; - if (!ui_state.awake) { brightness = 0; emit screen_shutoff(); } - std::thread{set_backlight, brightness}.detach(); + + if (brightness != last_brightness) { + std::thread{Hardware::set_brightness, brightness}.detach(); + } + last_brightness = brightness; } void GLWindow::timerUpdate() { @@ -296,9 +300,7 @@ void GLWindow::paintGL() { double dt = cur_draw_t - prev_draw_t; if (dt > 66 && onroad){ // warn on sub 15fps -#ifdef QCOM2 LOGW("slow frame(%llu) time: %.2f", ui_state.sm->frame, dt); -#endif } prev_draw_t = cur_draw_t; } @@ -307,9 +309,3 @@ void GLWindow::paintGL() { void GLWindow::wake() { handle_display_state(&ui_state, true); } - -FrameBuffer::FrameBuffer(const char *name, uint32_t layer, int alpha, int *out_w, int *out_h) { - *out_w = vwp_w; - *out_h = vwp_h; -} -FrameBuffer::~FrameBuffer() {} diff --git a/selfdrive/ui/qt/home.hpp b/selfdrive/ui/qt/home.hpp index 98ebc77f44..834c5cdbbb 100644 --- a/selfdrive/ui/qt/home.hpp +++ b/selfdrive/ui/qt/home.hpp @@ -44,10 +44,11 @@ private: bool onroad = true; double prev_draw_t = 0; - // TODO: this shouldn't be here + // TODO: make a nice abstraction to handle embedded device stuff float brightness_b = 0; float brightness_m = 0; float smooth_brightness = 0; + float last_brightness = 0; public slots: void timerUpdate(); diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index 31cff2c8cf..27004abbf2 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -22,6 +22,8 @@ #include "common/params.h" #include "common/util.h" +#include "selfdrive/hardware/hw.h" + QFrame* horizontal_line(QWidget* parent = 0){ QFrame* line = new QFrame(parent); line->setFrameShape(QFrame::StyledPanel); @@ -170,15 +172,25 @@ QWidget * device_panel() { } }); + // power buttons + QPushButton *poweroff_btn = new QPushButton("Power Off"); device_layout->addWidget(poweroff_btn, Qt::AlignBottom); + QObject::connect(poweroff_btn, &QPushButton::released, [=]() { + if (ConfirmationDialog::confirm("Are you sure you want to power off?")) { + Hardware::poweroff(); + } + }); + + device_layout->addWidget(horizontal_line(), Qt::AlignBottom); + QPushButton *reboot_btn = new QPushButton("Reboot"); device_layout->addWidget(reboot_btn, Qt::AlignBottom); - device_layout->addWidget(horizontal_line(), Qt::AlignBottom); -#ifdef __aarch64__ - QObject::connect(poweroff_btn, &QPushButton::released, [=]() { std::system("sudo poweroff"); }); - QObject::connect(reboot_btn, &QPushButton::released, [=]() { std::system("sudo reboot"); }); -#endif + QObject::connect(reboot_btn, &QPushButton::released, [=]() { + if (ConfirmationDialog::confirm("Are you sure you want to reboot?")) { + Hardware::reboot(); + } + }); QPushButton *uninstall_btn = new QPushButton("Uninstall openpilot"); device_layout->addWidget(uninstall_btn); @@ -205,8 +217,6 @@ QWidget * developer_panel() { QVBoxLayout *main_layout = new QVBoxLayout; main_layout->setMargin(100); - // TODO: enable SSH toggle and github keys - Params params = Params(); std::string brand = params.read_db_bool("Passive") ? "dashcam" : "openpilot"; std::vector> labels = { @@ -214,18 +224,14 @@ QWidget * developer_panel() { {"Git Branch", params.get("GitBranch", false)}, {"Git Commit", params.get("GitCommit", false).substr(0, 10)}, {"Panda Firmware", params.get("PandaFirmwareHex", false)}, + {"OS Version", Hardware::get_os_version()}, }; - std::string os_version = util::read_file("/VERSION"); - if (os_version.size()) { - labels.push_back({"OS Version", "AGNOS " + os_version}); - } - - for (int i = 0; iaddWidget(labelWidget(QString::fromStdString(l.first), QString::fromStdString(l.second))); - if(i+1addWidget(horizontal_line()); } } diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index d8cb4b33fe..ccd3d7c6bf 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -65,8 +65,6 @@ void ui_init(UIState *s) { s->scene.started = false; s->status = STATUS_OFFROAD; - s->fb = std::make_unique("ui", 0, true, &s->fb_w, &s->fb_h); - ui_nvg_init(s); s->last_frame = nullptr; diff --git a/selfdrive/ui/ui.hpp b/selfdrive/ui/ui.hpp index 97d659bf42..75f12a61e9 100644 --- a/selfdrive/ui/ui.hpp +++ b/selfdrive/ui/ui.hpp @@ -21,7 +21,6 @@ #include "common/mat.h" #include "common/visionimg.h" -#include "common/framebuffer.h" #include "common/modeldata.h" #include "common/params.h" #include "common/glutil.h" @@ -144,7 +143,6 @@ typedef struct UIState { VisionBuf * last_frame; // framebuffer - std::unique_ptr fb; int fb_w, fb_h; // NVG