33 */
44
55#pragma once
6- #include < C++Utilities/CppUtils.hpp>
6+ #include " C++Utilities/CppUtils.hpp"
77#include " Time/Time.hpp"
88#include " ErrorHandler/ErrorHandler.hpp"
99
@@ -13,31 +13,100 @@ typedef std::chrono::milliseconds ms;
1313typedef std::chrono::microseconds us;
1414typedef std::chrono::seconds s;
1515
16+ enum AlarmType{
17+ LOW_PRECISION,
18+ MID_PRECISION,
19+ HIGH_PRECISION
20+ };
21+
1622class TimedAction {
1723public:
1824 function<void ()> action;
19- uint32_t microseconds;
25+ uint32_t period;
26+ AlarmType alarm_precision;
27+ uint8_t id = -1 ;
2028
2129 TimedAction () = default ;
22- TimedAction (function<void ()> action, uint32_t microseconds);
2330};
2431
2532class State {
2633public:
27- vector<TimedAction> cyclic_actions = {} ;
34+ vector<TimedAction> cyclic_actions;
2835 vector<function<void ()>> on_enter_actions = {};
2936 vector<function<void ()>> on_exit_actions = {};
3037 void enter ();
3138 void exit ();
39+ template <class TimeUnit >
40+ void add_new_timed_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, AlarmType precision_type);
41+ template <class TimeUnit >
42+ void register_new_timed_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, AlarmType precision_type);
43+ void unregister_all_timed_actions ();
44+ void register_all_timed_actions ();
3245};
3346
47+ template <class TimeUnit >
48+ void State::register_new_timed_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, AlarmType precision_type){
49+ TimedAction timed_action = {};
50+ timed_action.alarm_precision = precision_type;
51+ timed_action.action = action;
52+ uint32_t miliseconds = chrono::duration_cast<chrono::milliseconds>(period).count ();
53+ uint32_t microseconds = chrono::duration_cast<chrono::microseconds>(period).count ();
54+ switch (precision_type) {
55+ case LOW_PRECISION:
56+ timed_action.period = miliseconds;
57+ timed_action.id = Time::register_low_precision_alarm (miliseconds, action);
58+ break ;
59+ case MID_PRECISION:
60+ timed_action.period = microseconds;
61+ timed_action.id = Time::register_mid_precision_alarm (microseconds, action).value ();
62+ break ;
63+ case HIGH_PRECISION:
64+ timed_action.period = microseconds;
65+ timed_action.id = Time::register_high_precision_alarm (microseconds, action).value ();
66+ break ;
67+ default :
68+ ErrorHandler (" Alarm Precision Type does not exist, AlarmType: %d" , precision_type);
69+ return ;
70+ break ;
71+ }
72+ cyclic_actions.push_back (timed_action);
73+ }
74+
75+ template <class TimeUnit >
76+ void State::add_new_timed_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, AlarmType precision_type){
77+ TimedAction timed_action = {};
78+ timed_action.alarm_precision = precision_type;
79+ timed_action.action = action;
80+ uint32_t miliseconds = chrono::duration_cast<chrono::milliseconds>(period).count ();
81+ uint32_t microseconds = chrono::duration_cast<chrono::microseconds>(period).count ();
82+ switch (precision_type) {
83+ case LOW_PRECISION:
84+ timed_action.period = miliseconds;
85+ break ;
86+ case MID_PRECISION:
87+ timed_action.period = microseconds;
88+ break ;
89+ case HIGH_PRECISION:
90+ timed_action.period = microseconds;
91+ break ;
92+ default :
93+ ErrorHandler (" Alarm Precision Type does not exist, AlarmType: %d" , precision_type);
94+ return ;
95+ break ;
96+ }
97+ cyclic_actions.push_back (timed_action);
98+ }
99+
100+
34101class StateMachine {
35102public:
36103 typedef uint8_t state_id;
37104
38105 state_id initial_state = 0 ;
39106 state_id current_state = 0 ;
40107
108+ bool is_on = true ;
109+
41110
42111 StateMachine () = default ;
43112 StateMachine (state_id initial_state);
@@ -46,9 +115,19 @@ class StateMachine {
46115 void add_transition (state_id old_state, state_id new_state, function<bool ()> transition);
47116
48117 template <class TimeUnit >
49- void add_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period);
118+ void add_low_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period);
50119 template <class TimeUnit >
51- void add_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state);
120+ void add_low_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state);
121+
122+ template <class TimeUnit >
123+ void add_mid_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period);
124+ template <class TimeUnit >
125+ void add_mid_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state);
126+
127+ template <class TimeUnit >
128+ void add_high_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period);
129+ template <class TimeUnit >
130+ void add_high_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state);
52131
53132 void add_enter_action (function<void ()> action);
54133 void add_enter_action (function<void ()> action, state_id state);
@@ -65,42 +144,76 @@ class StateMachine {
65144private:
66145 unordered_map<state_id, State> states;
67146 unordered_map<state_id, unordered_map<state_id, function<bool ()>>> transitions;
68-
69147 unordered_map<state_id, StateMachine*> nested_state_machine;
70- vector<uint8_t > current_state_timed_actions_in_milliseconds;
71- vector<uint8_t > current_state_timed_actions_in_microseconds;
72148};
73149
74150template <class TimeUnit >
75- void StateMachine::add_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state) {
151+ void StateMachine::add_low_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state) {
152+ if (not states.contains (state)) {
153+ ErrorHandler (" The state %d is not added to the state machine" , state);
154+ return ;
155+ }
156+
157+ uint32_t microseconds = (uint32_t )chrono::duration_cast<chrono::microseconds>(period).count ();
158+
159+ if (microseconds % 1000 != 0 ){
160+ ErrorHandler (" Low precision cyclic action does not have enough resolution for the desired period, Desired period: %d uS" , microseconds);
161+ return ;
162+ }
163+
164+ if (state == current_state && is_on) states[state].register_new_timed_action (action, period, LOW_PRECISION);
165+ else states[state].add_new_timed_action (action, period,LOW_PRECISION);
166+ }
167+
168+ template <class TimeUnit >
169+ void StateMachine::add_low_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period){
170+ add_low_precision_cyclic_action (action, period, current_state);
171+ }
172+
173+ template <class TimeUnit >
174+ void StateMachine::add_mid_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state) {
175+ if (not states.contains (state)) {
176+ ErrorHandler (" The state %d is not added to the state machine" , state);
177+ return ;
178+ }
179+
180+ uint32_t microseconds = (uint32_t )chrono::duration_cast<chrono::microseconds>(period).count ();
181+
182+ if (microseconds % 50 != 0 ){
183+ ErrorHandler (" Mid precision cyclic action does not have enough resolution for the desired period, Desired period: %d uS" , microseconds);
184+ return ;
185+ }
186+
187+ if (state == current_state && is_on) states[state].register_new_timed_action (action, period, MID_PRECISION);
188+ else states[state].add_new_timed_action (action, period,MID_PRECISION);
189+ }
190+
191+ template <class TimeUnit >
192+ void StateMachine::add_mid_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period){
193+ add_mid_precision_cyclic_action (action, period, current_state);
194+ }
195+
196+ template <class TimeUnit >
197+ void StateMachine::add_high_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period, state_id state) {
76198 if (not states.contains (state)) {
77199 ErrorHandler (" The state %d is not added to the state machine" , state);
78200 return ;
79201 }
80202
81203 uint32_t microseconds = (uint32_t )chrono::duration_cast<chrono::microseconds>(period).count ();
82- TimedAction timed_action (action, microseconds);
83- states[state].cyclic_actions .push_back (timed_action);
84-
85- if (state == current_state) {
86- if (microseconds % 1000 ) {
87- optional<uint8_t > optional_id = Time::register_high_precision_alarm (microseconds, action);
88- if (not optional_id) {
89- ErrorHandler (" The high precision alarm could not be registered" );
90- return ;
91- }
92- current_state_timed_actions_in_microseconds.push_back (optional_id.value ());
93- }
94- else {
95- uint8_t id = Time::register_low_precision_alarm (microseconds, action);
96- current_state_timed_actions_in_milliseconds.push_back (id);
97- }
204+
205+ if (microseconds < 1 ){
206+ ErrorHandler (" High precision cyclic action does not have enough resolution for the desired period, Desired period: %d uS" , microseconds);
207+ return ;
98208 }
209+
210+ if (state == current_state && is_on) states[state].register_new_timed_action (action, period, HIGH_PRECISION);
211+ else states[state].add_new_timed_action (action, period,HIGH_PRECISION);
99212}
100213
101214template <class TimeUnit >
102- void StateMachine::add_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period){
103- add_cyclic_action (action, period, current_state);
215+ void StateMachine::add_high_precision_cyclic_action (function<void ()> action, chrono::duration<int64_t, TimeUnit> period){
216+ add_high_precision_cyclic_action (action, period, current_state);
104217}
105218
106219#endif
0 commit comments