#include "core/config.h"
#if CONFIG_AUTOMAT_MODE && ( CONFIG_KEYSW || CONFIG_NFMBASECLASS )
#include <stdint.h>
#include <intrinsics.h>
#include <stdlib.h>

#include "core/csect.h"
#include "app/rseq/rseq.h"
#include "app/automat/automat.h"
#include "core/debugpins.h"
#if CONFIG_EXTMEM
#include "drivers/flash/base/extmem_flash.h"
#endif
#if CONFIG_NFMBASECLASS
#include "app/nfm/nfm_base.h"
#elif CONFIG_KEYSW
#include "drivers/keycontrol/keycontrol.h" // KEYCONTROL_STATE_LDASHALL, KEYCONTROL_STATE_LDBSHALL, KEYCONTROL_STATE_DEFAULT, KeySwitchHandle
#endif


#if CONFIG_NFMBASECLASS
//
#define PROTO_KEYSTATE_ARRAY        { eKeyState_SALL,\
                                      eKeyState_OALL,\
                                      eKeyState_LALL, }

#elif CONFIG_KEYSW
// SC3v4_UPC2163
#define PROTO_KEYSTATE_ARRAY_LEGACY { KEYCONTROL_STATE_SHORTALL,\
                                      KEYCONTROL_STATE_OPENALL,\
                                      KEYCONTROL_STATE_LOADALL, }
#elif
#error Please, define either CONFIG_NFMBASECLASS or CONFIG_KEYSW.
#endif

//---------------------------------------------------

#define DEBUG_PIN                        CONFIG_AUTOMAT_DEBUGPIN_1 // Debug pin: proto data output
#define DEBUG_PIN_2                      CONFIG_AUTOMAT_DEBUGPIN_2 // Debug pin: proto data output
#define DEBUG_PIN_3                      CONFIG_AUTOMAT_DEBUGPIN_3 // Debug pin
#define KEY_STATE_DEBUG                  0              // Debug pin: key state data output
#define DEBUG_AUTOMAT_DATA               0              // Demo 'automat' data
#define DEBUG_AUTOMAT_DATA_WRITE         0              // Save demo 'automat' data into flash
#define T_INTERVAL_MUL                   1              // Elementary proto-time-slot, <T>. (Interval=<T>*3)
#define DATAROM_BLOCK_ADDR               0x17FFFC       // было 0x17FFFC, потом 0x07FFFC, потом исправил снова на 0x17FFFC
#define DATAROM_SERIAL_ADDR              0x000040
#define DATAROM_SIGNATURE                0x55
#define PROTO_LOGIC_0_KEYSTATE_LEGACY    KEYCONTROL_STATE_LDASHALL
#define PROTO_LOGIC_1_KEYSTATE_LEGACY    KEYCONTROL_STATE_LDBSHALL
#define PROTO_LOGIC_0_KEYSTATE           eKeyState_LASR
#define PROTO_LOGIC_1_KEYSTATE           eKeyState_LBSR

#define NO_LOCKERS                       1              // do not use lockers due to all job is in IRQ
//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================
//==============================================================================
#if DEBUG_PIN && CONFIG_AUTOMAT_DEBUGPIN_1

    #define DEBUG_INIT_PIN
    #define DEBUG_SET_PIN    CONFIG_AUTOMAT_DEBUGPIN_SETPIN_1
    #define DEBUG_CLR_PIN    CONFIG_AUTOMAT_DEBUGPIN_CLRPIN_1
  #else
    #define DEBUG_INIT_PIN
    #define DEBUG_SET_PIN
    #define DEBUG_CLR_PIN
#endif

#if DEBUG_PIN_2 && CONFIG_AUTOMAT_DEBUGPIN_2
    #define DEBUG_INIT_PIN2
    #define DEBUG_SET_PIN2   CONFIG_AUTOMAT_DEBUGPIN_SETPIN_2
    #define DEBUG_CLR_PIN2   CONFIG_AUTOMAT_DEBUGPIN_CLRPIN_2
  #else
    #define DEBUG_INIT_PIN2
    #define DEBUG_SET_PIN2
    #define DEBUG_CLR_PIN2
#endif


#if DEBUG_PIN_3 && CONFIG_AUTOMAT_DEBUGPIN_3
    #define DEBUG_INIT_PIN3
    #define DEBUG_SET_PIN3   CONFIG_AUTOMAT_DEBUGPIN_SETPIN_3
    #define DEBUG_CLR_PIN3   CONFIG_AUTOMAT_DEBUGPIN_CLRPIN_3
  #else
    #define DEBUG_INIT_PIN3
    #define DEBUG_SET_PIN3
    #define DEBUG_CLR_PIN3
#endif
//------------------------------------------------------------------------------------------
static bool automat_event_startup( uint32_t ticks_per_1ms );
static void automat_ievent_tick();
static void automat_temperature_update( int8_t avgtemp_degree, bool isValueReady );
static void automat_event_shutdown();

const sNFMAutomatHandle_t NFMAutomatHandle = {

   .Init = automat_event_startup,
   .Tick = automat_ievent_tick,
   .TemperatureUpdate = automat_temperature_update,
   .DeInit = automat_event_shutdown,
};

//------------------------------------------------------------------------------------------

static bool sleep = false;
static bool state = false;
static volatile bool initialized = false;
// -----------
#pragma pack(push,1)
typedef union
{
   struct
   {
      uint8_t  data[3];
   };

   struct
   {
      uint8_t  signature;
      uint16_t interval;
      uint8_t  checksumm;
   };
}
sHeader_t;
#pragma pack(pop)
// -----------
#pragma pack(push,1)
typedef union
{
     char rawBytes[9];
     struct
     {
        char rawSerialTruncated[8];
        char rawSerialNullchr;
     };
}
sSerial_t;
#pragma pack(pop)
// -----------
#pragma pack(push, 1)
typedef struct
{
   struct
   {
      uint32_t gp_timer_counter;
      uint32_t gp_timer_maximum;
   }
   counters;

   struct
   {
      bool     avgTempReady;
      uint8_t  avgTempDegree;
      uint8_t  ticks_per_1ms;
   }
   extData;

   #if CONFIG_NFMBASECLASS
   struct
   {
      int32_t  shortcutIdState0;
      int32_t  shortcutIdState1;
   }
   keyStates;
   #endif

   union
   {
      struct
      {
        uint32_t serial;
        uint16_t interval;
        uint8_t  temp;
        uint8_t  checksumm;
      };

      struct
      {
        uint8_t  checksummBytes[7];
        uint8_t  checksumm;
      }
      raw;

      uint8_t txBytes[1];   // per-byte access
   }
   locData;

   struct
   {
      uint8_t  idx;
      uint8_t  len;
      uint8_t  bit;
   }
   protoControl;

   union
   {
      sHeader_t rawHeader;
      sSerial_t rawSerial;
   }
   uTempStorage;
}
sData_t;
#pragma pack(pop)
// -----------
#if CONFIG_NFMBASECLASS
static const eNFMKeyState_t automatKeyStates[] = PROTO_KEYSTATE_ARRAY;
#elif CONFIG_KEYSW
static const uint32_t automatKeyStatesLegacy[] = PROTO_KEYSTATE_ARRAY_LEGACY;
#endif
// -----------
static fRoutine_t *       rseq_task_list[ 8 ];
static fRoutine_t *       rseq_timer_list[ 2 ];
static sRoutineSequence_t rseq_timer;
static sRoutineSequence_t rseq_task;
static sData_t            g_sData;
// -----------
bool seqirq_state_wait_enum( void * arg );
bool seqirq_state_enum_timeout( void * arg );
bool seqirq_state_timer_nextstate( void * arg );
bool seqirq_state_timer_prevstate( void * arg );

bool seq_state_initstart( void * arg );
bool seq_state_start( void * arg );
bool seq_state_transmit_0( void * arg );
bool seq_state_wait( void * arg );
bool seq_state_transmit_1( void * arg );
bool seq_state_transmit_next( void * arg );
bool seq_state_keycontol_init( void * arg );
bool seq_state_keycontol_next( void * arg );

bool check_header( void * arg );
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
static inline void dataLineAssertLogic0()
{
  DEBUG_CLR_PIN;
  #if CONFIG_NFMBASECLASS
  NFMClass->methods.keyStatesMethods.shortcuts.setKeyStateByShortcut( g_sData.keyStates.shortcutIdState0 );
  #elif CONFIG_KEYSW
  KeySwitchHandle.SetKeyState( PROTO_LOGIC_0_KEYSTATE_LEGACY );
  #endif
}

static inline void dataLineAssertLogic1()
{
  DEBUG_SET_PIN;
  #if CONFIG_NFMBASECLASS
  NFMClass->methods.keyStatesMethods.shortcuts.setKeyStateByShortcut( g_sData.keyStates.shortcutIdState1 );
  #elif CONFIG_KEYSW
  KeySwitchHandle.SetKeyState( PROTO_LOGIC_1_KEYSTATE_LEGACY );
  #endif
}

static inline void dataLineAssertLogic(bool state)
{
  if( state )
   dataLineAssertLogic1();
  else
   dataLineAssertLogic0();
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
#if NO_LOCKERS == 0
static inline bool seqTake( void * arg )
{
   DI();
   return true;
}

static inline bool seqFree( void * arg )
{
   EI();
   return true;
}
#endif
static inline bool getTxLineBitValue( const uint8_t * pDataArray, int32_t idx )
{
   return ( pDataArray[ idx/8 ] & (1 << idx%8) );
}

static uint8_t getChecksumm( const uint8_t * pDataArray, uint32_t len )
{
    uint16_t checksumm16 = 0;
    for( int idx = 0; idx < len; ++idx )
    {
         checksumm16 += pDataArray[idx];
         checksumm16 = (checksumm16 >> 8) + ((uint8_t)checksumm16);
    }
    return (uint8_t)checksumm16;
}

static bool automat_event_startup( uint32_t ticks_per_1ms )
{
   bool result = false;

   __DI__

   rsa_sequence_init( &rseq_task,   &g_sData, rseq_task_list, sizeof(rseq_task_list)/sizeof(*rseq_task_list) );
   rsa_sequence_init( &rseq_timer,  &g_sData, rseq_timer_list, sizeof(rseq_timer_list)/sizeof(*rseq_timer_list) );

   #if NO_LOCKERS == 0
   rsa_sequence_setlockers( &rseq_timer, seqTake, seqFree );
   rsa_sequence_setlockers( &rseq_task, seqTake, seqFree );
   #endif

   g_sData.extData.avgTempDegree = 0;
   g_sData.extData.avgTempReady = false;
   g_sData.extData.ticks_per_1ms = ticks_per_1ms;
   g_sData.locData.checksumm = 0;
   g_sData.locData.interval = 0;
   g_sData.locData.serial = 0;
   g_sData.locData.temp = 0;
   g_sData.protoControl.bit = 0;
   g_sData.protoControl.idx = 0;
   g_sData.protoControl.len = 0;

   #if CONFIG_NFMBASECLASS
   g_sData.keyStates.shortcutIdState0 = -1;
   g_sData.keyStates.shortcutIdState1 = -1;

   // Initialize shortcuts for fast switching
   int32_t shortcutState0 = -1,  shortcutState1 = -1;

   NFMClass->methods.keyStatesMethods.shortcuts.findShortCutForState( PROTO_LOGIC_0_KEYSTATE, &shortcutState0 );
   NFMClass->methods.keyStatesMethods.shortcuts.findShortCutForState( PROTO_LOGIC_1_KEYSTATE, &shortcutState1 );

   g_sData.keyStates.shortcutIdState0 = shortcutState0;
   g_sData.keyStates.shortcutIdState1 = shortcutState1;
   #endif

   rsa_sequence_clear( &rseq_task );

   if( check_header( &g_sData ) )
   {
       rsa_sequence_insert_routine( &rseq_task, seq_state_initstart );

       result = true;
   }

   sleep = false; // disallow to sleep
   state = false; // current automat state = still disabled(false)
   initialized = true;

   __EI__

   DEBUG_INIT_PIN;
   DEBUG_INIT_PIN2;

   return result;
}

static void automat_event_shutdown()
{
   __DI__

   if( initialized )
   {
       rsa_sequence_iclear( &rseq_task );
       rsa_sequence_iclear( &rseq_timer );

       sleep = false; // disallow to sleep
       state = false; // current automat state = still disabled(false)

       initialized = false;
   }

   __EI__
}

static void automat_ievent_tick()
{
   if( ! initialized ) return;

   if( rsa_sequence_icall( &rseq_timer ) )
   {
       rsa_sequence_ireset( &rseq_timer );
   }

   if( rsa_sequence_icall( &rseq_task ) )
   {
       rsa_sequence_ireset( &rseq_task );
   }
}

static void automat_temperature_update( int8_t avgtemp_degree, bool isValueReady )
{
   if( ! initialized ) return;

   if( state )
   {
       __DI__ g_sData.extData.avgTempDegree = avgtemp_degree;
              g_sData.extData.avgTempReady = isValueReady; __EI__
   }
}

// check_header
static bool check_header( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   bool dataLoaded = false;

   {
       pData->uTempStorage.rawHeader.signature = ~DATAROM_SIGNATURE;

    #if DEBUG_AUTOMAT_DATA == 0
       #if CONFIG_EXTMEM
       if( !ExtMemHandle.Read( DATAROM_BLOCK_ADDR,
                   (__FLASH_BYTE*)&pData->uTempStorage.rawHeader,
                    sizeof(pData->uTempStorage.rawHeader)) )
       {
           pData->uTempStorage.rawHeader.signature = ~DATAROM_SIGNATURE;
       }
       #endif
    #else
        pData->uTempStorage.rawHeader.signature = DATAROM_SIGNATURE;
        pData->uTempStorage.rawHeader.interval  = 1000;
        pData->uTempStorage.rawHeader.checksumm = 0x41;

        #if CONFIG_EXTMEM
        #if DEBUG_AUTOMAT_DATA_WRITE == 1
            ExtMemHandle.Write( DATAROM_BLOCK_ADDR,
                        (__FLASH_BYTE*)&pData->uTempStorage.rawHeader,
                        sizeof(pData->uTempStorage.rawHeader) );
        #endif
        #endif
    #endif


       if( pData->uTempStorage.rawHeader.signature == DATAROM_SIGNATURE )
       {
            uint8_t checksumm = getChecksumm( pData->uTempStorage.rawHeader.data,
                                              sizeof(pData->uTempStorage.rawHeader.data) );

            if( pData->uTempStorage.rawHeader.checksumm == checksumm )
            {
                if( pData->uTempStorage.rawHeader.interval > 0 )
                {
                    pData->locData.interval = pData->uTempStorage.rawHeader.interval;

                    pData->uTempStorage.rawSerial.rawSerialNullchr = '\0';
                    for( int idx = 0; idx <= sizeof(pData->uTempStorage.rawSerial.rawSerialTruncated); ++idx )
                    {
                        pData->uTempStorage.rawSerial.rawSerialTruncated[idx] = '\0';
                    }

                    #if DEBUG_AUTOMAT_DATA
                        pData->locData.serial = 0x05555555;
                        dataLoaded = true;
                    #else
                        #if CONFIG_EXTMEM
                        if( ExtMemHandle.Read( DATAROM_SERIAL_ADDR,
                                    (__FLASH_BYTE*)pData->uTempStorage.rawSerial.rawSerialTruncated,
                                    sizeof(pData->uTempStorage.rawSerial.rawSerialTruncated) ) )
                        {
                            pData->locData.serial = atoi(pData->uTempStorage.rawSerial.rawBytes);
                            dataLoaded = true;
                        }
                        #else
                        pData->locData.serial = 0x05555555;
                        dataLoaded = true;
                        #endif
                    #endif

                    #if DEBUG_AUTOMAT_DATA_WRITE == 1
                    #if CONFIG_EXTMEM
                       if( dataLoaded )
                       {
                           ExtMemHandle.Write( DATAROM_SERIAL_ADDR, "5555555\0", 8 );
                       }
                    #endif
                    #endif


                }
            }
       }
   }

   return dataLoaded;
}

// [seq_state_check_header] => {seq_state_initstart}
/* TASK */static bool seq_state_initstart( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   // do not initiate startup sequence until the temperature is ready
   if( pData->extData.avgTempReady )
   {
   __DI__
     rsa_sequence_iclear( &rseq_task );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_initstart );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_wait );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_transmit_0 );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_wait );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_transmit_1 );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_wait );
     rsa_sequence_iinsert_routine( &rseq_task, seq_state_transmit_next );
   __EI__
   // initiate START signal
   dataLineAssertLogic( true );

   __DI__
     pData->counters.gp_timer_counter = 0;

     // Synchronious mode: 1 tick has been spent while changing the state
     pData->counters.gp_timer_maximum = (T_INTERVAL_MUL * 3) - 1;

     rsa_sequence_ireset( &rseq_task );
     rsa_sequence_iskip_routine( &rseq_task ); // {seq_state_start}
     rsa_sequence_iclear( &rseq_timer );
     rsa_sequence_iinsert_routine( &rseq_timer, seqirq_state_timer_nextstate );
   __EI__

   //----- checksumm
   pData->locData.temp = pData->extData.avgTempDegree;
   pData->locData.checksumm = getChecksumm( pData->locData.raw.checksummBytes,
                                            sizeof(pData->locData.raw.checksummBytes) );
   //----- checksumm

   pData->protoControl.bit = 0;
   pData->protoControl.idx = 0;
   pData->protoControl.len = 8 * sizeof(pData->locData.raw); // in [bits]

   // initiate START signal
   dataLineAssertLogic( true );
   }

   state = true; // fixed: 22/05/19
   sleep = true; // allow to sleep (wait for timer)

   return false; // do not move to next routine implicitly
}

// [seq_state_check_header] => [seq_state_initstart] => {seq_state_start}
/* TASK */static bool seq_state_start( void * arg )
{
   // interrupt START signal
   dataLineAssertLogic( false );

   sleep = false; // disallow to sleep

   DEBUG_SET_PIN3

   return true; // [seq_state_transmit_0]
}

// [seq_state_start] => {seq_state_transmit_0}
/* TASK */static bool seq_state_transmit_0( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   pData->protoControl.bit = getTxLineBitValue( pData->locData.txBytes,
                                                pData->protoControl.idx );

   if( pData->protoControl.bit )
   {    DEBUG_SET_PIN2         }
   else
   {    DEBUG_CLR_PIN2         }

   // just for order: repeat signal after @seq_state_start
   // interrupt START signal
   dataLineAssertLogic( false );

   __DI__
     pData->counters.gp_timer_counter = 0;

     // Synchronious mode: 1 tick has been spent for @seq_state_wait or @seq_state_transmit_next
     pData->counters.gp_timer_maximum = T_INTERVAL_MUL * ((pData->protoControl.bit)?1:2) - 1;

     rsa_sequence_iinsert_routine( &rseq_timer, seqirq_state_timer_nextstate );
   __EI__

   sleep = false; // disallow to sleep

   return true; // [seq_state_wait]
}

// [seq_state_transmit_0] => {seq_state_wait} => [seq_state_transmit_1] => {seq_state_wait}
/* TASK */static bool seq_state_wait( void * arg )
{
   sleep = true; // during waiting state - allow to sleep

   return false;
}

// [seq_state_wait] => {seq_state_transmit_1}
/* TASK */static bool seq_state_transmit_1( void * arg )
{
   sData_t * pData = (sData_t*)(arg);
   //rsa_sequence_insert_routine( &rseq_timer, seqirq_state_timer_nextstate );

   pData->protoControl.bit = getTxLineBitValue( pData->locData.txBytes,
                                                pData->protoControl.idx );

   dataLineAssertLogic( true );

   __DI__
     pData->counters.gp_timer_counter = 0;

     // Synchronious mode: 1 tick has been spent for @seq_state_wait or @seq_state_transmit_next
     pData->counters.gp_timer_maximum = T_INTERVAL_MUL * ((pData->protoControl.bit)?2:1) - 1;

     rsa_sequence_iinsert_routine( &rseq_timer, seqirq_state_timer_nextstate );
   __EI__

   sleep = false; // disallow to sleep

   return true; // [seq_state_wait]
}

// [seq_state_wait] => {seq_state_transmit_next}
/* TASK */ static bool seq_state_transmit_next( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   pData->protoControl.idx++;
   if( pData->protoControl.idx >= pData->protoControl.len )
   {
       //debugpin_2_pulse(); --- STOP signal duration measure
       dataLineAssertLogic( false );

       __DI__
         rsa_sequence_iclear( &rseq_task );
         rsa_sequence_iclear( &rseq_timer );

         pData->counters.gp_timer_counter = 0;
         pData->counters.gp_timer_maximum = T_INTERVAL_MUL;
       __EI__
       //---------

       //---------
       __DI__
         rsa_sequence_iinsert_routine( &rseq_task, seq_state_wait );
         rsa_sequence_iinsert_routine( &rseq_timer, seqirq_state_timer_nextstate );
         //---------
         rsa_sequence_iinsert_routine( &rseq_task, seq_state_keycontol_init );
         rsa_sequence_iinsert_routine( &rseq_task, seq_state_keycontol_next );
         rsa_sequence_iinsert_routine( &rseq_task, seq_state_wait );
       __EI__
       //---------

       sleep = true;  // wait for next state - allow to sleep
   }
   else
   {

       dataLineAssertLogic( false );
       __DI__
         rsa_sequence_iback_routine( &rseq_task );    // =>[seq_state_wait]
         rsa_sequence_iback_routine( &rseq_task );    // =>[seq_state_transmit_1]
         rsa_sequence_iback_routine( &rseq_task );    // =>[seq_state_wait]
       __EI__

       seq_state_transmit_0( arg );

       DEBUG_CLR_PIN3

       sleep = false; // disallow to sleep
   }

   return false;
}

// {seqirq_state_timer_nextstate}
/* IRQ */ static bool seqirq_state_timer_nextstate( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   if( pData->counters.gp_timer_counter < pData->counters.gp_timer_maximum )
   {
       pData->counters.gp_timer_counter++;

       sleep = true;  // allow to sleep each timer shoot

       return false;
   }

   rsa_sequence_remove_routine( &rseq_timer ); // [seqirq_state_timer_nextstate] => 0
   rsa_sequence_skip_routine( &rseq_task );    // next

   return true;
}

// {seqirq_state_timer_prevstate}
/* IRQ */ static bool seqirq_state_timer_prevstate( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   if( pData->counters.gp_timer_counter < pData->counters.gp_timer_maximum )
   {
       pData->counters.gp_timer_counter++;

       sleep = true; // allow to sleep each timer shoot

       return false;
   }

   rsa_sequence_remove_routine( &rseq_timer ); // [seqirq_state_timer_nextstate] => 0
   rsa_sequence_back_routine( &rseq_task );    // prev

   return true;
}

// [seq_state_transmit_next] => {seq_state_keycontol_init}
/* TASK */ static bool seq_state_keycontol_init( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   pData->protoControl.bit = 1;
   pData->protoControl.idx = 0;
   #if CONFIG_NFMBASECLASS
   pData->protoControl.len = sizeof(automatKeyStates)/sizeof(*automatKeyStates);
   #elif CONFIG_KEYSW
   pData->protoControl.len = sizeof(automatKeyStatesLegacy)/sizeof(*automatKeyStatesLegacy);
   #endif

   sleep = false; // disallow to sleep

   return true;
}

// [seq_state_keycontol_init] => {seq_state_keycontol_next}
/* TASK */ static bool seq_state_keycontol_next( void * arg )
{
   sData_t * pData = (sData_t*)(arg);

   if( pData->protoControl.idx >= pData->protoControl.len )
   {
       __DI__
         rsa_sequence_iclear( &rseq_task );
         rsa_sequence_iclear( &rseq_timer );
         rsa_sequence_iinsert_routine( &rseq_task, seq_state_initstart );
       __EI__

       sleep = false; // disallow to sleep

       return false;
   }

#if (KEY_STATE_DEBUG > 0) && (DEBUG_PIN > 0)
   if( pData->protoControl.bit == 0 ) {
       pData->protoControl.bit = 1; DEBUG_CLR_PIN;
   } else {
       pData->protoControl.bit = 0; DEBUG_SET_PIN;
   }
#endif
   //debugpin_2_pulse(); --- STOP signal duration measure

   #if CONFIG_NFMBASECLASS
   NFMClass->methods.keyStatesMethods.setKeyStateCommon( automatKeyStates[ pData->protoControl.idx ] );
   #elif CONFIG_KEYSW
   KeySwitchHandle.SetKeyState( automatKeyStatesLegacy[ pData->protoControl.idx ] );
   #endif

   pData->protoControl.idx++;

   __DI__
     pData->counters.gp_timer_counter = 0;
     pData->counters.gp_timer_maximum = (pData->locData.interval)*(pData->extData.ticks_per_1ms);
     rsa_sequence_iinsert_routine( &rseq_timer, seqirq_state_timer_prevstate );
   __EI__

   sleep = false; // disallow to sleep

   return true;
}
#endif