mirror of
https://github.com/jhbruhn/eurorack.git
synced 2025-03-14 18:55:48 +00:00
179 lines
5.4 KiB
C++
179 lines
5.4 KiB
C++
// Copyright 2015 Emilie Gillet.
|
|
//
|
|
// Author: Emilie Gillet (emilie.o.gillet@gmail.com)
|
|
// modified for ints by Jan-Henrik Bruhn (hi@jhbruhn.de)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
//
|
|
// See http://creativecommons.org/licenses/MIT/ for more information.
|
|
//
|
|
// -----------------------------------------------------------------------------
|
|
//
|
|
// Handles the "hold button to tweak a hidden parameter" behaviour of pots.
|
|
// A pot can be in 4 states:
|
|
// - POT_STATE_TRACKING: the main parameter tracks the position of the pot.
|
|
// - POT_STATE_LOCKING: the main parameter no longer tracks the position of
|
|
// the pot. We wait for the pot to move further from its original position
|
|
// to start modifying the hidden parameter.
|
|
// - POT_STATE_HIDDEN_PARAMETER: the hidden parameter tracks the position of
|
|
// the pot.
|
|
// - POT_STATE_CATCHING_UP: the pot adjusts the main parameter in a relative
|
|
// way, until the position of the pot and the value of the parameter match
|
|
// again.
|
|
|
|
#pragma once
|
|
|
|
#include "stmlib/dsp/dsp.h"
|
|
#include "stmlib/stmlib.h"
|
|
|
|
enum PotState {
|
|
POT_STATE_TRACKING,
|
|
POT_STATE_LOCKING,
|
|
POT_STATE_HIDDEN_PARAMETER,
|
|
POT_STATE_CATCHING_UP
|
|
};
|
|
|
|
template<size_t hidden_parameter_count>
|
|
class PotController {
|
|
public:
|
|
PotController() { }
|
|
~PotController() { }
|
|
|
|
void Init(
|
|
uint16_t* main_parameter,
|
|
uint16_t* hidden_parameters[hidden_parameter_count]) // this pot controller always works on values between 0 and 65535
|
|
{
|
|
state_ = POT_STATE_TRACKING;
|
|
was_catching_up_ = false;
|
|
|
|
main_parameter_ = main_parameter;
|
|
current_hidden_parameter_ = 0;
|
|
|
|
for(size_t i = 0; i < hidden_parameter_count; i++)
|
|
hidden_parameters_[i] = hidden_parameters[i];
|
|
|
|
value_ = 0;
|
|
stored_value_ = 0;
|
|
previous_value_ = 0;
|
|
}
|
|
|
|
inline void Lock(uint8_t selected_parameter)
|
|
{
|
|
if (selected_parameter > hidden_parameter_count)
|
|
return;
|
|
if (state_ == POT_STATE_LOCKING || state_ == POT_STATE_HIDDEN_PARAMETER) {
|
|
return;
|
|
}
|
|
if (hidden_parameters_[selected_parameter]) {
|
|
current_hidden_parameter_ = selected_parameter;
|
|
was_catching_up_ = state_ == POT_STATE_CATCHING_UP;
|
|
state_ = POT_STATE_LOCKING;
|
|
}
|
|
}
|
|
|
|
inline bool editing_hidden_parameter() const
|
|
{
|
|
return state_ == POT_STATE_HIDDEN_PARAMETER;
|
|
}
|
|
|
|
inline void Unlock()
|
|
{
|
|
if (state_ == POT_STATE_HIDDEN_PARAMETER || was_catching_up_) {
|
|
state_ = POT_STATE_CATCHING_UP;
|
|
} else {
|
|
state_ = POT_STATE_TRACKING;
|
|
}
|
|
}
|
|
|
|
inline void Realign()
|
|
{
|
|
state_ = POT_STATE_TRACKING;
|
|
}
|
|
|
|
inline void ProcessControlRate(uint16_t adc_value)
|
|
{
|
|
value_ += (adc_value - value_) >> 5;
|
|
CONSTRAIN(value_, 0, 65535);
|
|
// approximately this:
|
|
// ONE_POLE(value_, adc_value, 0.01f);
|
|
|
|
if (state_ == POT_STATE_TRACKING) {
|
|
*main_parameter_ = value_;
|
|
}
|
|
}
|
|
|
|
inline void ProcessUIRate()
|
|
{
|
|
switch (state_) {
|
|
case POT_STATE_TRACKING:
|
|
previous_value_ = value_;
|
|
break;
|
|
|
|
case POT_STATE_LOCKING:
|
|
if (abs(value_ - previous_value_) > 1966) {
|
|
stored_value_ = previous_value_;
|
|
CONSTRAIN(value_, 0, 65535);
|
|
*hidden_parameters_[current_hidden_parameter_] = value_;
|
|
state_ = POT_STATE_HIDDEN_PARAMETER;
|
|
previous_value_ = value_;
|
|
}
|
|
break;
|
|
|
|
case POT_STATE_HIDDEN_PARAMETER:
|
|
CONSTRAIN(value_, 0, 65535);
|
|
*hidden_parameters_[current_hidden_parameter_] = value_;
|
|
previous_value_ = value_;
|
|
break;
|
|
|
|
case POT_STATE_CATCHING_UP: {
|
|
if (abs(value_ - previous_value_) > 327) {
|
|
int32_t delta = value_ - previous_value_;
|
|
|
|
int32_t skew_ratio = delta > 0
|
|
? (65600 - stored_value_) / (65600 - previous_value_)
|
|
: (66 + stored_value_) / (66 + previous_value_);
|
|
CONSTRAIN(skew_ratio, 6553, 655350);
|
|
|
|
stored_value_ += (skew_ratio * delta) >> 12;
|
|
CONSTRAIN(stored_value_, 0, 65535);
|
|
|
|
if (abs(stored_value_ - value_) < 327) {
|
|
state_ = POT_STATE_TRACKING;
|
|
}
|
|
*main_parameter_ = stored_value_;
|
|
previous_value_ = value_;/*
|
|
state_ = POT_STATE_TRACKING;
|
|
*main_parameter_ = value_;*/
|
|
}
|
|
} break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
PotState state_;
|
|
bool was_catching_up_;
|
|
uint16_t* main_parameter_;
|
|
uint16_t* hidden_parameters_[hidden_parameter_count];
|
|
uint8_t current_hidden_parameter_;
|
|
int32_t value_;
|
|
int32_t stored_value_;
|
|
int32_t previous_value_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PotController);
|
|
};
|