Browse Source

main_framework_proto1 - new framework prototype using updated SWTimer (now PeriodicTask) and Observer (now PollingObserver)

usb_midi_launchpad
heck 6 months ago
parent
commit
3c4e80d8c9
  1. 235
      examples/main_framework_proto1.cc
  2. 36
      examples/main_framework_proto1.hh
  3. 119
      src/utils.hh

235
examples/main_framework_proto1.cc

@ -0,0 +1,235 @@
#include "main_framework_proto1.hh"
#include "utils.hh"
#include <functional>
namespace Heck {
namespace { // anonymous namespace for internal linkage
// declarations
void audio_callback(
ld::AudioHandle::InputBuffer in,
ld::AudioHandle::OutputBuffer out,
size_t size);
// =============================================================================================
// STATIC INIT
// =============================================================================================
ld::DaisySeed seed{};
ld::MidiUartHandler midi{};
dsp::Oscillator osc{};
// Buttons
std::array<bool, 4> buts_value{ false, false, false, false };
ld::Switch ld_but_1{};
PollingObserver<bool> but_1{ []() -> bool {
ld_but_1.Debounce();
return ld_but_1.Pressed();
},
[](bool val) {
buts_value[0] = val;
seed.PrintLine("BUT_1: %i", buts_value[0]);
} };
ld::Switch ld_but_2{};
PollingObserver<bool> but_2{ []() -> bool {
ld_but_2.Debounce();
return ld_but_2.Pressed();
},
[](bool val) {
buts_value[1] = val;
seed.PrintLine("BUT_2: %i", buts_value[1]);
} };
ld::Switch ld_but_3{};
PollingObserver<bool> but_3{ []() -> bool {
ld_but_3.Debounce();
return ld_but_3.Pressed();
},
[](bool val) {
buts_value[2] = val;
seed.PrintLine("BUT_3: %i", buts_value[2]);
} };
ld::Switch ld_but_4{};
PollingObserver<bool> but_4{ []() -> bool {
ld_but_4.Debounce();
return ld_but_4.Pressed();
},
[](bool val) {
buts_value[3] = val;
seed.PrintLine("BUT_4: %i", buts_value[3]);
} };
// Pots
std::array<float, 4> pots_value{ -1.F, -1.F, -1.F, -1.F };
PollingObserver<int> pot1{ []() -> int { return seed.adc.Get(0); },
[](int val) {
pots_value[0] = float(val) /
(float)std::numeric_limits<u16>::max();
seed.PrintLine("POT_0: %d", (int)(pots_value[0] * 100.));
} };
PollingObserver<int> pot2{ []() -> int { return seed.adc.Get(1); },
[](int val) {
pots_value[1] = float(val) /
(float)std::numeric_limits<u16>::max();
seed.PrintLine("POT_1: %d", (int)(pots_value[1] * 100.));
} };
PollingObserver<int> pot3{ []() -> int { return seed.adc.Get(2); },
[](int val) {
pots_value[2] = float(val) /
(float)std::numeric_limits<u16>::max();
seed.PrintLine("POT_2: %d", (int)(pots_value[2] * 100.));
} };
PollingObserver<int> pot4{ []() -> int { return seed.adc.Get(3); },
[](int val) {
pots_value[3] = float(val) /
(float)std::numeric_limits<u16>::max();
seed.PrintLine("POT_3: %d", (int)(pots_value[3] * 100.));
} };
// Tasks
PeriodicTask ui_task{ 10, [](u32 time_now) {
pot1.fetch_and_deliver_fuzzy(Constants::Hardware::BUT_FUZZ);
pot2.fetch_and_deliver_fuzzy(Constants::Hardware::BUT_FUZZ);
pot3.fetch_and_deliver_fuzzy(Constants::Hardware::BUT_FUZZ);
pot4.fetch_and_deliver_fuzzy(Constants::Hardware::BUT_FUZZ);
but_1.fetch_and_deliver();
but_2.fetch_and_deliver();
but_3.fetch_and_deliver();
but_4.fetch_and_deliver();
while (midi.HasEvents()) {
ld::MidiEvent msg = midi.PopEvent();
char strbuf[128];
GetMidiTypeAsString(msg, &strbuf[0]);
seed.PrintLine("%s", strbuf);
}
} };
PeriodicTask heartbeat_task{ 100, [](u32 time) {
static bool heartbeat_led_state{ false };
heartbeat_led_state = !heartbeat_led_state;
seed.SetLed(heartbeat_led_state);
return;
} };
// =============================================================================================
// RUNTIME INIT
// =============================================================================================
void init()
{
seed.Configure();
seed.Init(Constants::CPU_BOOST480MHZ);
seed.StartLog(Constants::Developer::LOG_BLOCKS_BOOT);
{
ld_but_1.Init(seed.GetPin(Constants::Hardware::PIN_BUT_1));
ld_but_2.Init(seed.GetPin(Constants::Hardware::PIN_BUT_2));
ld_but_3.Init(seed.GetPin(Constants::Hardware::PIN_BUT_3));
ld_but_4.Init(seed.GetPin(Constants::Hardware::PIN_BUT_4));
}
{
ld::AdcChannelConfig adc_cfg[4];
adc_cfg[0].InitSingle(ld::DaisySeed::GetPin(Constants::Hardware::PIN_POT_1));
adc_cfg[1].InitSingle(ld::DaisySeed::GetPin(Constants::Hardware::PIN_POT_2));
adc_cfg[2].InitSingle(ld::DaisySeed::GetPin(Constants::Hardware::PIN_POT_3));
adc_cfg[3].InitSingle(ld::DaisySeed::GetPin(Constants::Hardware::PIN_POT_4));
seed.adc.Init(adc_cfg, 4);
seed.adc.Start();
}
seed.PrintLine("Setting Blocksize: %i", Constants::AUDIO_BUFFERSIZE);
seed.SetAudioBlockSize(Constants::AUDIO_BUFFERSIZE);
seed.PrintLine("Setting Samplerate: %i", Constants::AUDIO_SAMPLERATE);
seed.SetAudioSampleRate(Constants::AUDIO_SAMPLERATE);
seed.PrintLine("Initializing MIDI");
ld::MidiUartHandler::Config midi_config{};
midi.Init(midi_config);
seed.PrintLine("Starting MIDI Receive");
midi.StartReceiveRt([](const ld::MidiEvent& msg) {
switch (msg.srt_type) {
case ld::TimingClock: {
} break;
case ld::Start: {
} break;
case ld::Stop: {
} break;
case ld::Reset: {
} break;
case ld::Continue: {
} break;
}
});
midi.Listen();
seed.PrintLine("Starting Audio");
seed.StartAudio(audio_callback);
osc.Init(Constants::AUDIO_SAMPLERATE);
osc.SetWaveform(osc.WAVE_SIN);
osc.SetAmp(1.F);
osc.SetFreq(100);
}
// =============================================================================================
// RUN
// =============================================================================================
void audio_callback(ld::AudioHandle::InputBuffer in, ld::AudioHandle::OutputBuffer out, size_t size)
{
{
float osc_out{};
for (size_t i = 0; i < size; i++) {
osc_out = osc.Process();
osc_out *= 0.05;
out[0][i] = osc_out;
out[1][i] = osc_out;
}
}
if constexpr (false) {
// Channel 1
for (size_t i = 0; i < size; i++) {
out[0][i] = in[0][i];
}
// Channel 2
for (size_t i = 0; i < size; i++) {
out[1][i] = in[1][i];
}
}
}
void mainloop()
{
seed.PrintLine("Entering MainLoop");
u32 uptime_ms{};
while (true) {
uptime_ms = ld::System::GetNow();
ui_task.run_pending(uptime_ms);
heartbeat_task.run_pending(uptime_ms);
}
}
} // namespace
} // namespace Heck
int main()
{
Heck::init();
Heck::mainloop();
}

36
examples/main_framework_proto1.hh

@ -0,0 +1,36 @@
#ifndef HECK_LIBDIZZY_MAIN_FRAMEWORK_PROTO1_HH
#define HECK_LIBDIZZY_MAIN_FRAMEWORK_PROTO1_HH
#include <cstdint>
#include "daisy_seed.h"
#include "daisysp.h"
#include "types.hh"
namespace Heck {
namespace Constants {
namespace Hardware {
constexpr int PIN_BUT_1 = 27;
constexpr int PIN_BUT_2 = 28;
constexpr int PIN_BUT_3 = 29;
constexpr int PIN_BUT_4 = 30;
constexpr int PIN_POT_1 = 15;
constexpr int PIN_POT_2 = 16;
constexpr int PIN_POT_3 = 17;
constexpr int PIN_POT_4 = 18;
constexpr int BUT_FUZZ = 40;
} // namespace Hardware
constexpr bool CPU_BOOST480MHZ = false;
constexpr int AUDIO_BUFFERSIZE = 4;
constexpr Samplerate AUDIO_SAMPLERATE = Samplerate::SAI_48KHZ;
namespace Developer {
constexpr bool LOG_BLOCKS_BOOT = true;
}
} // namespace Constants
} // namespace Heck
#endif

119
src/utils.hh

@ -27,6 +27,59 @@ namespace Heck {
u32 time_last_exec_{};
u32 time_period_{};
};
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
namespace Heck {
@ -56,5 +109,69 @@ namespace Heck {
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 init(FetchCallback fetch_cb, DeliverCallback deliver_cb)
{
set_fetch_callback(fetch_cb);
set_deliver_callback(deliver_cb);
}
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:
T val_current_{};
FetchCallback fetch_cb_{};
DeliverCallback deliver_cb_{};
};
} // namespace Heck
#endif // HECK_DAISY_UTILS_HH
#endif // HECK_DAISY_UTILS_HH`
Loading…
Cancel
Save