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// python -m cogapp -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// python -m cogapp -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
64#include <stdint.h>
65
66#include "private/minmax_push.h"
67
68namespace etl
69{
70 class fsm;
71 class hfsm;
72
74#if !defined(ETL_FSM_STATE_ID_TYPE)
76#else
78#endif
79
80 // For internal FSM use.
81 typedef typename etl::larger_type<etl::message_id_t>::type fsm_internal_id_t;
82
83#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
84 template <typename, typename, etl::fsm_state_id_t, typename...>
85 class fsm_state;
86#else
87 template <typename, typename, etl::fsm_state_id_t,
88 typename, typename, typename, typename,
89 typename, typename, typename, typename,
90 typename, typename, typename, typename,
91 typename, typename, typename, typename>
92 class fsm_state;
93#endif
94
95 //***************************************************************************
97 //***************************************************************************
99 {
100 public:
101
102 fsm_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
104 {
105 }
106 };
107
108 //***************************************************************************
110 //***************************************************************************
112 {
113 public:
114
116 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:null state", ETL_FSM_FILE_ID"A"), file_name_, line_number_)
117 {
118 }
119 };
120
121 //***************************************************************************
123 //***************************************************************************
125 {
126 public:
127
129 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state id", ETL_FSM_FILE_ID"B"), file_name_, line_number_)
130 {
131 }
132 };
133
134 //***************************************************************************
136 //***************************************************************************
138 {
139 public:
140
142 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list", ETL_FSM_FILE_ID"C"), file_name_, line_number_)
143 {
144 }
145 };
146
147 //***************************************************************************
149 //***************************************************************************
151 {
152 public:
153
155 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:state list order", ETL_FSM_FILE_ID"D"), file_name_, line_number_)
156 {
157 }
158 };
159
160 //***************************************************************************
162 //***************************************************************************
164 {
165 public:
167 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:change in composite state forbidden", ETL_FSM_FILE_ID"E"), file_name_, line_number_)
168 {
169 }
170 };
171
172 //***************************************************************************
174 //***************************************************************************
176 {
177 public:
179 : etl::fsm_exception(ETL_ERROR_TEXT("fsm:not started", ETL_FSM_FILE_ID"F"), file_name_, line_number_)
180 {
181 }
182 };
183
184 namespace private_fsm
185 {
186 template <typename T = void>
188 {
189 public:
190
191 // Pass this whenever no state change is desired.
192 // The highest unsigned value of fsm_state_id_t.
193 static ETL_CONSTANT fsm_state_id_t No_State_Change = etl::integral_limits<fsm_state_id_t>::max;
194
195 // Pass this when this event also needs to be passed to the parent.
196 static ETL_CONSTANT fsm_state_id_t Pass_To_Parent = No_State_Change - 1U;
197
198 // Pass this when this event should trigger a self transition.
199 static ETL_CONSTANT fsm_state_id_t Self_Transition = No_State_Change - 2U;
200 };
201
202 template <typename T>
204
205 template <typename T>
207
208 template <typename T>
210 }
211
212 //***************************************************************************
214 //***************************************************************************
216 {
217 public:
218
220 friend class etl::fsm;
221 friend class etl::hfsm;
222
223 using private_fsm::ifsm_state_helper<>::No_State_Change;
224 using private_fsm::ifsm_state_helper<>::Pass_To_Parent;
225 using private_fsm::ifsm_state_helper<>::Self_Transition;
226
227#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
228 template <typename, typename, etl::fsm_state_id_t, typename...>
229 friend class fsm_state;
230#else
231 template <typename, typename, etl::fsm_state_id_t,
232 typename, typename, typename, typename,
233 typename, typename, typename, typename,
234 typename, typename, typename, typename,
235 typename, typename, typename, typename>
236 friend class etl::fsm_state;
237#endif
238
239 //*******************************************
241 //*******************************************
243 {
244 return state_id;
245 }
246
247 //*******************************************
250 //*******************************************
252 {
253 ETL_ASSERT(state.p_parent == ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
254 state.p_parent = this;
255
256 if (p_default_child == ETL_NULLPTR)
257 {
258 p_active_child = &state;
259 p_default_child = &state;
260 }
261 }
262
263 //*******************************************
266 //*******************************************
267 template <typename TSize>
269 {
270 p_active_child = ETL_NULLPTR;
271 p_default_child = ETL_NULLPTR;
272
273 for (TSize i = 0; i < size; ++i)
274 {
275 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
276 add_child_state(*state_list[i]);
277 }
278 }
279
280 protected:
281
282 //*******************************************
284 //*******************************************
286 : state_id(state_id_),
287 p_context(ETL_NULLPTR),
288 p_parent(ETL_NULLPTR),
289 p_active_child(ETL_NULLPTR),
290 p_default_child(ETL_NULLPTR)
291 {
292 }
293
294 //*******************************************
296 //*******************************************
297 virtual ~ifsm_state()
298 {
299 }
300
301 //*******************************************
302 etl::fsm& get_fsm_context() const
303 {
304 return *p_context;
305 }
306
307 private:
308
309 virtual fsm_state_id_t process_event(const etl::imessage& message) = 0;
310
311 virtual fsm_state_id_t on_enter_state() { return No_State_Change; } // By default, do nothing.
312 virtual void on_exit_state() {} // By default, do nothing.
313
314 //*******************************************
315 void set_fsm_context(etl::fsm& context)
316 {
317 p_context = &context;
318 }
319
320 // The state id.
321 const etl::fsm_state_id_t state_id;
322
323 // A pointer to the FSM context.
324 etl::fsm* p_context;
325
326 // A pointer to the parent.
327 ifsm_state* p_parent;
328
329 // A pointer to the active child.
330 ifsm_state* p_active_child;
331
332 // A pointer to the default active child.
333 ifsm_state* p_default_child;
334
335 // Disabled.
336 ifsm_state(const ifsm_state&);
337 ifsm_state& operator =(const ifsm_state&);
338 };
339
340 //***************************************************************************
342 //***************************************************************************
344 {
345 public:
346
347 friend class etl::hfsm;
348 using imessage_router::receive;
349
350 //*******************************************
352 //*******************************************
353 fsm(etl::message_router_id_t id)
354 : imessage_router(id)
355 , p_state(ETL_NULLPTR)
356 , state_list(ETL_NULLPTR)
357 , number_of_states(0U)
358 {
359 }
360
361 //*******************************************
363 //*******************************************
364 template <typename TSize>
366 {
367 state_list = p_states;
368 number_of_states = etl::fsm_state_id_t(size);
369
370 ETL_ASSERT(number_of_states > 0, ETL_ERROR(etl::fsm_state_list_exception));
371 ETL_ASSERT(number_of_states < ifsm_state::No_State_Change, ETL_ERROR(etl::fsm_state_list_exception));
372
373 for (etl::fsm_state_id_t i = 0; i < size; ++i)
374 {
375 ETL_ASSERT(state_list[i] != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
376 ETL_ASSERT(state_list[i]->get_state_id() == i, ETL_ERROR(etl::fsm_state_list_order_exception));
377 state_list[i]->set_fsm_context(*this);
378 }
379 }
380
381 //*******************************************
386 //*******************************************
387 virtual void start(bool call_on_enter_state = true)
388 {
389 // Can only be started once.
390 if (p_state == ETL_NULLPTR)
391 {
392 p_state = state_list[0];
393 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
394
396 {
397 etl::fsm_state_id_t next_state_id;
399
400 do
401 {
402 p_last_state = p_state;
403 next_state_id = p_state->on_enter_state();
404 if (next_state_id != ifsm_state::No_State_Change)
405 {
406 ETL_ASSERT(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
407 p_state = state_list[next_state_id];
408 }
409 } while (p_last_state != p_state);
410 }
411 }
412 }
413
414 //*******************************************
416 //*******************************************
417 void receive(const etl::imessage& message) ETL_OVERRIDE
418 {
419 if (is_started())
420 {
421 etl::fsm_state_id_t next_state_id = p_state->process_event(message);
422
423 if (have_changed_state(next_state_id))
424 {
425 ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
426 etl::ifsm_state* p_next_state = state_list[next_state_id];
427
428 do
429 {
430 p_state->on_exit_state();
431 p_state = p_next_state;
432
433 next_state_id = p_state->on_enter_state();
434
435 if (have_changed_state(next_state_id))
436 {
437 ETL_ASSERT_OR_RETURN(next_state_id < number_of_states, ETL_ERROR(etl::fsm_state_id_exception));
438 p_next_state = state_list[next_state_id];
439 }
440 } while (p_next_state != p_state); // Have we changed state again?
441 }
442 else if (is_self_transition(next_state_id))
443 {
444 p_state->on_exit_state();
445 p_state->on_enter_state();
446 }
447 }
448 else
449 {
450 ETL_ASSERT_FAIL(ETL_ERROR(etl::fsm_not_started));
451 }
452 }
453
454 using imessage_router::accepts;
455
456 //*******************************************
459 //*******************************************
460 bool accepts(etl::message_id_t) const ETL_OVERRIDE
461 {
462 return true;
463 }
464
465 //*******************************************
467 //*******************************************
469 {
470 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
471 return p_state->get_state_id();
472 }
473
474 //*******************************************
476 //*******************************************
478 {
479 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
480 return *p_state;
481 }
482
483 //*******************************************
485 //*******************************************
486 const ifsm_state& get_state() const
487 {
488 ETL_ASSERT(p_state != ETL_NULLPTR, ETL_ERROR(etl::fsm_null_state_exception));
489 return *p_state;
490 }
491
492 //*******************************************
494 //*******************************************
495 bool is_started() const
496 {
497 return p_state != ETL_NULLPTR;
498 }
499
500 //*******************************************
503 //*******************************************
504 virtual void reset(bool call_on_exit_state = false)
505 {
506 if ((p_state != ETL_NULLPTR) && call_on_exit_state)
507 {
508 p_state->on_exit_state();
509 }
510
511 p_state = ETL_NULLPTR;
512 }
513
514 //********************************************
515 ETL_DEPRECATED bool is_null_router() const ETL_OVERRIDE
516 {
517 return false;
518 }
519
520 //********************************************
521 bool is_producer() const ETL_OVERRIDE
522 {
523 return true;
524 }
525
526 //********************************************
527 bool is_consumer() const ETL_OVERRIDE
528 {
529 return true;
530 }
531
532 private:
533
534 //********************************************
535 bool have_changed_state(etl::fsm_state_id_t next_state_id) const
536 {
537 return (next_state_id != p_state->get_state_id()) &&
538 (next_state_id != ifsm_state::No_State_Change) &&
539 (next_state_id != ifsm_state::Self_Transition);
540 }
541
542 //********************************************
543 bool is_self_transition(etl::fsm_state_id_t next_state_id) const
544 {
545 return (next_state_id == ifsm_state::Self_Transition);
546 }
547
548 etl::ifsm_state* p_state;
549 etl::ifsm_state** state_list;
550 etl::fsm_state_id_t number_of_states;
551 };
552
553 //*************************************************************************************************
554 // For C++17 and above.
555 //*************************************************************************************************
556#if ETL_USING_CPP17 && !defined(ETL_FSM_FORCE_CPP03_IMPLEMENTATION) // For C++17 and above
557 //***************************************************************************
558 // The definition for all types.
559 //***************************************************************************
560 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
561 class fsm_state : public ifsm_state
562 {
563 public:
564
565 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
566
567 fsm_state()
568 : ifsm_state(STATE_ID)
569 {
570 }
571
572 protected:
573
574 ~fsm_state()
575 {
576 }
577
578 TContext& get_fsm_context() const
579 {
580 return static_cast<TContext&>(ifsm_state::get_fsm_context());
581 }
582
583 private:
584
585 //********************************************
586 struct result_t
587 {
588 bool was_handled;
589 etl::fsm_state_id_t state_id;
590 };
591
592 //********************************************
593 etl::fsm_state_id_t process_event(const etl::imessage& message)
594 {
595 etl::fsm_state_id_t new_state_id;
596
597 const bool was_handled = (process_event_type<TMessageTypes>(message, new_state_id) || ...);
598
599 if (!was_handled || (new_state_id == Pass_To_Parent))
600 {
601 new_state_id = (p_parent != nullptr) ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
602 }
603
604 return new_state_id;
605 }
606
607 //********************************************
608 template <typename TMessage>
609 bool process_event_type(const etl::imessage& msg, etl::fsm_state_id_t& new_state_id)
610 {
611 if (TMessage::ID == msg.get_message_id())
612 {
613 new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const TMessage&>(msg));
614 return true;
615 }
616 else
617 {
618 return false;
619 }
620 }
621 };
622
624 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_, typename... TMessageTypes>
625 ETL_CONSTANT etl::fsm_state_id_t fsm_state<TContext, TDerived, STATE_ID_, TMessageTypes...>::STATE_ID;
626
627#else
628//*************************************************************************************************
629// For C++14 and below.
630//*************************************************************************************************
631 //***************************************************************************
632 // The definition for all 16 message types.
633 //***************************************************************************
634 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
635 typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
636 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void,
637 typename T9 = void, typename T10 = void, typename T11 = void, typename T12 = void,
638 typename T13 = void, typename T14 = void, typename T15 = void, typename T16 = void>
639 class fsm_state : public ifsm_state
640 {
641 public:
642
643 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
644
645 fsm_state()
646 : ifsm_state(STATE_ID)
647 {
648 }
649
650 protected:
651
652 ~fsm_state()
653 {
654 }
655
656 TContext& get_fsm_context() const
657 {
658 return static_cast<TContext&>(ifsm_state::get_fsm_context());
659 }
660
661 private:
662
663 etl::fsm_state_id_t process_event(const etl::imessage& message)
664 {
666 etl::message_id_t event_id = message.get_message_id();
667
668 switch (event_id)
669 {
670 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
671 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
672 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
673 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
674 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
675 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
676 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
677 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
678 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
679 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
680 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
681 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
682 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
683 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
684 case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
685 case T16::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T16&>(message)); break;
686 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
687 }
688
689 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
690 }
691 };
692
693 //***************************************************************************
694 // Specialisation for 15 message types.
695 //***************************************************************************
696 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
697 typename T1, typename T2, typename T3, typename T4,
698 typename T5, typename T6, typename T7, typename T8,
699 typename T9, typename T10, typename T11, typename T12,
700 typename T13, typename T14, typename T15>
702 {
703 public:
704
705 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
706
707 fsm_state()
708 : ifsm_state(STATE_ID)
709 {
710 }
711
712 protected:
713
714 ~fsm_state()
715 {
716 }
717
718 TContext& get_fsm_context() const
719 {
720 return static_cast<TContext&>(ifsm_state::get_fsm_context());
721 }
722
723 private:
724
725 etl::fsm_state_id_t process_event(const etl::imessage& message)
726 {
728 etl::message_id_t event_id = message.get_message_id();
729
730 switch (event_id)
731 {
732 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
733 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
734 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
735 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
736 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
737 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
738 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
739 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
740 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
741 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
742 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
743 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
744 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
745 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
746 case T15::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T15&>(message)); break;
747 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
748 }
749
750 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
751 }
752 };
753
754 //***************************************************************************
755 // Specialisation for 14 message types.
756 //***************************************************************************
757 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
758 typename T1, typename T2, typename T3, typename T4,
759 typename T5, typename T6, typename T7, typename T8,
760 typename T9, typename T10, typename T11, typename T12,
761 typename T13, typename T14>
763 {
764 public:
765
766 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
767
768 fsm_state()
769 : ifsm_state(STATE_ID)
770 {
771 }
772
773 protected:
774
775 ~fsm_state()
776 {
777 }
778
779 TContext& get_fsm_context() const
780 {
781 return static_cast<TContext&>(ifsm_state::get_fsm_context());
782 }
783
784 private:
785
786 etl::fsm_state_id_t process_event(const etl::imessage& message)
787 {
789 etl::message_id_t event_id = message.get_message_id();
790
791 switch (event_id)
792 {
793 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
794 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
795 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
796 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
797 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
798 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
799 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
800 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
801 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
802 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
803 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
804 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
805 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
806 case T14::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T14&>(message)); break;
807 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
808 }
809
810 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
811 }
812 };
813
814 //***************************************************************************
815 // Specialisation for 13 message types.
816 //***************************************************************************
817 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
818 typename T1, typename T2, typename T3, typename T4,
819 typename T5, typename T6, typename T7, typename T8,
820 typename T9, typename T10, typename T11, typename T12,
821 typename T13>
823 {
824 public:
825
826 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
827
828 fsm_state()
829 : ifsm_state(STATE_ID)
830 {
831 }
832
833 protected:
834
835 ~fsm_state()
836 {
837 }
838
839 TContext& get_fsm_context() const
840 {
841 return static_cast<TContext&>(ifsm_state::get_fsm_context());
842 }
843
844 private:
845
846 etl::fsm_state_id_t process_event(const etl::imessage& message)
847 {
849 etl::message_id_t event_id = message.get_message_id();
850
851 switch (event_id)
852 {
853 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
854 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
855 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
856 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
857 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
858 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
859 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
860 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
861 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
862 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
863 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
864 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
865 case T13::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T13&>(message)); break;
866 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
867 }
868
869 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
870 }
871 };
872
873 //***************************************************************************
874 // Specialisation for 12 message types.
875 //***************************************************************************
876 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
877 typename T1, typename T2, typename T3, typename T4,
878 typename T5, typename T6, typename T7, typename T8,
879 typename T9, typename T10, typename T11, typename T12>
881 {
882 public:
883
884 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
885
886 fsm_state()
887 : ifsm_state(STATE_ID)
888 {
889 }
890
891 protected:
892
893 ~fsm_state()
894 {
895 }
896
897 TContext& get_fsm_context() const
898 {
899 return static_cast<TContext&>(ifsm_state::get_fsm_context());
900 }
901
902 private:
903
904 etl::fsm_state_id_t process_event(const etl::imessage& message)
905 {
907 etl::message_id_t event_id = message.get_message_id();
908
909 switch (event_id)
910 {
911 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
912 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
913 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
914 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
915 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
916 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
917 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
918 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
919 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
920 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
921 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
922 case T12::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T12&>(message)); break;
923 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
924 }
925
926 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
927 }
928 };
929
930 //***************************************************************************
931 // Specialisation for 11 message types.
932 //***************************************************************************
933 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
934 typename T1, typename T2, typename T3, typename T4,
935 typename T5, typename T6, typename T7, typename T8,
936 typename T9, typename T10, typename T11>
938 {
939 public:
940
941 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
942
943 fsm_state()
944 : ifsm_state(STATE_ID)
945 {
946 }
947
948 protected:
949
950 ~fsm_state()
951 {
952 }
953
954 TContext& get_fsm_context() const
955 {
956 return static_cast<TContext&>(ifsm_state::get_fsm_context());
957 }
958
959 private:
960
961 etl::fsm_state_id_t process_event(const etl::imessage& message)
962 {
964 etl::message_id_t event_id = message.get_message_id();
965
966 switch (event_id)
967 {
968 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
969 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
970 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
971 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
972 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
973 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
974 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
975 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
976 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
977 case T10::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T10&>(message)); break;
978 case T11::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T11&>(message)); break;
979 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
980 }
981
982 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
983 }
984 };
985
986 //***************************************************************************
987 // Specialisation for 10 message types.
988 //***************************************************************************
989 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
990 typename T1, typename T2, typename T3, typename T4,
991 typename T5, typename T6, typename T7, typename T8,
992 typename T9, typename T10>
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 {
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 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1035 }
1036
1037 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1038 }
1039 };
1040
1041 //***************************************************************************
1042 // Specialisation for 9 message types.
1043 //***************************************************************************
1044 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1045 typename T1, typename T2, typename T3, typename T4,
1046 typename T5, typename T6, typename T7, typename T8,
1047 typename T9>
1049 {
1050 public:
1051
1052 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1053
1054 fsm_state()
1055 : ifsm_state(STATE_ID)
1056 {
1057 }
1058
1059 protected:
1060
1061 ~fsm_state()
1062 {
1063 }
1064
1065 TContext& get_fsm_context() const
1066 {
1067 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1068 }
1069
1070 private:
1071
1072 etl::fsm_state_id_t process_event(const etl::imessage& message)
1073 {
1075 etl::message_id_t event_id = message.get_message_id();
1076
1077 switch (event_id)
1078 {
1079 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1080 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1081 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1082 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1083 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1084 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1085 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1086 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1087 case T9::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T9&>(message)); break;
1088 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1089 }
1090
1091 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1092 }
1093 };
1094
1095 //***************************************************************************
1096 // Specialisation for 8 message types.
1097 //***************************************************************************
1098 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1099 typename T1, typename T2, typename T3, typename T4,
1100 typename T5, typename T6, typename T7, typename T8>
1102 {
1103 public:
1104
1105 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1106
1107 fsm_state()
1108 : ifsm_state(STATE_ID)
1109 {
1110 }
1111
1112 protected:
1113
1114 ~fsm_state()
1115 {
1116 }
1117
1118 TContext& get_fsm_context() const
1119 {
1120 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1121 }
1122
1123 private:
1124
1125 etl::fsm_state_id_t process_event(const etl::imessage& message)
1126 {
1128 etl::message_id_t event_id = message.get_message_id();
1129
1130 switch (event_id)
1131 {
1132 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1133 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1134 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1135 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1136 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1137 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1138 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1139 case T8::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T8&>(message)); break;
1140 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1141 }
1142
1143 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1144 }
1145 };
1146
1147 //***************************************************************************
1148 // Specialisation for 7 message types.
1149 //***************************************************************************
1150 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1151 typename T1, typename T2, typename T3, typename T4,
1152 typename T5, typename T6, typename T7>
1154 {
1155 public:
1156
1157 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1158
1159 fsm_state()
1160 : ifsm_state(STATE_ID)
1161 {
1162 }
1163
1164 protected:
1165
1166 ~fsm_state()
1167 {
1168 }
1169
1170 TContext& get_fsm_context() const
1171 {
1172 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1173 }
1174
1175 private:
1176
1177 etl::fsm_state_id_t process_event(const etl::imessage& message)
1178 {
1180 etl::message_id_t event_id = message.get_message_id();
1181
1182 switch (event_id)
1183 {
1184 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1185 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1186 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1187 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1188 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1189 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1190 case T7::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T7&>(message)); break;
1191 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1192 }
1193
1194 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1195 }
1196 };
1197
1198 //***************************************************************************
1199 // Specialisation for 6 message types.
1200 //***************************************************************************
1201 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1202 typename T1, typename T2, typename T3, typename T4,
1203 typename T5, typename T6>
1205 {
1206 public:
1207
1208 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1209
1210 fsm_state()
1211 : ifsm_state(STATE_ID)
1212 {
1213 }
1214
1215 protected:
1216
1217 ~fsm_state()
1218 {
1219 }
1220
1221 TContext& get_fsm_context() const
1222 {
1223 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1224 }
1225
1226 private:
1227
1228 etl::fsm_state_id_t process_event(const etl::imessage& message)
1229 {
1231 etl::message_id_t event_id = message.get_message_id();
1232
1233 switch (event_id)
1234 {
1235 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1236 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1237 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1238 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1239 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1240 case T6::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T6&>(message)); break;
1241 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1242 }
1243
1244 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1245 }
1246 };
1247
1248 //***************************************************************************
1249 // Specialisation for 5 message types.
1250 //***************************************************************************
1251 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1252 typename T1, typename T2, typename T3, typename T4,
1253 typename T5>
1255 {
1256 public:
1257
1258 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1259
1260 fsm_state()
1261 : ifsm_state(STATE_ID)
1262 {
1263 }
1264
1265 protected:
1266
1267 ~fsm_state()
1268 {
1269 }
1270
1271 TContext& get_fsm_context() const
1272 {
1273 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1274 }
1275
1276 private:
1277
1278 etl::fsm_state_id_t process_event(const etl::imessage& message)
1279 {
1281 etl::message_id_t event_id = message.get_message_id();
1282
1283 switch (event_id)
1284 {
1285 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1286 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1287 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1288 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1289 case T5::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T5&>(message)); break;
1290 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1291 }
1292
1293 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1294 }
1295 };
1296
1297 //***************************************************************************
1298 // Specialisation for 4 message types.
1299 //***************************************************************************
1300 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1301 typename T1, typename T2, typename T3, typename T4>
1303 {
1304 public:
1305
1306 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1307
1308 fsm_state()
1309 : ifsm_state(STATE_ID)
1310 {
1311 }
1312
1313 protected:
1314
1315 ~fsm_state()
1316 {
1317 }
1318
1319 TContext& get_fsm_context() const
1320 {
1321 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1322 }
1323
1324 private:
1325
1326 etl::fsm_state_id_t process_event(const etl::imessage& message)
1327 {
1329 etl::message_id_t event_id = message.get_message_id();
1330
1331 switch (event_id)
1332 {
1333 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1334 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1335 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1336 case T4::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T4&>(message)); break;
1337 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1338 }
1339
1340 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1341 }
1342 };
1343
1344 //***************************************************************************
1345 // Specialisation for 3 message types.
1346 //***************************************************************************
1347 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1348 typename T1, typename T2, typename T3>
1350 {
1351 public:
1352
1353 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1354
1355 fsm_state()
1356 : ifsm_state(STATE_ID)
1357 {
1358 }
1359
1360 protected:
1361
1362 ~fsm_state()
1363 {
1364 }
1365
1366 TContext& get_fsm_context() const
1367 {
1368 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1369 }
1370
1371 private:
1372
1373 etl::fsm_state_id_t process_event(const etl::imessage& message)
1374 {
1376 etl::message_id_t event_id = message.get_message_id();
1377
1378 switch (event_id)
1379 {
1380 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1381 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1382 case T3::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T3&>(message)); break;
1383 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1384 }
1385
1386 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1387 }
1388 };
1389
1390 //***************************************************************************
1391 // Specialisation for 2 message types.
1392 //***************************************************************************
1393 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1394 typename T1, typename T2>
1396 {
1397 public:
1398
1399 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1400
1401 fsm_state()
1402 : ifsm_state(STATE_ID)
1403 {
1404 }
1405
1406 protected:
1407
1408 ~fsm_state()
1409 {
1410 }
1411
1412 TContext& get_fsm_context() const
1413 {
1414 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1415 }
1416
1417 private:
1418
1419 etl::fsm_state_id_t process_event(const etl::imessage& message)
1420 {
1422 etl::message_id_t event_id = message.get_message_id();
1423
1424 switch (event_id)
1425 {
1426 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1427 case T2::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T2&>(message)); break;
1428 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1429 }
1430
1431 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1432 }
1433 };
1434
1435 //***************************************************************************
1436 // Specialisation for 1 message type.
1437 //***************************************************************************
1438 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1439 typename T1>
1441 {
1442 public:
1443
1444 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1445
1446 fsm_state()
1447 : ifsm_state(STATE_ID)
1448 {
1449 }
1450
1451 protected:
1452
1453 ~fsm_state()
1454 {
1455 }
1456
1457 TContext& get_fsm_context() const
1458 {
1459 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1460 }
1461
1462 private:
1463
1464 etl::fsm_state_id_t process_event(const etl::imessage& message)
1465 {
1467 etl::message_id_t event_id = message.get_message_id();
1468
1469 switch (event_id)
1470 {
1471 case T1::ID: new_state_id = static_cast<TDerived*>(this)->on_event(static_cast<const T1&>(message)); break;
1472 default: new_state_id = p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message); break;
1473 }
1474
1475 return (new_state_id != Pass_To_Parent) ? new_state_id : (p_parent ? p_parent->process_event(message) : No_State_Change);
1476 }
1477 };
1478
1479 //***************************************************************************
1480 // Specialisation for 0 message types.
1481 //***************************************************************************
1482 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_>
1484 {
1485 public:
1486
1487 static ETL_CONSTANT etl::fsm_state_id_t STATE_ID = STATE_ID_;
1488
1489 fsm_state()
1490 : ifsm_state(STATE_ID)
1491 {
1492 }
1493
1494 protected:
1495
1496 ~fsm_state()
1497 {
1498 }
1499
1500 TContext& get_fsm_context() const
1501 {
1502 return static_cast<TContext&>(ifsm_state::get_fsm_context());
1503 }
1504 private:
1505
1506 etl::fsm_state_id_t process_event(const etl::imessage& message)
1507 {
1508 return p_parent ? p_parent->process_event(message) : static_cast<TDerived*>(this)->on_event_unknown(message);
1509 }
1510 };
1511
1512 template <typename TContext, typename TDerived, etl::fsm_state_id_t STATE_ID_,
1513 typename T1, typename T2, typename T3, typename T4,
1514 typename T5, typename T6, typename T7, typename T8,
1515 typename T9, typename T10, typename T11, typename T12,
1516 typename T13, typename T14, typename T15, typename T16>
1518#endif
1519}
1520
1521#include "private/minmax_pop.h"
1522
1523#endif
Base exception class for FSM.
Definition fsm.h:99
Exception for message received but not started.
Definition fsm.h:176
Exception for null state pointer.
Definition fsm.h:112
Exception for forbidden state changes.
Definition fsm.h:164
Exception for invalid state id.
Definition fsm.h:125
Exception for incompatible state list.
Definition fsm.h:138
Exception for incompatible order state list.
Definition fsm.h:151
Definition fsm.h:640
The FSM class.
Definition fsm.h:344
etl::fsm_state_id_t get_state_id() const
Gets the current state id.
Definition fsm.h:468
void receive(const etl::imessage &message) ETL_OVERRIDE
Top level message handler for the FSM.
Definition fsm.h:417
virtual void start(bool call_on_enter_state=true)
Definition fsm.h:387
fsm(etl::message_router_id_t id)
Constructor.
Definition fsm.h:353
virtual void reset(bool call_on_exit_state=false)
Definition fsm.h:504
bool accepts(etl::message_id_t) const ETL_OVERRIDE
Definition fsm.h:460
void set_states(etl::ifsm_state **p_states, TSize size)
Set the states for the FSM.
Definition fsm.h:365
const ifsm_state & get_state() const
Gets a const reference to the current state interface.
Definition fsm.h:486
ifsm_state & get_state()
Gets a reference to the current state interface.
Definition fsm.h:477
bool is_started() const
Checks if the FSM has been started.
Definition fsm.h:495
Definition hfsm.h:42
Interface class for FSM states.
Definition fsm.h:216
void add_child_state(etl::ifsm_state &state)
Definition fsm.h:251
void set_child_states(etl::ifsm_state **state_list, TSize size)
Definition fsm.h:268
etl::fsm_state_id_t get_state_id() const
Gets the id for this state.
Definition fsm.h:242
ifsm_state(etl::fsm_state_id_t state_id_)
Constructor.
Definition fsm.h:285
virtual ~ifsm_state()
Destructor.
Definition fsm.h:297
This is the base of all message routers.
Definition message_router_generator.h:121
Definition message.h:73
Definition message.h:91
#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
bitset_ext
Definition absolute.h:38
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
uint_least8_t fsm_state_id_t
Allow alternative type for state id.
Definition fsm.h:75
pair holds two objects of arbitrary type
Definition utility.h:164