#include "Atm_player.hpp" /* Add optional parameters for the state machine to begin() * Add extra initialization code */ Atm_player& Atm_player::begin( int pin /* = - 1 */ ) { // clang-format off const static state_t state_table[] PROGMEM = { /* ON_ENTER ON_LOOP ON_EXIT EVT_START EVT_STOP EVT_TOGGLE EVT_TIMER EVT_EOPAT EVT_REPEAT ELSE */ /* IDLE */ ENT_IDLE, ATM_SLEEP, -1, START, -1, START, -1, -1, -1, -1, /* START */ ENT_START, -1, -1, -1, -1, -1, -1, -1, -1, SOUND, /* SOUND */ ENT_SOUND, -1, -1, -1, IDLE, IDLE, QUIET, -1, -1, -1, /* QUIET */ ENT_QUIET, -1, -1, -1, IDLE, IDLE, NEXT, -1, -1, -1, /* NEXT */ ENT_NEXT, -1, -1, -1, IDLE, IDLE, -1, REPEAT, -1, SOUND, /* REPEAT */ ENT_REPEAT, -1, -1, -1, IDLE, IDLE, -1, -1, FINISH, START, /* FINISH */ ENT_FINISH, -1, -1, -1, IDLE, -1, -1, -1, IDLE, START, }; // clang-format on Machine::begin( state_table, ELSE ); Atm_player::pin = pin; speed( 100 ); pitch( 100 ); repeat( 1 ); play( 880, 50 ); return *this; } /* Add C++ code for each event (input) * The code must return 1 if the event should be triggered */ int Atm_player::event( int id ) { switch ( id ) { case EVT_START: return 0; case EVT_TIMER: return timer.expired( this ); case EVT_EOPAT: if ( patternwidth == 32 ) { return ( step * 3 * sizeof( uint32_t ) ) >= patternsize; } else { return ( step * 3 * sizeof( int ) ) >= patternsize; } case EVT_REPEAT: return counter_repeat.expired(); } return 0; } /* Add C++ code for each action * This generates the 'output' for the state machine */ void Atm_player::action( int id ) { switch ( id ) { case ENT_FINISH: push( connectors, ON_FINISH, 0, 0, 0 ); return; case ENT_IDLE: #ifndef ATM_PLAYER_DISABLE_TONE if ( pin >= 0 ) noTone( pin ); // Tone takes up 7 bytes extra SRAM #endif counter_repeat.set( repeatCount ); return; case ENT_START: step = 0; counter_repeat.decrement(); return; case ENT_SOUND: if ( patternwidth == 32 ) { uint32_t v = pattern32[step * 3] * (uint32_t)pitchFactor; push( connectors, ON_NOTE, true, v & 0xFFFF, v >> 16 & 0xFFFF ); #ifndef ATM_PLAYER_DISABLE_TONE if ( pin >= 0 ) tone( pin, pattern32[step * 3] * pitchFactor ); #endif timer.set( pattern32[step * 3 + 1] * speedFactor ); } else { push( connectors, ON_NOTE, true, pattern16[step * 3] * pitchFactor, 1 ); #ifndef ATM_PLAYER_DISABLE_TONE if ( pin >= 0 ) tone( pin, pattern16[step * 3] * pitchFactor ); #endif timer.set( pattern16[step * 3 + 1] * speedFactor ); } return; case ENT_QUIET: if ( patternwidth == 32 ) { uint32_t v = pattern32[step * 3] * (uint32_t)pitchFactor; push( connectors, ON_NOTE, false, v & 0xFFFF, v >> 16 & 0xFFFF ); #ifndef ATM_PLAYER_DISABLE_TONE if ( pin >= 0 ) noTone( pin ); #endif timer.set( pattern32[step * 3 + 2] * speedFactor ); } else { push( connectors, ON_NOTE, false, pattern16[step * 3] * pitchFactor, 0 ); #ifndef ATM_PLAYER_DISABLE_TONE if ( pin >= 0 ) noTone( pin ); #endif timer.set( pattern16[step * 3 + 2] * speedFactor ); } return; case ENT_NEXT: step++; return; case ENT_REPEAT: return; } } /* How many times to repeat the pattern * */ Atm_player& Atm_player::repeat( uint16_t v /* = -1 */) { counter_repeat.set( repeatCount = v ); return *this; } Atm_player& Atm_player::speed( float v ) { speedFactor = 100 / v; return *this; } Atm_player& Atm_player::pitch( float v ) { pitchFactor = v / 100; return *this; } Atm_player& Atm_player::start( void ) { trigger( EVT_START ); return *this; } Atm_player& Atm_player::stop( void ) { trigger( EVT_STOP ); return *this; } Atm_player& Atm_player::toggle( void ) { trigger( EVT_TOGGLE ); return *this; } /* Sets the pattern and pattern length (in bytes) * */ Atm_player& Atm_player::play( int* pat, int patsize ) { patternwidth = 16; pattern16 = pat; patternsize = patsize; counter_repeat.set( repeatCount ); step = 0; return *this; } Atm_player& Atm_player::play( uint32_t* pat, int patsize ) { patternwidth = 32; pattern32 = pat; patternsize = patsize; counter_repeat.set( repeatCount ); step = 0; return *this; } Atm_player& Atm_player::play( int freq, int period, int pause /* = 0 */ ) { patternwidth = 16; stub[0] = freq; stub[1] = period; stub[2] = pause; pattern16 = stub; patternsize = 3 * sizeof( int ); step = 0; return *this; } /* Optionally override the default trigger() method * Control what triggers your machine can and cannot process */ Atm_player& Atm_player::trigger( int event ) { Machine::trigger( event ); return *this; } /* Optionally override the default state() method * Control what the machine returns when another process requests its state() */ int Atm_player::state( void ) { return Machine::state(); } /* Nothing customizable below this line ************************************************************************************************ */ /* onFinish() push connector variants ( slots 1, autostore 0, broadcast 0 ) * * Usage in action() handler: push( connectors, ON_FINISH, 0, v, up) */ Atm_player& Atm_player::onFinish( Machine& machine, int event ) { onPush( connectors, ON_FINISH, 0, 1, 1, machine, event ); return *this; } Atm_player& Atm_player::onFinish( atm_cb_push_t callback, int idx ) { onPush( connectors, ON_FINISH, 0, 1, 1, callback, idx ); return *this; } /* onNote() push connector variants ( slots 2, autostore 0, broadcast 0 ) * * Usage in action() handler: push( connectors, ON_NOTE, sub, v, up) */ Atm_player& Atm_player::onNote( Machine& machine, int event ) { onPush( connectors, ON_NOTE, 0, 2, 1, machine, event ); return *this; } Atm_player& Atm_player::onNote( atm_cb_push_t callback, int idx ) { onPush( connectors, ON_NOTE, 0, 2, 1, callback, idx ); return *this; } Atm_player& Atm_player::onNote( int sub, Machine& machine, int event ) { onPush( connectors, ON_NOTE, sub, 2, 0, machine, event ); return *this; } Atm_player& Atm_player::onNote( int sub, atm_cb_push_t callback, int idx ) { onPush( connectors, ON_NOTE, sub, 2, 0, callback, idx ); return *this; } /* State trace method * Sets the symbol table and the default logging method for serial monitoring */ Atm_player& Atm_player::trace( Stream& stream ) { Machine::setTrace( &stream, atm_serial_debug::trace, "PLAYER\0EVT_START\0EVT_STOP\0EVT_TOGGLE\0EVT_TIMER\0EVT_EOPAT\0EVT_REPEAT\0ELSE\0IDLE\0START\0SOUND\0QUIET\0NEXT\0REPEAT\0FINISH" ); return *this; }