You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
8.9 KiB
353 lines
8.9 KiB
#ifndef HECK_DIZZY_UTILS_HH
|
|
#define HECK_DIZZY_UTILS_HH
|
|
|
|
#include "dizzy_types.hh"
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// String representations
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
void GetMidiTypeAsString(const ld::MidiEvent& msg, char* str);
|
|
void GetMidiRTTypeAsString(const ld::MidiEvent& msg, char* str);
|
|
} // namespace Heck::Dizzy
|
|
|
|
// ---------------------------------------------------------
|
|
// Scaling
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
float scalen_min_max(float val, float min, float max);
|
|
float scalen_center_range(float val, float center, float range);
|
|
} // namespace Heck::Dizzy
|
|
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// SWTimer
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
class SWTimer {
|
|
public:
|
|
using Callback = std::function<void(u32 time)>;
|
|
|
|
void set_period(u32 time_units);
|
|
void set_callback(const Callback& cb);
|
|
bool is_it_already_time_again(u32 time_now);
|
|
|
|
private:
|
|
Callback callback_{};
|
|
u32 time_last_exec_{};
|
|
u32 time_period_{};
|
|
};
|
|
|
|
// !!!
|
|
// constexpr function pointer
|
|
// !!!
|
|
// template<auto F>
|
|
// struct FunctionPtr {
|
|
// constexpr FunctionPtr() = default;
|
|
// static void call()
|
|
// {
|
|
// F();
|
|
// }
|
|
// };
|
|
|
|
|
|
|
|
template<void (*TASK)(u32), int PERIOD>
|
|
class PeriodicTaskCT {
|
|
public:
|
|
PeriodicTaskCT() = default;
|
|
|
|
PeriodicTaskCT(PeriodicTaskCT&) = delete;
|
|
PeriodicTaskCT& operator=(PeriodicTaskCT&) = delete;
|
|
|
|
PeriodicTaskCT(PeriodicTaskCT&&) = delete;
|
|
PeriodicTaskCT& operator=(PeriodicTaskCT&&) = delete;
|
|
|
|
~PeriodicTaskCT() = default;
|
|
|
|
bool run_pending(u32 time_now)
|
|
{
|
|
if (time_now - time_last_exec_ >= PERIOD) {
|
|
time_last_exec_ = time_now;
|
|
TASK(time_now);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
u32 time_last_exec_{};
|
|
};
|
|
|
|
class PeriodicTask {
|
|
public:
|
|
using Task = std::function<void(u32 time)>;
|
|
|
|
PeriodicTask() = delete;
|
|
~PeriodicTask() = default;
|
|
|
|
PeriodicTask(u32 period, Task t)
|
|
{
|
|
init(period, t);
|
|
}
|
|
|
|
PeriodicTask(PeriodicTask&) = delete;
|
|
PeriodicTask& operator=(PeriodicTask&) = delete;
|
|
|
|
PeriodicTask(PeriodicTask&&) = delete;
|
|
PeriodicTask& operator=(PeriodicTask&&) = delete;
|
|
|
|
void set_period(u32 time_units)
|
|
{
|
|
time_period_ = time_units;
|
|
}
|
|
|
|
void set_task(Task t)
|
|
{
|
|
task_ = t;
|
|
}
|
|
|
|
bool run_pending(u32 time_now)
|
|
{
|
|
if (time_now - time_last_exec_ >= time_period_) {
|
|
time_last_exec_ = time_now;
|
|
if (task_) {
|
|
//todo: constexpr if metrics
|
|
task_(time_now);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
void init(u32 period, Task t)
|
|
{
|
|
set_period(period);
|
|
set_task(t);
|
|
}
|
|
|
|
Task task_{};
|
|
u32 time_last_exec_{};
|
|
u32 time_period_{};
|
|
};
|
|
} // namespace Heck::Dizzy
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// Observer
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
template<typename T>
|
|
class Observer {
|
|
|
|
public:
|
|
bool on_change(T val_new, std::function<void(T val_current)> fn)
|
|
{
|
|
if (val_new != val_current_) {
|
|
val_current_ = val_new;
|
|
fn(val_current_);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool on_change_fuzzy(T val_new, T min_deviation, std::function<void(T val_current)> fn)
|
|
{
|
|
if (std::abs(val_new - val_current_) >= min_deviation) {
|
|
val_current_ = val_new;
|
|
fn(val_current_);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
T val_current_{};
|
|
};
|
|
|
|
template<typename T>
|
|
class PollingObserver {
|
|
|
|
public:
|
|
using FetchCallback = std::function<T(void)>;
|
|
using DeliverCallback = std::function<void(T val_current)>;
|
|
|
|
PollingObserver() = delete;
|
|
~PollingObserver() = default;
|
|
|
|
explicit PollingObserver(FetchCallback fetch_cb, DeliverCallback deliver_cb)
|
|
{
|
|
init(fetch_cb, deliver_cb);
|
|
}
|
|
|
|
PollingObserver(PollingObserver&) = delete;
|
|
PollingObserver& operator=(PollingObserver) = delete;
|
|
|
|
PollingObserver(PollingObserver&&) = delete;
|
|
PollingObserver& operator=(PollingObserver&&) = delete;
|
|
|
|
void set_fetch_callback(FetchCallback cb)
|
|
{
|
|
fetch_cb_ = cb;
|
|
}
|
|
|
|
void set_deliver_callback(DeliverCallback cb)
|
|
{
|
|
deliver_cb_ = cb;
|
|
}
|
|
|
|
bool fetch_and_deliver()
|
|
{
|
|
T val_fetched{ fetch_cb_() };
|
|
if (val_fetched != val_current_) {
|
|
val_current_ = val_fetched;
|
|
deliver_cb_(val_current_);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool fetch_and_deliver_fuzzy(T min_deviation)
|
|
{
|
|
T val_fetched{ fetch_cb_() };
|
|
if (std::abs(val_fetched - val_current_) >= min_deviation) {
|
|
val_current_ = val_fetched;
|
|
deliver_cb_(val_current_);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
void init(FetchCallback fetch_cb, DeliverCallback deliver_cb)
|
|
{
|
|
set_fetch_callback(fetch_cb);
|
|
set_deliver_callback(deliver_cb);
|
|
}
|
|
|
|
T val_current_{};
|
|
FetchCallback fetch_cb_{};
|
|
DeliverCallback deliver_cb_{};
|
|
};
|
|
} // namespace Heck::Dizzy
|
|
|
|
|
|
// ---------------------------------------------------------
|
|
// Cache
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
template<typename T>
|
|
class Cache {
|
|
|
|
public:
|
|
using UpdateCallback = std::function<T(void)>;
|
|
using NotifyChangeCallback = std::function<void(Cache<T>&)>;
|
|
|
|
|
|
explicit Cache(UpdateCallback update_cb, NotifyChangeCallback notify_change_cb)
|
|
{
|
|
init(update_cb, notify_change_cb);
|
|
}
|
|
|
|
Cache() = delete;
|
|
Cache(Cache&) = delete;
|
|
Cache& operator=(Cache) = delete;
|
|
|
|
Cache(Cache&&) = delete;
|
|
Cache& operator=(Cache&&) = delete;
|
|
~Cache() = default;
|
|
|
|
T read()
|
|
{
|
|
return val_current_;
|
|
}
|
|
|
|
void set_update_callback(UpdateCallback cb)
|
|
{
|
|
update_cb_ = cb;
|
|
}
|
|
|
|
void set_notify_change_callback(NotifyChangeCallback cb)
|
|
{
|
|
notify_change_cb_ = cb;
|
|
}
|
|
|
|
bool update_and_notify_change()
|
|
{
|
|
T val_fetched{ update_cb_() };
|
|
if (val_fetched != val_current_) {
|
|
val_current_ = val_fetched;
|
|
notify_change_cb_(*this);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool update_and_notify_change_fuzzy(T min_deviation)
|
|
{
|
|
T val_fetched{ update_cb_() };
|
|
if (std::abs(val_fetched - val_current_) >= min_deviation) {
|
|
val_current_ = val_fetched;
|
|
notify_change_cb_(*this);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private:
|
|
void init(UpdateCallback fetch_cb, NotifyChangeCallback deliver_cb)
|
|
{
|
|
set_update_callback(fetch_cb);
|
|
set_notify_change_callback(deliver_cb);
|
|
}
|
|
|
|
T val_current_{};
|
|
UpdateCallback update_cb_{};
|
|
NotifyChangeCallback notify_change_cb_{};
|
|
};
|
|
|
|
} // namespace Heck::Dizzy
|
|
|
|
// ---------------------------------------------------------
|
|
// DigitalIn
|
|
// ---------------------------------------------------------
|
|
namespace Heck::Dizzy {
|
|
struct DigitalIn {
|
|
public:
|
|
DigitalIn() = default;
|
|
~DigitalIn() = default;
|
|
|
|
DigitalIn(u8 daisy_pin)
|
|
{
|
|
init(daisy_pin);
|
|
}
|
|
|
|
DigitalIn(DigitalIn&) = delete;
|
|
DigitalIn& operator=(DigitalIn&) = delete;
|
|
|
|
DigitalIn(DigitalIn&&) = delete;
|
|
DigitalIn& operator=(DigitalIn&&) = delete;
|
|
|
|
void init(u8 daisy_pin)
|
|
{
|
|
gpio_.Init(ld::DaisySeed::GetPin(daisy_pin), ld::GPIO::Mode::INPUT, ld::GPIO::Pull::PULLUP);
|
|
}
|
|
|
|
bool read()
|
|
{
|
|
return !gpio_.Read();
|
|
}
|
|
|
|
Cache<bool> cache{ [&]() -> bool { return read(); }, [](Cache<bool>&) {} };
|
|
|
|
private:
|
|
|
|
ld::GPIO gpio_{};
|
|
};
|
|
|
|
|
|
} // namespace Heck::Dizzy
|
|
#endif // HECK_DAISY_UTILS_HH`
|