65 lines
2.7 KiB
C++
65 lines
2.7 KiB
C++
|
|
// glue/settings_view.hpp — on-device settings menu views (TFT + rotary encoder).
|
||
|
|
//
|
||
|
|
// Adds entries to the MEMLNaut display carousel (the same DisplayDriver the
|
||
|
|
// SystemView and SelfTest use). Navigation: rotate to move between views;
|
||
|
|
// press to focus a view; rotate-while-focused to change its value; press
|
||
|
|
// again to unfocus. See src/memllib/.../display/DisplayDriver.hpp.
|
||
|
|
//
|
||
|
|
// Currently provides:
|
||
|
|
// * Joystick: Dual / Single — for the 4-input ("two 2-D joystick") modes,
|
||
|
|
// toggles whether the SECOND joystick (input channels 2,3) feeds the ML
|
||
|
|
// engine. "Single" pins those channels to the neutral value (0.5) via the
|
||
|
|
// platform-agnostic ModeBase pin mechanism, so the network is never
|
||
|
|
// rebuilt and trained state survives toggling. Default is Dual (the 4-D
|
||
|
|
// variant naturally uses both joysticks).
|
||
|
|
//
|
||
|
|
// Only registered for modes whose input arity is exactly 4 (the two-joystick
|
||
|
|
// modes); other modes (e.g. SoundAnalysisMIDI, whose joystick channels are not
|
||
|
|
// 2,3) get no joystick toggle.
|
||
|
|
|
||
|
|
#pragma once
|
||
|
|
|
||
|
|
#include <array>
|
||
|
|
#include <cstddef>
|
||
|
|
#include <memory>
|
||
|
|
#include <span>
|
||
|
|
|
||
|
|
#include "../src/memllib/hardware/memlnaut/MEMLNaut.hpp"
|
||
|
|
#include "../src/memllib/hardware/memlnaut/display/SingleSelectView.hpp"
|
||
|
|
|
||
|
|
namespace nisps_firmware {
|
||
|
|
|
||
|
|
// The second 2-D joystick maps to ML input channels 2 and 3 (joy_z / joy_w).
|
||
|
|
inline constexpr std::size_t kSecondJoystickCh0 = 2u;
|
||
|
|
inline constexpr std::size_t kSecondJoystickCh1 = 3u;
|
||
|
|
|
||
|
|
// Add the settings views for `mode` to the display carousel. Must run AFTER
|
||
|
|
// MEMLNaut::Initialize() (so the display + TFT exist) and after
|
||
|
|
// addSystemInfoView(), on core 0.
|
||
|
|
template <typename ModeT>
|
||
|
|
inline void wire_settings(ModeT& mode) {
|
||
|
|
if constexpr (ModeT::input_channel_count() == 4u) {
|
||
|
|
MEMLNaut* meml = MEMLNaut::Instance();
|
||
|
|
if (!meml || !meml->disp) return;
|
||
|
|
|
||
|
|
// Kept alive for the program lifetime (the carousel holds a shared_ptr
|
||
|
|
// too, but this guarantees ownership regardless of view churn).
|
||
|
|
static std::shared_ptr<SingleSelectView> joystick_view;
|
||
|
|
joystick_view = std::make_shared<SingleSelectView>("Joystick");
|
||
|
|
meml->disp->AddView(joystick_view); // calls Setup() → creates the selector
|
||
|
|
|
||
|
|
// Index 0 = Dual (default, no pinning); index 1 = Single.
|
||
|
|
std::array<String, 2u> options = { String("Dual"), String("Single") };
|
||
|
|
joystick_view->setOptions(std::span<String>(options.data(), options.size()));
|
||
|
|
joystick_view->setNewVoiceCallback([&mode](std::size_t idx) {
|
||
|
|
const bool single = (idx == 1u);
|
||
|
|
mode.set_input_pinned(kSecondJoystickCh0, single);
|
||
|
|
mode.set_input_pinned(kSecondJoystickCh1, single);
|
||
|
|
});
|
||
|
|
} else {
|
||
|
|
(void)mode;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
} // namespace nisps_firmware
|