Embedded Template Library 1.0
Loading...
Searching...
No Matches
fsm.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2017 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#if 0
30#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE.
31#endif
32
33//***************************************************************************
34// THIS FILE HAS BEEN AUTO GENERATED. DO NOT EDIT THIS FILE.
35//***************************************************************************
36
37//***************************************************************************
38// To generate to header file, run this at the command line.
39// Note: You will need Python and COG installed.
40//
41// cog -d -e -ofsm.h -DHandlers=<n> fsm_generator.h
42// Where <n> is the number of messages to support.
43//
44// e.g.
45// To generate handlers for up to 16 events...
46// cog -d -e -ofsm.h -DHandlers=16 fsm_generator.h
47//
48// See generate.bat
49//***************************************************************************
50
51#ifndef ETL_FSM_INCLUDED
52#define ETL_FSM_INCLUDED
53
54#include "platform.h"
55#include "array.h"
56#include "nullptr.h"
57#include "error_handler.h"
58#include "exception.h"
59#include "user_type.h"
60#include "message_router.h"
61#include "integral_limits.h"
62#include "largest.h"
63#if ETL_USING_CPP11
64 #include "tuple.h"
65#endif
66
67#include <stdint.h>
68
69#include "private/minmax_push.h"
70
71namespace etl
72{
73 class fsm;
74 class hfsm;
75
77#if !defined(ETL_FSM_STATE_ID_TYPE)
78 typedef uint_least8_t fsm_state_id_t;
79#else
80 typedef ETL_FSM_STATE_ID_TYPE fsm_state_id_t;
81#endif
82
83 // For internal FSM use.
84 typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
85
86#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
87 template <typename, typename, etl::fsm_state_id_t, typename...>
88 class fsm_state;
89#else
90 template <typename, typename, etl::fsm_state_id_t,
91 typename, typename, typename, typename,
92 typename, typename, typename, typename,
93 typename, typename, typename, typename,
94 typename, typename, typename, typename>
95 class fsm_state;
96#endif
97
98 //***************************************************************************
100 //***************************************************************************
101 class fsm_exception : public etl::exception
102 {
103 public:
104
105 fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
106 : etl::exception(reason_, file_name_, line_number_)
107 {
108 }
109 };
110
111 //***************************************************************************
113 //***************************************************************************
114 class fsm_null_state_exception : public etl::fsm_exception
115 {
116 public:
117
118 fsm_null_state_exception(string_type file_name_, numeric_type line_number_)
119 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FSM_FILE_ID"A"), file_name_, line_number_)
120 {
121 }
122 };
123
124 //***************************************************************************
126 //***************************************************************************
127 class fsm_state_id_exception : public etl::fsm_exception
128 {
129 public:
130
131 fsm_state_id_exception(string_type file_name_, numeric_type line_number_)
132 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FSM_FILE_ID"B"), file_name_, line_number_)
133 {
134 }
135 };
136
137 //***************************************************************************
139 //***************************************************************************
140 class fsm_state_list_exception : public etl::fsm_exception
141 {
142 public:
143
144 fsm_state_list_exception(string_type file_name_, numeric_type line_number_)
145 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FSM_FILE_ID"C"), file_name_, line_number_)
146 {
147 }
148 };
149
150 //***************************************************************************
152 //***************************************************************************
153 class fsm_state_list_order_exception : public etl::fsm_exception
154 {
155 public:
156
157 fsm_state_list_order_exception(string_type file_name_, numeric_type line_number_)
158 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list order", ETL_FSM_FILE_ID"D"), file_name_, line_number_)
159 {
160 }
161 };
162
163 //***************************************************************************
165 //***************************************************************************
166 class fsm_not_started : public etl::fsm_exception
167 {
168 public:
169 fsm_not_started(string_type file_name_, numeric_type line_number_)
170 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
171 {
172 }
173 };
174
175 //***************************************************************************
178 //***************************************************************************
179 class fsm_reentrant_transition_forbidden : public etl::fsm_exception
180 {
181 public:
182 fsm_reentrant_transition_forbidden(string_type file_name_, numeric_type line_number_)
183 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:reentrant calls to start/receive/etc. forbidden", ETL_FSM_FILE_ID"G"), file_name_, line_number_)
184 {
185 }
186 };
187
188 namespace private_fsm
189 {
190 template <typename T = void>
192 {
193 public:
194
195 // Pass this whenever no state change is desired.
196 // The highest unsigned value of fsm_state_id_t.
197 static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
198
199 // Pass this when this event also needs to be passed to the parent.
200 static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
201
202 // Pass this when this event should trigger a self transition.
203 static ETL_CONSTANT fsm_state_id_t Self_Transition = No_State_Change - 2U;
204 };
205
206 template <typename T>
207 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::No_State_Change;
208
209 template <typename T>
210 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Pass_To_Parent;
211
212 template <typename T>
213 ETL_CONSTANT fsm_state_id_t ifsm_state_helper<T>::Self_Transition;
214
215 // Compile-time: TState::ID must equal its index in the type list (0..N-1)
216 template <size_t Id, typename...> struct check_ids : etl::true_type
217 {
218 };
219
220 template <size_t Id, typename TState0, typename... TRest>
221 struct check_ids<Id, TState0, TRest...>
222 : etl::integral_constant<bool, (TState0::STATE_ID == Id) && private_fsm::check_ids<Id + 1, TRest...>::value>
223 {
224 };
225
226 //***************************************************************************
230 //***************************************************************************
232 {
233 public:
234 //*******************************************
237 //*******************************************
238 fsm_reentrancy_guard(bool& transition_guard_flag)
239 : is_locked(transition_guard_flag)
240 {
242 is_locked = true;
243 }
244
245 //*******************************************
248 //*******************************************
250 {
251 is_locked = false;
252 }
253
254 private:
255 // Reference to the flag signifying a lock on the state machine.
256 bool& is_locked;
257
258 // Copy & move semantics disabled since this is a guard.
260 fsm_reentrancy_guard& operator= (fsm_reentrancy_guard const&) ETL_DELETE;
261#if ETL_USING_CPP11
263 fsm_reentrancy_guard& operator= (fsm_reentrancy_guard&&) ETL_DELETE;
264#endif
265 };
266 }
267
268 class ifsm_state;
269
270#if ETL_USING_CPP11
271 //***************************************************************************
273 //***************************************************************************
274 template <typename... TStates>
275 class fsm_state_pack
276 {
277 public:
278
279 friend class etl::fsm;
280
281 ETL_STATIC_ASSERT((private_fsm::check_ids<0, TStates...>::value), "State IDs must be 0..N-1 and in order");
282 ETL_STATIC_ASSERT(sizeof...(TStates) > 0, "At least one state is required");
283 ETL_STATIC_ASSERT(sizeof...(TStates) < private_fsm::ifsm_state_helper<>::No_State_Change, "State IDs mst be less than ifsm_state::No_State_Change");
284
285 //*********************************
286 // The number of states.
287 //*********************************
288 static ETL_CONSTEXPR size_t size()
289 {
290 return sizeof...(TStates);
291 }
292
293 //*********************************
295 //*********************************
296 template <typename TState>
297 TState& get()
298 {
299 return etl::get<TState>(storage);
300 }
301
302 //*********************************
304 //*********************************
305 template <typename TState>
306 const TState& get() const
307 {
308 return etl::get<TState>(storage);
309 }
310
311 private:
312
313 //*********************************
315 //*********************************
316 etl::ifsm_state** get_state_list()
317 {
318 return &states[0];
319 }
320
322 etl::tuple<TStates...> storage{};
323
325 etl::ifsm_state* states[sizeof...(TStates)]{ &etl::get<TStates>(storage)... };
326 };
327#endif
328
329 //***************************************************************************
331 //***************************************************************************
333 {
334 public:
335
337 friend class etl::fsm;
338 friend class etl::hfsm;
339
340 using private_fsm::ifsm_state_helper<>::No_State_Change;
341 using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
342 using private_fsm::ifsm_state_helper<>::Self_Transition;
343
344#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
345 template <typename, typename, etl::fsm_state_id_t, typename...>
346 friend class fsm_state;
347#else
348 template <typename, typename, etl::fsm_state_id_t,
349 typename, typename, typename, typename,
350 typename, typename, typename, typename,
351 typename, typename, typename, typename,
352 typename, typename, typename, typename>
353 friend class etl::fsm_state;
354#endif
355
356 //*******************************************
358 //*******************************************
360 {
361 return state_id;
362 }
363
364 //*******************************************
367 //*******************************************
369 {
370 ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
371 state.p_parent = this;
372
373 if (p_default_child == ETL_NULLPTR)
374 {
375 p_default_child = &state;
376 }
377 }
378
379 //*******************************************
382 //*******************************************
383 template <typename TSize>
384 void set_child_states(etl::ifsm_state** state_list, TSize size)
385 {
386 p_active_child = ETL_NULLPTR;
387 p_default_child = ETL_NULLPTR;
388
389 for (TSize i = 0; i < size; ++i)
390 {
391 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
392 add_child_state(*state_list[i]);
393 }
394 }
395
396 protected:
397
398 //*******************************************
400 //*******************************************
402 : state_id(state_id_),
403 p_context(ETL_NULLPTR),
404 p_parent(ETL_NULLPTR),
405 p_active_child(ETL_NULLPTR),
406 p_default_child(ETL_NULLPTR)
407 {
408 }
409
410 //*******************************************
412 //*******************************************
413 virtual ~ifsm_state()
414 {
415 }
416
417 //*******************************************
418 etl::fsm& get_fsm_context() const
419 {
420 return *p_context;
421 }
422
423 private:
424
425 virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
426
427 virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
428 virtual void on_exit_state() {} // By default, do nothing.
429
430 //*******************************************
431 void set_fsm_context(etl::fsm& context)
432 {
433 p_context = &context;
434 }
435
436 // The state id.
437 const etl::fsm_state_id_t state_id;
438
439 // A pointer to the FSM context.
440 etl::fsm* p_context;
441
442 // A pointer to the parent.
443 ifsm_state* p_parent;
444
445 // A pointer to the active child.
446 ifsm_state* p_active_child;
447
448 // A pointer to the default active child.
449 ifsm_state* p_default_child;
450
451 // Disabled.
452 ifsm_state(const ifsm_state&) ETL_DELETE;
453 ifsm_state& operator =(const ifsm_state&) ETL_DELETE;
454 };
455
456 //***************************************************************************
458 //***************************************************************************
460 {
461 public:
462
463 friend class etl::hfsm;
464 using imessage_router::receive;
465
466 //*******************************************
468 //*******************************************
469 fsm(etl::message_router_id_t id)
470 : imessage_router(id)
471 , p_state(ETL_NULLPTR)
472 , state_list(ETL_NULLPTR)
473 , number_of_states(0U)
474 , is_processing_state_change(false)
475 {
476 }
477
478 //*******************************************
481 //*******************************************
482 template <typename TSize>
483 void set_states(etl::ifsm_state** p_states, TSize size)
484 {
485 state_list = p_states;
486 number_of_states = etl::fsm_state_id_t(size);
487
488 ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
489 ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
490
491 for (etl::fsm_state_id_t i = 0; i < size; ++i)
492 {
493 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
494 ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
495 state_list[i]->set_fsm_context(*this);
496 }
497 }
498
499#if ETL_USING_CPP11
500 //*******************************************
503 //*******************************************
504 template <typename... TStates>
505 void set_states(etl::fsm_state_pack<TStates...>& state_pack)
506 {
507 state_list = state_pack.get_state_list();
508 number_of_states = etl::fsm_state_id_t(state_pack.size());
509
510 for (etl::fsm_state_id_t i = 0; i < number_of_states; ++i)
511 {
512 state_list[i]->set_fsm_context(*this);
513 }
514 }
515#endif
516
517 //*******************************************
522 //*******************************************
523 virtual void start(bool call_on_enter_state = true)
524 {
525 private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change);
526
527 // Can only be started once.
528 if (!is_started())
529 {
530 p_state = state_list[0];
531 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
532
533 if (call_on_enter_state)
534 {
535 etl::fsm_state_id_t next_state_id;
536 etl::ifsm_state* p_last_state;
537
538 do
539 {
540 p_last_state = p_state;
541 next_state_id = p_state->on_enter_state();
542 if (next_state_id != ifsm_state::No_State_Change)
543 {
544 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
545 p_state = state_list[next_state_id];
546 }
547 } while (p_last_state != p_state);
548 }
549 }
550 }
551
552 //*******************************************
554 //*******************************************
555 void receive(const etl::imessage& message) ETL_OVERRIDE
556 {
557 private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change);
558
559 if (is_started())
560 {
561 etl::fsm_state_id_t next_state_id = p_state->process_event(message);
562
563 process_state_change(next_state_id);
564 }
565 else
566 {
567 ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
568 }
569 }
570
571 //*******************************************
573 //*******************************************
575 {
576 private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change);
577
578 if (is_started())
579 {
580 return process_state_change(new_state_id);
581 }
582 else
583 {
584 return ifsm_state::No_State_Change;
585 }
586 }
587
588 using imessage_router::accepts;
589
590 //*******************************************
593 //*******************************************
594 bool accepts(etl::message_id_t) const ETL_OVERRIDE
595 {
596 return true;
597 }
598
599 //*******************************************
601 //*******************************************
603 {
604 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
605 return p_state->get_state_id();
606 }
607
608 //*******************************************
610 //*******************************************
612 {
613 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
614 return *p_state;
615 }
616
617 //*******************************************
619 //*******************************************
620 const ifsm_state& get_state() const
621 {
622 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
623 return *p_state;
624 }
625
626 //*******************************************
628 //*******************************************
629 bool is_started() const
630 {
631 return p_state != ETL_NULLPTR;
632 }
633
634 //*******************************************
637 //*******************************************
638 virtual void reset(bool call_on_exit_state = false)
639 {
640 private_fsm::fsm_reentrancy_guard transition_lock(is_processing_state_change);
641
642 if (is_started() && call_on_exit_state)
643 {
644 p_state->on_exit_state();
645 }
646
647 p_state = ETL_NULLPTR;
648 }
649
650 //********************************************
651 ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
652 {
653 return false;
654 }
655
656 //********************************************
657 bool is_producer() const ETL_OVERRIDE
658 {
659 return true;
660 }
661
662 //********************************************
663 bool is_consumer() const ETL_OVERRIDE
664 {
665 return true;
666 }
667
668 private:
669
670 //********************************************
671 bool have_changed_state(etl::fsm_state_id_t next_state_id) const
672 {
673 return (next_state_id != p_state->get_state_id()) &&
674 (next_state_id != ifsm_state::No_State_Change) &&
675 (next_state_id != ifsm_state::Self_Transition);
676 }
677
678 //********************************************
679 bool is_self_transition(etl::fsm_state_id_t next_state_id) const
680 {
681 return (next_state_id == ifsm_state::Self_Transition);
682 }
683
684 //*******************************************
686 //*******************************************
687 virtual etl::fsm_state_id_t process_state_change(etl::fsm_state_id_t next_state_id)
688 {
689 if (is_self_transition(next_state_id))
690 {
691 p_state->on_exit_state();
692 next_state_id = p_state->on_enter_state();
693 }
694
695 if (have_changed_state(next_state_id))
696 {
697 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
698 etl::ifsm_state* p_next_state = state_list[next_state_id];
699
700 do
701 {
702 p_state->on_exit_state();
703 p_state = p_next_state;
704
705 next_state_id = p_state->on_enter_state();
706
707 if (have_changed_state(next_state_id))
708 {
709 ETL_ASSERT_OR_RETURN_VALUE(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception), p_state->get_state_id());
710 p_next_state = state_list[next_state_id];
711 }
712 } while (p_next_state != p_state); // Have we changed state again?
713 }
714
715 return p_state->get_state_id();
716 }
717
718 etl::ifsm_state* p_state;
719 etl::ifsm_state** state_list;
720 etl::fsm_state_id_t number_of_states;
721 bool is_processing_state_change;
722 };
723
724 //*************************************************************************************************
725 // For C++17 and above.
726 //*************************************************************************************************
727#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
728 //***************************************************************************
729 // The definition for all types.
730 //***************************************************************************
731 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
732 class fsm_state : public ifsm_state
733 {
734 public:
735
736 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
737
738 fsm_state()
739 : ifsm_state(STATE_ID)
740 {
741 }
742
743 protected:
744
745 ~fsm_state()
746 {
747 }
748
749 TContext& get_fsm_context() const
750 {
751 return static_cast<TContext&>(ifsm_state::get_fsm_context());
752 }
753
754 private:
755
756 //********************************************
757 struct result_t
758 {
759 bool was_handled;
760 etl::fsm_state_id_t state_id;
761 };
762
763 //********************************************
764 etl::fsm_state_id_t process_event(const etl::imessage& message)
765 {
766 etl::fsm_state_id_t new_state_id;
767
768 const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
769
770 if (!was_handled || (new_state_id == Pass_To_Parent))
771 {
772 new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
773 }
774
775 return new_state_id;
776 }
777
778 //********************************************
779 template <typename TMessage>
780 bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
781 {
782 if (TMessage::ID == msg.get_message_id())
783 {
784 new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
785 return true;
786 }
787 else
788 {
789 return false;
790 }
791 }
792 };
793
795 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
796 ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
797
798#else
799//*************************************************************************************************
800// For C++14 and below.
801//*************************************************************************************************
802 //***************************************************************************
803 // The definition for all 16 message types.
804 //***************************************************************************
805 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
806 typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
807 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
808 typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
809 typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
810 class fsm_state : public ifsm_state
811 {
812 public:
813
814 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
815
816 fsm_state()
817 : ifsm_state(STATE_ID)
818 {
819 }
820
821 protected:
822
823 ~fsm_state()
824 {
825 }
826
827 TContext& get_fsm_context() const
828 {
829 return static_cast<TContext&>(ifsm_state::get_fsm_context());
830 }
831
832 private:
833
834 etl::fsm_state_id_t process_event(const etl::imessage& message)
835 {
836 etl::fsm_state_id_t new_state_id;
837 etl::message_id_t event_id = message.get_message_id();
838
839 switch (event_id)
840 {
841 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
842 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
843 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
844 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
845 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
846 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
847 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
848 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
849 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
850 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
851 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
852 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
853 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
854 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
855 case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
856 case T16::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T16&>(message)); break;
857 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
858 }
859
860 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
861 }
862 };
863
864 //***************************************************************************
865 // Specialisation for 15 message types.
866 //***************************************************************************
867 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
868 typename T1, typename T2, typename T3, typename T4,
869 typename T5, typename T6, typename T7, typename T8,
870 typename T9, typename T10, typename T11, typename T12,
871 typename T13, typename T14, typename T15>
872 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, void> : public ifsm_state
873 {
874 public:
875
876 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
877
878 fsm_state()
879 : ifsm_state(STATE_ID)
880 {
881 }
882
883 protected:
884
885 ~fsm_state()
886 {
887 }
888
889 TContext& get_fsm_context() const
890 {
891 return static_cast<TContext&>(ifsm_state::get_fsm_context());
892 }
893
894 private:
895
896 etl::fsm_state_id_t process_event(const etl::imessage& message)
897 {
898 etl::fsm_state_id_t new_state_id;
899 etl::message_id_t event_id = message.get_message_id();
900
901 switch (event_id)
902 {
903 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
904 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
905 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
906 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
907 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
908 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
909 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
910 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
911 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
912 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
913 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
914 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
915 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
916 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
917 case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
918 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
919 }
920
921 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
922 }
923 };
924
925 //***************************************************************************
926 // Specialisation for 14 message types.
927 //***************************************************************************
928 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
929 typename T1, typename T2, typename T3, typename T4,
930 typename T5, typename T6, typename T7, typename T8,
931 typename T9, typename T10, typename T11, typename T12,
932 typename T13, typename T14>
933 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, void, void> : public ifsm_state
934 {
935 public:
936
937 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
938
939 fsm_state()
940 : ifsm_state(STATE_ID)
941 {
942 }
943
944 protected:
945
946 ~fsm_state()
947 {
948 }
949
950 TContext& get_fsm_context() const
951 {
952 return static_cast<TContext&>(ifsm_state::get_fsm_context());
953 }
954
955 private:
956
957 etl::fsm_state_id_t process_event(const etl::imessage& message)
958 {
959 etl::fsm_state_id_t new_state_id;
960 etl::message_id_t event_id = message.get_message_id();
961
962 switch (event_id)
963 {
964 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
965 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
966 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
967 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
968 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
969 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
970 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
971 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
972 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
973 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
974 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
975 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
976 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
977 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
978 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
979 }
980
981 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
982 }
983 };
984
985 //***************************************************************************
986 // Specialisation for 13 message types.
987 //***************************************************************************
988 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
989 typename T1, typename T2, typename T3, typename T4,
990 typename T5, typename T6, typename T7, typename T8,
991 typename T9, typename T10, typename T11, typename T12,
992 typename T13>
993 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, void, void, void> : public ifsm_state
994 {
995 public:
996
997 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
998
999 fsm_state()
1000 : ifsm_state(STATE_ID)
1001 {
1002 }
1003
1004 protected:
1005
1006 ~fsm_state()
1007 {
1008 }
1009
1010 TContext& get_fsm_context() const
1011 {
1012 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1013 }
1014
1015 private:
1016
1017 etl::fsm_state_id_t process_event(const etl::imessage& message)
1018 {
1019 etl::fsm_state_id_t new_state_id;
1020 etl::message_id_t event_id = message.get_message_id();
1021
1022 switch (event_id)
1023 {
1024 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1025 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1026 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1027 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1028 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1029 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1030 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1031 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1032 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1033 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
1034 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
1035 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
1036 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
1037 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1038 }
1039
1040 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1041 }
1042 };
1043
1044 //***************************************************************************
1045 // Specialisation for 12 message types.
1046 //***************************************************************************
1047 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1048 typename T1, typename T2, typename T3, typename T4,
1049 typename T5, typename T6, typename T7, typename T8,
1050 typename T9, typename T10, typename T11, typename T12>
1051 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, void, void, void, void> : public ifsm_state
1052 {
1053 public:
1054
1055 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1056
1057 fsm_state()
1058 : ifsm_state(STATE_ID)
1059 {
1060 }
1061
1062 protected:
1063
1064 ~fsm_state()
1065 {
1066 }
1067
1068 TContext& get_fsm_context() const
1069 {
1070 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1071 }
1072
1073 private:
1074
1075 etl::fsm_state_id_t process_event(const etl::imessage& message)
1076 {
1077 etl::fsm_state_id_t new_state_id;
1078 etl::message_id_t event_id = message.get_message_id();
1079
1080 switch (event_id)
1081 {
1082 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1083 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1084 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1085 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1086 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1087 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1088 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1089 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1090 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1091 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
1092 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
1093 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
1094 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1095 }
1096
1097 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1098 }
1099 };
1100
1101 //***************************************************************************
1102 // Specialisation for 11 message types.
1103 //***************************************************************************
1104 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1105 typename T1, typename T2, typename T3, typename T4,
1106 typename T5, typename T6, typename T7, typename T8,
1107 typename T9, typename T10, typename T11>
1108 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, void, void, void, void, void> : public ifsm_state
1109 {
1110 public:
1111
1112 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1113
1114 fsm_state()
1115 : ifsm_state(STATE_ID)
1116 {
1117 }
1118
1119 protected:
1120
1121 ~fsm_state()
1122 {
1123 }
1124
1125 TContext& get_fsm_context() const
1126 {
1127 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1128 }
1129
1130 private:
1131
1132 etl::fsm_state_id_t process_event(const etl::imessage& message)
1133 {
1134 etl::fsm_state_id_t new_state_id;
1135 etl::message_id_t event_id = message.get_message_id();
1136
1137 switch (event_id)
1138 {
1139 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1140 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1141 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1142 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1143 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1144 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1145 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1146 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1147 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1148 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
1149 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
1150 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1151 }
1152
1153 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1154 }
1155 };
1156
1157 //***************************************************************************
1158 // Specialisation for 10 message types.
1159 //***************************************************************************
1160 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1161 typename T1, typename T2, typename T3, typename T4,
1162 typename T5, typename T6, typename T7, typename T8,
1163 typename T9, typename T10>
1164 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, void, void, void, void, void, void> : public ifsm_state
1165 {
1166 public:
1167
1168 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1169
1170 fsm_state()
1171 : ifsm_state(STATE_ID)
1172 {
1173 }
1174
1175 protected:
1176
1177 ~fsm_state()
1178 {
1179 }
1180
1181 TContext& get_fsm_context() const
1182 {
1183 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1184 }
1185
1186 private:
1187
1188 etl::fsm_state_id_t process_event(const etl::imessage& message)
1189 {
1190 etl::fsm_state_id_t new_state_id;
1191 etl::message_id_t event_id = message.get_message_id();
1192
1193 switch (event_id)
1194 {
1195 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1196 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1197 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1198 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1199 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1200 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1201 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1202 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1203 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1204 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
1205 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1206 }
1207
1208 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1209 }
1210 };
1211
1212 //***************************************************************************
1213 // Specialisation for 9 message types.
1214 //***************************************************************************
1215 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1216 typename T1, typename T2, typename T3, typename T4,
1217 typename T5, typename T6, typename T7, typename T8,
1218 typename T9>
1219 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, void, void, void, void, void, void, void> : public ifsm_state
1220 {
1221 public:
1222
1223 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1224
1225 fsm_state()
1226 : ifsm_state(STATE_ID)
1227 {
1228 }
1229
1230 protected:
1231
1232 ~fsm_state()
1233 {
1234 }
1235
1236 TContext& get_fsm_context() const
1237 {
1238 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1239 }
1240
1241 private:
1242
1243 etl::fsm_state_id_t process_event(const etl::imessage& message)
1244 {
1245 etl::fsm_state_id_t new_state_id;
1246 etl::message_id_t event_id = message.get_message_id();
1247
1248 switch (event_id)
1249 {
1250 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1251 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1252 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1253 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1254 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1255 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1256 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1257 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1258 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1259 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1260 }
1261
1262 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1263 }
1264 };
1265
1266 //***************************************************************************
1267 // Specialisation for 8 message types.
1268 //***************************************************************************
1269 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1270 typename T1, typename T2, typename T3, typename T4,
1271 typename T5, typename T6, typename T7, typename T8>
1272 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, void, void, void, void, void, void, void, void> : public ifsm_state
1273 {
1274 public:
1275
1276 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1277
1278 fsm_state()
1279 : ifsm_state(STATE_ID)
1280 {
1281 }
1282
1283 protected:
1284
1285 ~fsm_state()
1286 {
1287 }
1288
1289 TContext& get_fsm_context() const
1290 {
1291 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1292 }
1293
1294 private:
1295
1296 etl::fsm_state_id_t process_event(const etl::imessage& message)
1297 {
1298 etl::fsm_state_id_t new_state_id;
1299 etl::message_id_t event_id = message.get_message_id();
1300
1301 switch (event_id)
1302 {
1303 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1304 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1305 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1306 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1307 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1308 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1309 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1310 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1311 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1312 }
1313
1314 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1315 }
1316 };
1317
1318 //***************************************************************************
1319 // Specialisation for 7 message types.
1320 //***************************************************************************
1321 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1322 typename T1, typename T2, typename T3, typename T4,
1323 typename T5, typename T6, typename T7>
1324 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, void, void, void, void, void, void, void, void, void> : public ifsm_state
1325 {
1326 public:
1327
1328 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1329
1330 fsm_state()
1331 : ifsm_state(STATE_ID)
1332 {
1333 }
1334
1335 protected:
1336
1337 ~fsm_state()
1338 {
1339 }
1340
1341 TContext& get_fsm_context() const
1342 {
1343 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1344 }
1345
1346 private:
1347
1348 etl::fsm_state_id_t process_event(const etl::imessage& message)
1349 {
1350 etl::fsm_state_id_t new_state_id;
1351 etl::message_id_t event_id = message.get_message_id();
1352
1353 switch (event_id)
1354 {
1355 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1356 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1357 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1358 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1359 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1360 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1361 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1362 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1363 }
1364
1365 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1366 }
1367 };
1368
1369 //***************************************************************************
1370 // Specialisation for 6 message types.
1371 //***************************************************************************
1372 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1373 typename T1, typename T2, typename T3, typename T4,
1374 typename T5, typename T6>
1375 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1376 {
1377 public:
1378
1379 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1380
1381 fsm_state()
1382 : ifsm_state(STATE_ID)
1383 {
1384 }
1385
1386 protected:
1387
1388 ~fsm_state()
1389 {
1390 }
1391
1392 TContext& get_fsm_context() const
1393 {
1394 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1395 }
1396
1397 private:
1398
1399 etl::fsm_state_id_t process_event(const etl::imessage& message)
1400 {
1401 etl::fsm_state_id_t new_state_id;
1402 etl::message_id_t event_id = message.get_message_id();
1403
1404 switch (event_id)
1405 {
1406 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1407 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1408 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1409 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1410 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1411 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1412 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1413 }
1414
1415 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1416 }
1417 };
1418
1419 //***************************************************************************
1420 // Specialisation for 5 message types.
1421 //***************************************************************************
1422 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1423 typename T1, typename T2, typename T3, typename T4,
1424 typename T5>
1425 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1426 {
1427 public:
1428
1429 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1430
1431 fsm_state()
1432 : ifsm_state(STATE_ID)
1433 {
1434 }
1435
1436 protected:
1437
1438 ~fsm_state()
1439 {
1440 }
1441
1442 TContext& get_fsm_context() const
1443 {
1444 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1445 }
1446
1447 private:
1448
1449 etl::fsm_state_id_t process_event(const etl::imessage& message)
1450 {
1451 etl::fsm_state_id_t new_state_id;
1452 etl::message_id_t event_id = message.get_message_id();
1453
1454 switch (event_id)
1455 {
1456 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1457 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1458 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1459 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1460 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1461 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1462 }
1463
1464 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1465 }
1466 };
1467
1468 //***************************************************************************
1469 // Specialisation for 4 message types.
1470 //***************************************************************************
1471 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1472 typename T1, typename T2, typename T3, typename T4>
1473 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1474 {
1475 public:
1476
1477 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1478
1479 fsm_state()
1480 : ifsm_state(STATE_ID)
1481 {
1482 }
1483
1484 protected:
1485
1486 ~fsm_state()
1487 {
1488 }
1489
1490 TContext& get_fsm_context() const
1491 {
1492 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1493 }
1494
1495 private:
1496
1497 etl::fsm_state_id_t process_event(const etl::imessage& message)
1498 {
1499 etl::fsm_state_id_t new_state_id;
1500 etl::message_id_t event_id = message.get_message_id();
1501
1502 switch (event_id)
1503 {
1504 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1505 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1506 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1507 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1508 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1509 }
1510
1511 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1512 }
1513 };
1514
1515 //***************************************************************************
1516 // Specialisation for 3 message types.
1517 //***************************************************************************
1518 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1519 typename T1, typename T2, typename T3>
1520 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1521 {
1522 public:
1523
1524 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1525
1526 fsm_state()
1527 : ifsm_state(STATE_ID)
1528 {
1529 }
1530
1531 protected:
1532
1533 ~fsm_state()
1534 {
1535 }
1536
1537 TContext& get_fsm_context() const
1538 {
1539 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1540 }
1541
1542 private:
1543
1544 etl::fsm_state_id_t process_event(const etl::imessage& message)
1545 {
1546 etl::fsm_state_id_t new_state_id;
1547 etl::message_id_t event_id = message.get_message_id();
1548
1549 switch (event_id)
1550 {
1551 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1552 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1553 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1554 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1555 }
1556
1557 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1558 }
1559 };
1560
1561 //***************************************************************************
1562 // Specialisation for 2 message types.
1563 //***************************************************************************
1564 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1565 typename T1, typename T2>
1566 class fsm_state<TContext, TDerived, STATE_ID_, T1, T2, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1567 {
1568 public:
1569
1570 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1571
1572 fsm_state()
1573 : ifsm_state(STATE_ID)
1574 {
1575 }
1576
1577 protected:
1578
1579 ~fsm_state()
1580 {
1581 }
1582
1583 TContext& get_fsm_context() const
1584 {
1585 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1586 }
1587
1588 private:
1589
1590 etl::fsm_state_id_t process_event(const etl::imessage& message)
1591 {
1592 etl::fsm_state_id_t new_state_id;
1593 etl::message_id_t event_id = message.get_message_id();
1594
1595 switch (event_id)
1596 {
1597 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1598 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1599 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1600 }
1601
1602 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1603 }
1604 };
1605
1606 //***************************************************************************
1607 // Specialisation for 1 message type.
1608 //***************************************************************************
1609 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1610 typename T1>
1611 class fsm_state<TContext, TDerived, STATE_ID_, T1, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1612 {
1613 public:
1614
1615 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1616
1617 fsm_state()
1618 : ifsm_state(STATE_ID)
1619 {
1620 }
1621
1622 protected:
1623
1624 ~fsm_state()
1625 {
1626 }
1627
1628 TContext& get_fsm_context() const
1629 {
1630 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1631 }
1632
1633 private:
1634
1635 etl::fsm_state_id_t process_event(const etl::imessage& message)
1636 {
1637 etl::fsm_state_id_t new_state_id;
1638 etl::message_id_t event_id = message.get_message_id();
1639
1640 switch (event_id)
1641 {
1642 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1643 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1644 }
1645
1646 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1647 }
1648 };
1649
1650 //***************************************************************************
1651 // Specialisation for 0 message types.
1652 //***************************************************************************
1653 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>
1654 class fsm_state<TContext, TDerived, STATE_ID_, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void> : public ifsm_state
1655 {
1656 public:
1657
1658 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1659
1660 fsm_state()
1661 : ifsm_state(STATE_ID)
1662 {
1663 }
1664
1665 protected:
1666
1667 ~fsm_state()
1668 {
1669 }
1670
1671 TContext& get_fsm_context() const
1672 {
1673 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1674 }
1675 private:
1676
1677 etl::fsm_state_id_t process_event(const etl::imessage& message)
1678 {
1679 return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
1680 }
1681 };
1682
1683 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1684 typename T1, typename T2, typename T3, typename T4,
1685 typename T5, typename T6, typename T7, typename T8,
1686 typename T9, typename T10, typename T11, typename T12,
1687 typename T13, typename T14, typename T15, typename T16>
1688 ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16>::STATE_ID;
1689#endif
1690}
1691
1692#include "private/minmax_pop.h"
1693
1694#endif
Base exception class for FSM.
Definition fsm.h:102
Exception for message received but not started.
Definition fsm.h:167
Exception for null state pointer.
Definition fsm.h:115
Exception for call to receive/start/etc. while receive/start/etc. is already happening....
Definition fsm.h:180
Exception for invalid state id.
Definition fsm.h:128
Exception for incompatible state list.
Definition fsm.h:141
Exception for incompatible order state list.
Definition fsm.h:154
Definition fsm.h:811
The FSM class.
Definition fsm.h:460
etl::fsm_state_id_t get_state_id() const
Gets the current state id.
Definition fsm.h:602
void receive(const etl::imessage &message) ETL_OVERRIDE
Top level message handler for the FSM.
Definition fsm.h:555
virtual void start(bool call_on_enter_state=true)
Definition fsm.h:523
fsm(etl::message_router_id_t id)
Constructor.
Definition fsm.h:469
virtual void reset(bool call_on_exit_state=false)
Definition fsm.h:638
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Definition fsm.h:594
etl::fsm_state_id_t transition_to(etl::fsm_state_id_t new_state_id)
Invoke a state transition.
Definition fsm.h:574
void set_states(etl::ifsm_state **p_states, TSize size)
Definition fsm.h:483
const ifsm_state & get_state() const
Gets a const reference to the current state interface.
Definition fsm.h:620
ifsm_state & get_state()
Gets a reference to the current state interface.
Definition fsm.h:611
bool is_started() const
Checks if the FSM has been started.
Definition fsm.h:629
Definition hfsm.h:42
Interface class for FSM states.
Definition fsm.h:333
void add_child_state(etl::ifsm_state &state)
Definition fsm.h:368
void set_child_states(etl::ifsm_state **state_list, TSize size)
Definition fsm.h:384
etl::fsm_state_id_t get_state_id() const
Gets the id for this state.
Definition fsm.h:359
ifsm_state(etl::fsm_state_id_t state_id_)
Constructor.
Definition fsm.h:401
virtual ~ifsm_state()
Destructor.
Definition fsm.h:413
friend class etl::fsm
Allows ifsm_state functions to be private.
Definition fsm.h:337
This is the base of all message routers.
Definition message_router_generator.h:121
Definition message.h:73
Definition message.h:91
RAII detection mechanism to catch reentrant calls to methods that might transition the state machine ...
Definition fsm.h:232
~fsm_reentrancy_guard() ETL_NOEXCEPT
Definition fsm.h:249
fsm_reentrancy_guard(bool &transition_guard_flag)
Definition fsm.h:238
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
Definition integral_limits.h:516
Defines a type that is as larger or larger than the specified type. Will return the specified type is...
Definition largest_generator.h:352
integral_constant
Definition type_traits_generator.h:895
bitset_ext
Definition absolute.h:39
uint_least8_t message_id_t
Allow alternative type for message id.
Definition message_types.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
T & get(array< T, Size > &a)
Definition array.h:1216
uint_least8_t fsm_state_id_t
Allow alternative type for state id.
Definition fsm.h:78
Definition fsm.h:217