123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- #include "Automaton.h"
- int Machine::state() {
- return current;
- }
- Machine& Machine::state( int state ) {
- next = state;
- last_trigger = -1;
- flags &= ~ATM_SLEEP_FLAG;
- return *this;
- }
- Machine& Machine::trigger( int evt ) {
- int new_state;
- int max_cycle = 8;
- do {
- flags &= ~ATM_SLEEP_FLAG;
- cycle();
- new_state = read_state( state_table + ( current * state_width ) + evt + ATM_ON_EXIT + 1 );
- } while ( --max_cycle && ( new_state == -1 || next_trigger != -1 ) );
- if ( new_state > -1 ) {
- next_trigger = evt;
- flags &= ~ATM_SLEEP_FLAG;
- cycle();
- flags &= ~ATM_SLEEP_FLAG;
- cycle();
- }
- return *this;
- }
- Machine& Machine::setTrace( Stream* stream, swcb_sym_t callback, const char symbols[] ) {
- callback_trace = callback;
- stream_trace = stream;
- this->symbols = symbols;
- return *this;
- }
- uint8_t Machine::sleep( int8_t v ) {
- if ( v > -1 ) flags = v ? flags | ATM_SLEEP_FLAG : flags & ~ATM_SLEEP_FLAG;
- return ( flags & ATM_SLEEP_FLAG ) > 0;
- }
- Machine& Machine::begin( const state_t* tbl, int width ) {
- state_table = tbl;
- state_width = ATM_ON_EXIT + width + 2;
- flags &= ~ATM_SLEEP_FLAG;
- automaton.add( *this, false );
- current = -1;
- next = 0;
- next_trigger = -1;
- return *this;
- }
- void Machine::onPush( atm_connector connectors[], int id, int sub, int slots, int fill, Machine& machine, int event ) {
- if ( sub == -1 ) {
- sub = 0;
- for ( int i = 0; i < slots; i++ ) {
- if ( connectors[id + i].mode() == 0 ) {
- sub = i;
- }
- }
- }
- if ( slots > 1 && fill ) {
- for ( int i = 0; i < slots; i++ ) {
- connectors[id + i].set( &machine, event );
- }
- } else {
- connectors[id + sub].set( &machine, event );
- }
- }
- void Machine::onPush( atm_connector connectors[], int id, int sub, int slots, int fill, atm_cb_push_t callback, int idx ) {
- if ( sub == -1 ) {
- sub = 0;
- for ( int i = 0; i < slots; i++ ) {
- if ( connectors[id + i].mode() == 0 ) {
- sub = i;
- }
- }
- }
- if ( slots > 1 && fill ) {
- for ( int i = 0; i < slots; i++ ) {
- connectors[id + i].set( callback, idx );
- }
- } else {
- connectors[id + sub].set( callback, idx );
- }
- }
- void Machine::push( atm_connector connectors[], int id, int sub, int v, int up ) {
- if ( ( id & ATM_BROADCAST ) > 0 ) {
- id = id & ~ATM_BROADCAST;
- for ( int i = id; i < sub; i++ ) {
- connectors[id + i].push( v, up );
- }
- } else {
- connectors[id + sub].push( v, up );
- }
- }
- const char* Machine::mapSymbol( int id, const char map[] ) {
- int cnt = 0;
- int i = 0;
- if ( id == -1 ) return "*NONE*";
- if ( id == 0 ) return map;
- while ( 1 ) {
- if ( map[i] == '\0' && ++cnt == id ) {
- i++;
- break;
- }
- i++;
- }
- return &map[i];
- }
- Machine& Machine::cycle( uint32_t time ) {
- uint32_t cycle_start = millis();
- do {
- if ( ( flags & ( ATM_SLEEP_FLAG | ATM_CYCLE_FLAG ) ) == 0 ) {
- cycles++;
- flags |= ATM_CYCLE_FLAG;
- if ( next != -1 ) {
- action( ATM_ON_SWITCH );
- if ( callback_trace ) {
- callback_trace( stream_trace, *this, symbols, mapSymbol( current == -1 ? current : current + state_width - ATM_ON_EXIT, symbols ),
- mapSymbol( next == -1 ? next : next + state_width - ATM_ON_EXIT, symbols ),
- mapSymbol( last_trigger == -1 ? -1 : last_trigger + 1, symbols ), millis() - state_millis, cycles );
- }
- if ( current > -1 ) action( read_state( state_table + ( current * state_width ) + ATM_ON_EXIT ) );
- current = next;
- next = -1;
- state_millis = millis();
- action( read_state( state_table + ( current * state_width ) + ATM_ON_ENTER ) );
- if ( read_state( state_table + ( current * state_width ) + ATM_ON_LOOP ) == ATM_SLEEP ) {
- flags |= ATM_SLEEP_FLAG;
- } else {
- flags &= ~ATM_SLEEP_FLAG;
- }
- cycles = 0;
- }
- state_t i = read_state( state_table + ( current * state_width ) + ATM_ON_LOOP );
- if ( i != -1 ) {
- action( i );
- }
- for ( i = ATM_ON_EXIT + 1; i < state_width; i++ ) {
- state_t next_state = read_state( state_table + ( current * state_width ) + i );
- if ( ( next_state != -1 ) && ( i == state_width - 1 || event( i - ATM_ON_EXIT - 1 ) || next_trigger == i - ATM_ON_EXIT - 1 ) ) {
- state( next_state );
- last_trigger = i - ATM_ON_EXIT - 1;
- next_trigger = -1;
- break;
- }
- }
- flags &= ~ATM_CYCLE_FLAG;
- }
- } while ( millis() - cycle_start < time );
- return *this;
- }
|