#include "Atm_out.h" Atm_out& Atm_out::begin( int attached_pin, bool activeLow, EthernetUDP& udpRef, OSCBundle& bndl, const char* address ) { // clang-format off static const state_t state_table[] PROGMEM = { /* ON_ENTER ON_LOOP ON_EXIT EVT_ON_TIMER EVT_OFF_TIMER EVT_WT_TIMER EVT_COUNTER EVT_ON EVT_OFF EVT_BLINK EVT_TOGGLE EVT_TOGGLE_BLINK ELSE */ /* IDLE */ ENT_INIT, ATM_SLEEP, -1, -1, -1, -1, -1, WT_ON, -1, WT_START, ON, WT_START, -1, // LED off /* ON */ ENT_ON, ATM_SLEEP, -1, -1, -1, -1, -1, -1, OFF, WT_START, OFF, OFF, -1, // LED on /* START */ ENT_ON, -1, -1, BLINK_OFF, -1, -1, -1, WT_ON, OFF, -1, OFF, OFF, -1, // Start blinking /* BLINK_OFF */ ENT_OFF, -1, -1, -1, LOOP, -1, -1, WT_ON, OFF, -1, OFF, OFF, -1, /* LOOP */ -1, -1, -1, -1, -1, -1, DONE, WT_ON, OFF, -1, OFF, OFF, START, /* DONE */ -1, -1, EXT_CHAIN, -1, OFF, -1, -1, WT_ON, OFF, WT_START, OFF, OFF, -1, // Wait after last blink /* OFF */ ENT_OFF, -1, -1, -1, -1, -1, -1, WT_ON, OFF, WT_START, -1, -1, IDLE, // All off -> IDLE /* WT_ON */ -1, -1, -1, -1, -1, ON, -1, WT_ON, OFF, WT_START, -1, -1, -1, // LEAD for ON /* WT_START */ -1, -1, -1, -1, -1, START, -1, WT_ON, OFF, WT_START, -1, -1, -1, // LEAD for BLINK }; // clang-format on Machine::begin( state_table, ELSE ); pin = attached_pin; this->activeLow = activeLow; level = 255; toLow = 0; toHigh = 255; wrap = false; pinMode( pin, OUTPUT ); digitalWrite( pin, activeLow ? HIGH : LOW ); on_timer.set( 500 ); off_timer.set( 500 ); pwm( 512, 1 ); lead_timer.set( 0 ); repeat_count = ATM_COUNTER_OFF; counter.set( repeat_count ); while ( state() != 0 ) cycle(); _adress = address; this->_udpRef = &udpRef; this->_bndl = &bndl ; return *this; } Atm_out& Atm_out::pwm( uint16_t width, float freq ) { if ( freq > -1 ) { this->freq = freq; } else { freq = this->freq; } this->width = width; float cycle_width = 1000 / freq; on_timer.set( cycle_width / 1024 * this->width ); off_timer.set( cycle_width / 1024 * ( 1024 - this->width ) ); return *this; } Atm_out& Atm_out::frequency( float freq ) { this->freq = freq; float cycle_width = 1000 / freq; on_timer.set( cycle_width / 1024 * this->width ); off_timer.set( cycle_width / 1024 * ( 1024 - this->width ) ); return *this; } int Atm_out::event( int id ) { switch ( id ) { case EVT_ON_TIMER: return on_timer.expired( this ); case EVT_OFF_TIMER: return off_timer.expired( this ); case EVT_WT_TIMER: return lead_timer.expired( this ); case EVT_COUNTER: return counter.expired(); } return 0; } void Atm_out::action( int id ) { switch ( id ) { case ENT_INIT: counter.set( repeat_count ); return; case ENT_ON: if ( on_timer.value > 0 ) { // Never turn if on_timer is zero (duty cycle 0 must be dark) if ( activeLow ) { digitalWrite( pin, LOW ); } else { if ( level == toHigh ) { digitalWrite( pin, HIGH ); } else { analogWrite( pin, mapLevel( level ) ); } } } return; case ENT_OFF: counter.decrement(); if ( !activeLow ) { digitalWrite( pin, LOW ); } else { if ( level == toHigh ) { digitalWrite( pin, HIGH ); } else { analogWrite( pin, mapLevel( level ) ); } } return; case EXT_CHAIN: onfinish.push( 0 ); return; } } int Atm_out::mapLevel( int level ) { if ( levelMapSize ) { return levelMap[level]; } else { return map( level, toLow, toHigh, 0, 255 ); } } Atm_out& Atm_out::on( void ) { trigger( EVT_ON ); return *this; } Atm_out& Atm_out::off( void ) { trigger( EVT_OFF ); return *this; } Atm_out& Atm_out::toggle( void ) { trigger( EVT_TOGGLE ); return *this; } Atm_out& Atm_out::toggleBlink( void ) { trigger( EVT_TOGGLE_BLINK ); return *this; } Atm_out& Atm_out::start( void ) { trigger( EVT_BLINK ); return *this; } Atm_out& Atm_out::onFinish( Machine& machine, int event /* = 0 */ ) { onfinish.set( &machine, event ); return *this; } Atm_out& Atm_out::onFinish( atm_cb_push_t callback, int idx /* = 0 */ ) { onfinish.set( callback, idx ); return *this; } Atm_out& Atm_out::blink( uint32_t duration, uint32_t pause_duration, uint16_t repeat_count /* = ATM_COUNTER_OFF */ ) { blink( duration ); // Time in which led is fully on pause( pause_duration ); repeat( repeat_count ); return *this; } Atm_out& Atm_out::blink( uint32_t duration ) { on_timer.set( duration ); // Time in which led is fully on return *this; } Atm_out& Atm_out::blink( void ) { trigger( EVT_BLINK ); return *this; } Atm_out& Atm_out::range( int toLow, int toHigh, bool wrap /* = false */ ) { this->toLow = toLow; this->toHigh = toHigh; this->wrap = wrap; level = toHigh; return *this; } Atm_out& Atm_out::levels( unsigned char* map, int mapsize, bool wrap /* = false */ ) { this->levelMap = map; levelMapSize = mapsize; range( 0, mapsize - 1, wrap ); return *this; } Atm_out& Atm_out::pause( uint32_t duration ) { // Time in which led is fully off off_timer.set( duration ? duration : 1 ); // Make sure off_timer is never 0 (work around) return *this; } Atm_out& Atm_out::fade( int fade ) { return *this; } // Dummy for method compatibility with Atm_fade Atm_out& Atm_out::lead( uint32_t ms ) { lead_timer.set( ms ); return *this; } Atm_out& Atm_out::repeat( uint16_t repeat ) { counter.set( repeat_count = repeat ); return *this; } int Atm_out::brightness( int level /* = -1 */ ) { if ( level > -1 ) { this->level = level; if ( current == ON || current == START ) { analogWrite( pin, mapLevel( level ) ); } } return this->level; } int Atm_out::brighten( int v ) { if ( abs( v ) == 1 ) { int br = (int)this->level + v; if ( br > toHigh ) br = wrap ? toLow : toHigh; if ( br < toLow ) br = wrap ? toHigh : toLow; brightness( br ); } return this->level; } Atm_out& Atm_out::trigger( int event ) { if ( event > ELSE ) { brighten( event == EVT_BRUP ? 1 : -1 ); } else { Machine::trigger( event ); } return *this; } Atm_out& Atm_out::onOSC(OSCMessage& msg ){ Serial.println("OSC"); int patternOffset = msg.match(_adress) ; if(patternOffset){ if(msg.fullMatch("/on", patternOffset)){trigger(EVT_ON);} if(msg.fullMatch("/off", patternOffset)){trigger(EVT_OFF);} if(msg.fullMatch("/toggle", patternOffset)){trigger(EVT_TOGGLE);} if(msg.fullMatch("/blink", patternOffset)){trigger(EVT_BLINK);} if(msg.fullMatch("/brightness", patternOffset)){brightness(msg.getInt(0));} return *this; } } Atm_out& Atm_out::trace( Stream& stream ) { setTrace( &stream, atm_serial_debug::trace, "LED\0EVT_ON_TIMER\0EVT_OFF_TIMER\0EVT_WT_TIMER\0EVT_COUNTER\0EVT_ON\0EVT_OFF\0EVT_" "BLINK\0EVT_TOGGLE\0EVT_TOGGLE_BLINK\0ELSE\0" "IDLE\0ON\0START\0BLINK_OFF\0LOOP\0DONE\0OFF\0WT_ON\0WT_START" ); return *this; }