2016-01-13 03:19:56 +00:00
|
|
|
//
|
|
|
|
// Stepper.hpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 12/01/2016.
|
2018-05-13 19:19:52 +00:00
|
|
|
// Copyright 2016 Thomas Harte. All rights reserved.
|
2016-01-13 03:19:56 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#ifndef Stepper_hpp
|
|
|
|
#define Stepper_hpp
|
|
|
|
|
2017-11-11 20:28:40 +00:00
|
|
|
#include <cstdint>
|
2016-01-13 03:19:56 +00:00
|
|
|
|
|
|
|
namespace SignalProcessing {
|
|
|
|
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
Allows a repeating action running at an input rate to determine how many times it should
|
|
|
|
trigger an action that runs at an unrelated output rate; therefore it allows something with one
|
|
|
|
clock to sample something with another.
|
|
|
|
|
|
|
|
Uses a Bresenham-like error term internally for full-integral storage with no drift.
|
2016-07-31 17:32:30 +00:00
|
|
|
|
|
|
|
Pegs the beginning of both clocks to the time at which the stepper is created. So e.g. a stepper
|
|
|
|
that converts from an input clock of 1200 to an output clock of 2 will first fire on cycle 600.
|
2016-07-29 09:19:01 +00:00
|
|
|
*/
|
2017-03-26 18:34:47 +00:00
|
|
|
class Stepper {
|
2016-01-13 03:19:56 +00:00
|
|
|
public:
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
Establishes a stepper with a one-to-one conversion rate.
|
|
|
|
*/
|
2016-02-13 03:35:16 +00:00
|
|
|
Stepper() : Stepper(1,1) {}
|
|
|
|
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
Establishes a stepper that will receive steps at the @c input_rate and dictate the number
|
|
|
|
of steps that should be taken at the @c output_rate.
|
|
|
|
*/
|
2016-02-13 03:35:16 +00:00
|
|
|
Stepper(uint64_t output_rate, uint64_t input_rate) :
|
2020-05-10 03:00:39 +00:00
|
|
|
accumulated_error_(-(int64_t(input_rate) << 1)),
|
2016-02-13 03:35:16 +00:00
|
|
|
input_rate_(input_rate),
|
|
|
|
output_rate_(output_rate),
|
|
|
|
whole_step_(output_rate / input_rate),
|
2020-05-10 03:00:39 +00:00
|
|
|
adjustment_up_(int64_t(output_rate % input_rate) << 1),
|
|
|
|
adjustment_down_(int64_t(input_rate) << 1) {}
|
2016-01-20 03:05:34 +00:00
|
|
|
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
Advances one step at the input rate.
|
|
|
|
|
|
|
|
@returns the number of output steps.
|
|
|
|
*/
|
2017-03-26 18:34:47 +00:00
|
|
|
inline uint64_t step() {
|
2016-01-13 03:19:56 +00:00
|
|
|
uint64_t update = whole_step_;
|
|
|
|
accumulated_error_ += adjustment_up_;
|
2017-03-26 18:34:47 +00:00
|
|
|
if(accumulated_error_ > 0) {
|
2016-01-13 03:19:56 +00:00
|
|
|
update++;
|
|
|
|
accumulated_error_ -= adjustment_down_;
|
|
|
|
}
|
|
|
|
return update;
|
|
|
|
}
|
|
|
|
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
Advances by @c number_of_steps steps at the input rate.
|
|
|
|
|
|
|
|
@returns the number of output steps.
|
|
|
|
*/
|
2017-03-26 18:34:47 +00:00
|
|
|
inline uint64_t step(uint64_t number_of_steps) {
|
2016-07-29 09:19:01 +00:00
|
|
|
uint64_t update = whole_step_ * number_of_steps;
|
2020-05-10 03:00:39 +00:00
|
|
|
accumulated_error_ += adjustment_up_ * int64_t(number_of_steps);
|
2017-03-26 18:34:47 +00:00
|
|
|
if(accumulated_error_ > 0) {
|
2020-05-10 03:00:39 +00:00
|
|
|
update += 1 + uint64_t(accumulated_error_ / adjustment_down_);
|
2016-07-29 09:19:01 +00:00
|
|
|
accumulated_error_ = (accumulated_error_ % adjustment_down_) - adjustment_down_;
|
|
|
|
}
|
|
|
|
return update;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
@returns the output rate.
|
|
|
|
*/
|
2017-03-26 18:34:47 +00:00
|
|
|
inline uint64_t get_output_rate() {
|
2016-01-20 03:05:34 +00:00
|
|
|
return output_rate_;
|
|
|
|
}
|
|
|
|
|
2016-07-29 09:19:01 +00:00
|
|
|
/*!
|
|
|
|
@returns the input rate.
|
|
|
|
*/
|
2017-03-26 18:34:47 +00:00
|
|
|
inline uint64_t get_input_rate() {
|
2016-01-20 03:05:34 +00:00
|
|
|
return input_rate_;
|
|
|
|
}
|
|
|
|
|
2016-01-13 03:19:56 +00:00
|
|
|
private:
|
|
|
|
int64_t accumulated_error_;
|
2016-01-20 03:05:34 +00:00
|
|
|
uint64_t input_rate_, output_rate_;
|
2017-11-09 03:36:41 +00:00
|
|
|
uint64_t whole_step_;
|
|
|
|
int64_t adjustment_up_, adjustment_down_;
|
2016-01-13 03:19:56 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* Stepper_hpp */
|