diff options
author | Roland Reichwein <mail@reichwein.it> | 2025-01-20 20:39:10 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2025-01-20 20:39:10 +0100 |
commit | 5fd637644c7529bfdc5291215f3f8ee1edd304c4 (patch) | |
tree | 2f135c3cae2bc034aa27b33b39dca95b992cb69f | |
parent | ef578ac72a70bfbe8aee726d43374c841d77ade4 (diff) |
Fixed status led
-rw-r--r-- | MainLoop.cpp | 187 | ||||
-rw-r--r-- | MainLoop.h | 2 | ||||
-rw-r--r-- | StatusLED.cpp | 41 | ||||
-rw-r--r-- | StatusLED.h | 7 |
4 files changed, 141 insertions, 96 deletions
diff --git a/MainLoop.cpp b/MainLoop.cpp index 2ffcc0a..b6331a2 100644 --- a/MainLoop.cpp +++ b/MainLoop.cpp @@ -23,6 +23,7 @@ using namespace std::chrono_literals; using namespace std::string_literals; MainLoop::MainLoop(int argc, char** argv): + m_status{}, m_config{argc, argv}, m_note_click{m_config}, m_clock_click{}, @@ -31,6 +32,8 @@ MainLoop::MainLoop(int argc, char** argv): m_pcm{m_config}, m_ui{m_config} { + m_status.add(LED{"/sys/class/leds/ACT", "/sys/class/leds/PWR"}); + m_status.add(LED{"/sys/class/leds/thingm1:green:led1", "/sys/class/leds/thingm1:red:led1"}); } bool run_flag = true; @@ -60,97 +63,103 @@ void MainLoop::reconfigure_mode() { int MainLoop::run() { - signal(SIGTERM, signal_handler); - signal(SIGINT, signal_handler); - - //debug_cout.activate(); - log_cout.activate(); - log_cout.log_lines(log_lines); - - m_pcm.write(); - - Timer timer_50ms(50ms, true); - timer_50ms.start(); - - Timer timer_500ms(500ms, true); - timer_500ms.start(); - - Timer timer_10min(10min, true); - timer_10min.start(); - - // Main signals - boost::signals2::signal<void()> signal_count_loops; - - // - // Signal-Slot Connections: - // - m_midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){m_note_click.receive_note(channel, note, timestamp);}); - //m_click_connection = m_note_click.signal_click.connect([&](){m_pcm.click(0);}); - reconfigure_mode(); - m_note_click.signal_bpm.connect([&](int bpm){m_ui.slot_note_bpm(bpm);}); - m_clock_click.signal_bpm.connect([&](int bpm){m_ui.slot_clock_bpm(bpm);}); - m_midi.signal_active_sensing.connect([&](){m_ui.slot_active_sensing();}); - timer_500ms.elapsed.connect([&](){m_ui.draw();}); - signal_count_loops.connect([&](){m_ui.count_main_loops();}); - m_midi.signal_count_events.connect([&](size_t size){m_ui.count_midi_events(size);}); - timer_10min.elapsed.connect([&](){m_config.persist();}); - m_midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){m_ui.slot_midi_note(channel, note, timestamp);}); - m_midi.signal_clock.connect([&](){m_clock_click.receive_clock();}); - m_config.signal_mode.connect([&](int mode){reconfigure_mode();}); - timer_50ms.elapsed.connect([&](){m_internal_click.run_cyclic_50ms();}); - - m_midi.flush(); - - while (run_flag) { - debug_cout << "Main loop entered." << std::endl; - signal_count_loops(); - - fd_set read_set; - FD_ZERO(&read_set); - FD_SET(m_midi.fd(), &read_set); - FD_SET(0, &read_set); - - if constexpr (0) { - // PCM fd almost always writeable: for single frames at high speed - fd_set write_set; - FD_ZERO(&write_set); - FD_SET(m_pcm.fd(), &write_set); + try { + signal(SIGTERM, signal_handler); + signal(SIGINT, signal_handler); + + //debug_cout.activate(); + log_cout.activate(); + log_cout.log_lines(log_lines); + + m_pcm.write(); + + Timer timer_50ms(50ms, true); + timer_50ms.start(); + + Timer timer_500ms(500ms, true); + timer_500ms.start(); + + Timer timer_10min(10min, true); + timer_10min.start(); + + // Main signals + boost::signals2::signal<void()> signal_count_loops; + + // + // Signal-Slot Connections: + // + m_midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){m_note_click.receive_note(channel, note, timestamp);}); + //m_click_connection = m_note_click.signal_click.connect([&](){m_pcm.click(0);}); + reconfigure_mode(); + m_note_click.signal_bpm.connect([&](int bpm){m_ui.slot_note_bpm(bpm);}); + m_clock_click.signal_bpm.connect([&](int bpm){m_ui.slot_clock_bpm(bpm);}); + m_midi.signal_active_sensing.connect([&](){m_ui.slot_active_sensing();}); + timer_500ms.elapsed.connect([&](){m_ui.draw();}); + signal_count_loops.connect([&](){m_ui.count_main_loops();}); + m_midi.signal_count_events.connect([&](size_t size){m_ui.count_midi_events(size);}); + timer_10min.elapsed.connect([&](){m_config.persist();}); + m_midi.signal_note.connect([&](int channel, int note, uint64_t timestamp){m_ui.slot_midi_note(channel, note, timestamp);}); + m_midi.signal_clock.connect([&](){m_clock_click.receive_clock();}); + m_config.signal_mode.connect([&](int mode){reconfigure_mode();}); + timer_50ms.elapsed.connect([&](){m_internal_click.run_cyclic_50ms();}); + + m_midi.flush(); + + while (run_flag) { + debug_cout << "Main loop entered." << std::endl; + signal_count_loops(); + + fd_set read_set; + FD_ZERO(&read_set); + FD_SET(m_midi.fd(), &read_set); + FD_SET(0, &read_set); + + if constexpr (0) { + // PCM fd almost always writeable: for single frames at high speed + fd_set write_set; + FD_ZERO(&write_set); + FD_SET(m_pcm.fd(), &write_set); + } + + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 20000; + + int result = select(FD_SETSIZE, &read_set, nullptr/*&write_set*/, nullptr, &timeout); + if (result < 0) { + throw std::runtime_error("select() failed"); + } else if (result == 0) { + debug_cout << "select() timeout" << std::endl; + } + + while (m_midi.event_ready()) + { + //std::cout << "read..." << std::endl; + auto event = m_midi.read(); + //std::cout << "process..." << std::endl; + m_midi.process(event); + } + + if (m_pcm.write_available()) { + //std::cout << "DEBUG: WRITE" << std::endl; + m_pcm.write(); + } + + while (m_ui.key_available()) { + m_ui.handle_input(); + } + + // handle timers, TODO: make updates more efficient at scale + timer_50ms.update(); + timer_500ms.update(); + timer_10min.update(); } - struct timeval timeout; - timeout.tv_sec = 0; - timeout.tv_usec = 20000; - - int result = select(FD_SETSIZE, &read_set, nullptr/*&write_set*/, nullptr, &timeout); - if (result < 0) { - throw std::runtime_error("select() failed"); - } else if (result == 0) { - debug_cout << "select() timeout" << std::endl; - } - - while (m_midi.event_ready()) - { - //std::cout << "read..." << std::endl; - auto event = m_midi.read(); - //std::cout << "process..." << std::endl; - m_midi.process(event); - } - - if (m_pcm.write_available()) { - //std::cout << "DEBUG: WRITE" << std::endl; - m_pcm.write(); - } - - while (m_ui.key_available()) { - m_ui.handle_input(); - } - - // handle timers, TODO: make updates more efficient at scale - timer_50ms.update(); - timer_500ms.update(); - timer_10min.update(); + return 0; + } catch (const std::exception& ex) { + std::cerr << "Error: " << ex.what() << std::endl; + m_status.setMode(StatusLED::Mode::Error); + return 1; } - - return 0; } @@ -1,5 +1,6 @@ #pragma once +#include "StatusLED.h" #include "NoteClick.h" #include "ClockClick.h" #include "InternalClick.h" @@ -21,6 +22,7 @@ private: boost::signals2::connection m_click_connection; + StatusLED m_status; Config m_config; PIDFile m_pid_file{m_config.get_programname()}; diff --git a/StatusLED.cpp b/StatusLED.cpp index 3013ddb..711257d 100644 --- a/StatusLED.cpp +++ b/StatusLED.cpp @@ -1,21 +1,33 @@ #include "StatusLED.h" +#include <iostream> + +#include <fmt/format.h> +#include <libreichwein/file.h> + namespace fs = std::filesystem; StatusLED::StatusLED(): m_mode{Mode::OK}, m_bpm{60} { } -void StatusLED::addLED(const LED& led) +void StatusLED::add(const LED& led) { if (fs::exists(led.green) && fs::exists(led.red)) { - m_leds.push_back(led); + if (init(led)) { + m_leds.push_back(led); + update(led); + } } } void StatusLED::setMode(Mode mode) { m_mode = mode; + + for (const auto& i: m_leds) { + update(i); + } } void StatusLED::setBPM(int bpm) @@ -23,10 +35,31 @@ void StatusLED::setBPM(int bpm) m_bpm = bpm; } -void StatusLED::initLED(const LED& led) +bool StatusLED::init(const LED& led) { + try { + Reichwein::File::setFile(led.green / "trigger", "none"); + Reichwein::File::setFile(led.red / "trigger", "none"); + return true; + } catch (...) { + return false; + } } -void StatusLED::updateLED(const LED& led) +void StatusLED::update(const LED& led) { + int green{}; + int red{}; + + if (m_mode == Mode::OK) { + green = 255; + } else if (m_mode == Mode::Error) { + red = 255; + } else { + throw std::runtime_error("LED mode unimplemented"); + } + + Reichwein::File::setFile(led.green / "brightness", fmt::format("{}", green)); + Reichwein::File::setFile(led.red / "brightness", fmt::format("{}", red)); } + diff --git a/StatusLED.h b/StatusLED.h index b1c0f23..9348f19 100644 --- a/StatusLED.h +++ b/StatusLED.h @@ -22,16 +22,17 @@ public: StatusLED(); - void addLED(const LED& led); + void add(const LED& led); void setMode(Mode mode); void setBPM(int bpm); private: - void initLED(const LED& led); - void updateLED(const LED& led); + bool init(const LED& led); + void update(const LED& led); std::vector<LED> m_leds; // on best effort base, those will all show the same status Mode m_mode; int m_bpm; }; + |