-
Notifications
You must be signed in to change notification settings - Fork 0
/
Pulser.hpp
90 lines (70 loc) · 2.54 KB
/
Pulser.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#ifndef _PULSER_HPP_
#define _PULSER_HPP_
#include <thread>
#include <mutex>
#include <chrono>
#include <math.h>
#include <iostream>
const int GIGA = 1000000000; // 10^9
namespace commbot{
class Pulser{
public:
Pulser(const float_t &freq=0) noexcept(false){
set_freq(freq);
thread_timer_ = std::thread{&Pulser::timer, this}; // start timer thread
}
~Pulser() noexcept(false){
is_on_ = false; // stops thread
if(thread_timer_.joinable()) thread_timer_.join();
else throw std::runtime_error("~Pulser: thread not joinable.");
}
bool get_state(){
std::lock_guard<std::mutex> guard_state(mutex_);
return state_;
}
void set_freq(const float_t &freq) noexcept(false){
std::lock_guard<std::mutex> guard_period(mutex_);
if(freq < 0) throw std::invalid_argument("Pulser: tried to set illegal frequency of " + std::to_string(freq) + " Hz");
else if(freq == 0){
period_ = 9999; // unused
state_ = false;
}
else period_ = 1/freq;
}
void activate(const float_t &freq) {
set_is_active(true);
set_freq(freq);
}
void deactivate() {
set_is_active(false);
set_freq(0);
}
private:
bool is_on_ = true; // controls timer thread
bool is_active_ = false;
bool state_ = false; // pulse state
std::mutex mutex_; // protect fields used in timer thread
float_t period_; // period in seconds
std::thread thread_timer_;
// Sets is_active_ using lock_guard
void set_is_active(const bool &is_active){
std::lock_guard<std::mutex> guard_is_active(mutex_);
is_active_ = is_active;
}
// Changes state_ at freq_
void timer() noexcept{
std::chrono::steady_clock::time_point t_prev = std::chrono::steady_clock::now();
while(is_on_){
if(!is_active_) state_ = false;
else{
if(std::chrono::steady_clock::now().time_since_epoch().count()
- t_prev.time_since_epoch().count() > period_*GIGA){
state_ = !state_; // change state
t_prev = std::chrono::steady_clock::now(); // track time of state change
}
}
}
}
}; // end Pulser class
} // end commbot namespace
#endif