I'm trying to model a pulse waveform in my application
and I need a way to keep track of the pulses so that I can repeat
their sequence. From the figure shown below, what I'd like to do is
simulate the first three pulses (pulse 1-3), then simulate pulse 4
immediately after pulse 3, and simulate pulse 5 immediately after 4.
Then repeat the whole sequence N times.
As shown in the diagram, I have the interval in seconds,
the start time of the first pulse in seconds, and the duration of
each pulse also in seconds. My application will be running real time
in a run loop where it will be executing at 1 Hz.
My question is, how do I keep track of all the pulses and make sure
they are all simulated with respect to each other? What I mean by simulated is,
for example I'd like to print a simple statement during the duration of the
1st three pulses, and the same for pulse 4 and 5. Can someone suggest a pseudo
algorithm at the very least for this operation?
Defining the class sequence
as follows, we can simply check activity of each pulse by sequence::isActive
.
DEMO is here.
class sequence
{
int period_;
int start_;
int end_;
std::array<std::pair<int,int>, 5> pulses;
public:
sequence(int start, int duration, int interval, int repeat)
: period_(2*interval+3*duration),
start_(start),
end_(start+repeat*period_),
pulses
{{
{0 , duration }, // pulse 1
{interval , interval + duration}, // pulse 2
{2*interval , 2*interval+ duration}, // pulse 3
{2*interval+ duration, 2*interval+2*duration}, // pulse 4
{2*interval+2*duration, period_ } // pulse 5
}}
{
if(duration <= 0){
throw std::runtime_error("Duration must be positive integer.");
}
if(interval < 0){
throw std::runtime_error("Interval must be non negative integer.");
}
}
bool isActive(int time, std::size_t idx) const
{
const auto& pulse = pulses[idx];
// 0 for each start time of sequence (pulse 1)
const auto refTime = (time - start_)%period_;
return (pulse.first <= refTime) && (refTime < pulse.second) && (time < end_);
}
int getPeriod() const{
return period_;
}
int getStartTime() const{
return start_;
}
int getEndTime() const{
return end_;
}
std::size_t getPulseNum() const{
return pulses.size();
}
};
Assuming I understood the problem correctly, the way I would do it is to use modulo-arithmetic, and characterize each pulse-train as a boolean function with a timestamp as a parameter to the function, e.g.:
// Returns true iff the pulse is present at the specified time
bool IsPulseActiveAtTime(long int theTime);
The benefit of doing it this way is that you can simulate an infinite series of pulses while using only a small, fixed amount of memory. It also allows you to efficiently query what the expected state of each pulse-train was/will-be at any past/future time (i.e. not just as at the current time), should you need to do so.
Here's a simple demonstration program that prints out a ticker-tape of four pulses over the course of 100 simulated "seconds":
#include <stdio.h>
class PulseSequence
{
public:
PulseSequence(long int startTime, long int duration, long int interval)
: _startTime(startTime)
, _duration(duration)
, _interval(interval)
{
// empty
}
bool IsPulseActiveAtTime(long int theTime) const
{
if (theTime < _startTime) return false;
return ((theTime-_startTime) % _interval) < _duration;
}
private:
const long int _startTime; // time at which the first pulse starts
const long int _duration; // length of each pulse
const long int _interval; // difference between the start-time of one pulse and the start-time of the next
};
// Unit test/example
int main(int, char **)
{
const int NUM_PULSE_SEQUENCES = 4;
const PulseSequence sequences[NUM_PULSE_SEQUENCES] = {
PulseSequence(0, 3, 5),
PulseSequence(1, 2, 6),
PulseSequence(3, 3, 4),
PulseSequence(5, 1, 3),
};
for (long int curTime = 0; curTime < 100; curTime++)
{
printf("curTime=%02li: [", curTime);
for (int i=0; i<NUM_PULSE_SEQUENCES; i++) putchar(sequences[i].IsPulseActiveAtTime(curTime)?('0'+i):' ');
printf("]\n");
}
return 0;
}
The output looks like this:
$ ./a.out
curTime=00: [0 ]
curTime=01: [01 ]
curTime=02: [01 ]
curTime=03: [ 2 ]
curTime=04: [ 2 ]
curTime=05: [0 23]
curTime=06: [0 ]
curTime=07: [012 ]
curTime=08: [ 123]
curTime=09: [ 2 ]
curTime=10: [0 ]
curTime=11: [0 23]
curTime=12: [0 2 ]
curTime=13: [ 12 ]
[...]