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