metaforce/Runtime/Input/CRumbleGenerator.cpp

113 lines
3.0 KiB
C++
Raw Permalink Normal View History

#include "Runtime/Input/CRumbleGenerator.hpp"
#include "Runtime/GameGlobalObjects.hpp"
2016-02-21 06:34:42 +00:00
2021-04-10 08:42:06 +00:00
namespace metaforce {
2018-12-08 05:30:43 +00:00
CRumbleGenerator::CRumbleGenerator() {
HardStopAll();
2016-02-21 06:34:42 +00:00
}
2018-12-08 05:30:43 +00:00
CRumbleGenerator::~CRumbleGenerator() { HardStopAll(); }
2018-01-26 19:46:35 +00:00
#define PWM_MONITOR 0
#if PWM_MONITOR
static bool b_tp = false;
static std::chrono::steady_clock::time_point s_tp;
#endif
2018-12-08 05:30:43 +00:00
void CRumbleGenerator::Update(float dt) {
2018-01-26 19:46:35 +00:00
#if PWM_MONITOR
2018-12-08 05:30:43 +00:00
std::chrono::milliseconds::rep ms = 0;
std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
if (!b_tp) {
b_tp = true;
s_tp = now;
} else {
2018-12-08 05:30:43 +00:00
ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - s_tp).count();
}
2018-01-26 19:46:35 +00:00
#endif
2018-12-08 05:30:43 +00:00
if (!xf0_24_disabled) {
bool updated = false;
for (size_t i = 0; i < x0_voices.size(); ++i) {
const float intensity = x0_voices[i].GetIntensity();
2018-12-08 05:30:43 +00:00
if (!x0_voices[i].Update(dt) || intensity <= 0.f) {
xc0_periodTime[i] = 0.f;
xd0_onTime[i] = 0.f;
if (xe0_commandArray[i] != EMotorState::Stop) {
2018-01-26 19:46:35 +00:00
#if PWM_MONITOR
2018-12-08 05:30:43 +00:00
s_tp = now;
fmt::print(FMT_STRING("{}ms ON\n"), ms);
2018-01-26 19:46:35 +00:00
#endif
2018-12-08 05:30:43 +00:00
xe0_commandArray[i] = EMotorState::Stop;
updated = true;
}
} else {
xc0_periodTime[i] += dt;
if (xc0_periodTime[i] >= 1.f / (30.f * intensity)) {
xc0_periodTime[i] = 0.f;
if (xe0_commandArray[i] != EMotorState::Rumble) {
2018-01-26 19:46:35 +00:00
#if PWM_MONITOR
2018-12-08 05:30:43 +00:00
s_tp = now;
fmt::print(FMT_STRING("{}ms Off\n"), ms);
2018-01-26 19:46:35 +00:00
#endif
2018-12-08 05:30:43 +00:00
xe0_commandArray[i] = EMotorState::Rumble;
updated = true;
}
} else {
xd0_onTime[i] += dt;
if (xd0_onTime[i] >= (1.f / 30.f)) {
xd0_onTime[i] = 0.f;
if (xe0_commandArray[i] != EMotorState::Stop) {
2018-01-26 19:46:35 +00:00
#if PWM_MONITOR
2018-12-08 05:30:43 +00:00
s_tp = now;
fmt::print(FMT_STRING("{}ms ON\n"), ms);
2018-01-26 19:46:35 +00:00
#endif
2018-12-08 05:30:43 +00:00
xe0_commandArray[i] = EMotorState::Stop;
updated = true;
2018-01-26 09:48:42 +00:00
}
2018-12-08 05:30:43 +00:00
}
2018-01-26 09:48:42 +00:00
}
2018-12-08 05:30:43 +00:00
}
2018-01-26 09:48:42 +00:00
}
2018-12-08 05:30:43 +00:00
if (updated)
g_InputGenerator->ControlAllMotors(xe0_commandArray);
}
}
2018-12-08 05:30:43 +00:00
void CRumbleGenerator::HardStopAll() {
static constexpr std::array HardStopCommands{
EMotorState::StopHard,
EMotorState::StopHard,
EMotorState::StopHard,
EMotorState::StopHard,
};
xc0_periodTime.fill(0.0f);
xd0_onTime.fill(0.0f);
xe0_commandArray.fill(EMotorState::Stop);
for (auto& voice : x0_voices) {
voice.HardReset();
2018-12-08 05:30:43 +00:00
}
2018-12-08 05:30:43 +00:00
g_InputGenerator->ControlAllMotors(HardStopCommands);
}
2018-12-08 05:30:43 +00:00
s16 CRumbleGenerator::Rumble(const SAdsrData& adsr, float gain, ERumblePriority prio, EIOPort port) {
CRumbleVoice& vox = x0_voices[size_t(port)];
const s16 freeChan = vox.GetFreeChannel();
2018-12-08 05:30:43 +00:00
if (prio >= vox.GetPriority(freeChan)) {
xc0_periodTime[size_t(port)] = 0.f;
2018-12-08 05:30:43 +00:00
return vox.Activate(adsr, freeChan, gain, prio);
}
return -1;
2018-01-26 09:48:42 +00:00
}
2018-12-08 05:30:43 +00:00
void CRumbleGenerator::Stop(s16 id, EIOPort port) {
CRumbleVoice& vox = x0_voices[size_t(port)];
2018-12-08 05:30:43 +00:00
vox.Deactivate(id, false);
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce