Atm_led.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "Atm_led.hpp"
  2. Atm_led& Atm_led::begin( int attached_pin, bool activeLow ) {
  3. // clang-format off
  4. static const state_t state_table[] PROGMEM = {
  5. /* 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 */
  6. /* IDLE */ ENT_INIT, ATM_SLEEP, -1, -1, -1, -1, -1, WT_ON, -1, WT_START, ON, WT_START, -1, // LED off
  7. /* ON */ ENT_ON, ATM_SLEEP, -1, -1, -1, -1, -1, -1, OFF, WT_START, OFF, OFF, -1, // LED on
  8. /* START */ ENT_ON, -1, -1, BLINK_OFF, -1, -1, -1, WT_ON, OFF, -1, OFF, OFF, -1, // Start blinking
  9. /* BLINK_OFF */ ENT_OFF, -1, -1, -1, LOOP, -1, -1, WT_ON, OFF, -1, OFF, OFF, -1,
  10. /* LOOP */ -1, -1, -1, -1, -1, -1, DONE, WT_ON, OFF, -1, OFF, OFF, START,
  11. /* DONE */ -1, -1, EXT_CHAIN, -1, OFF, -1, -1, WT_ON, OFF, WT_START, OFF, OFF, -1, // Wait after last blink
  12. /* OFF */ ENT_OFF, -1, -1, -1, -1, -1, -1, WT_ON, OFF, WT_START, -1, -1, IDLE, // All off -> IDLE
  13. /* WT_ON */ -1, -1, -1, -1, -1, ON, -1, WT_ON, OFF, WT_START, -1, -1, -1, // LEAD for ON
  14. /* WT_START */ -1, -1, -1, -1, -1, START, -1, WT_ON, OFF, WT_START, -1, -1, -1, // LEAD for BLINK
  15. };
  16. // clang-format on
  17. Machine::begin( state_table, ELSE );
  18. pin = attached_pin;
  19. this->activeLow = activeLow;
  20. level = 255;
  21. toLow = 0;
  22. toHigh = 255;
  23. wrap = false;
  24. pinMode( pin, OUTPUT );
  25. digitalWrite( pin, activeLow ? HIGH : LOW );
  26. on_timer.set( 500 );
  27. off_timer.set( 500 );
  28. pwm( 512, 1 );
  29. lead_timer.set( 0 );
  30. repeat_count = ATM_COUNTER_OFF;
  31. counter.set( repeat_count );
  32. while ( state() != 0 ) cycle();
  33. return *this;
  34. }
  35. Atm_led& Atm_led::pwm( uint16_t width, float freq ) {
  36. if ( freq > -1 ) {
  37. this->freq = freq;
  38. } else {
  39. freq = this->freq;
  40. }
  41. this->width = width;
  42. float cycle_width = 1000 / freq;
  43. on_timer.set( cycle_width / 1024 * this->width );
  44. off_timer.set( cycle_width / 1024 * ( 1024 - this->width ) );
  45. return *this;
  46. }
  47. Atm_led& Atm_led::frequency( float freq ) {
  48. this->freq = freq;
  49. float cycle_width = 1000 / freq;
  50. on_timer.set( cycle_width / 1024 * this->width );
  51. off_timer.set( cycle_width / 1024 * ( 1024 - this->width ) );
  52. return *this;
  53. }
  54. int Atm_led::event( int id ) {
  55. switch ( id ) {
  56. case EVT_ON_TIMER:
  57. return on_timer.expired( this );
  58. case EVT_OFF_TIMER:
  59. return off_timer.expired( this );
  60. case EVT_WT_TIMER:
  61. return lead_timer.expired( this );
  62. case EVT_COUNTER:
  63. return counter.expired();
  64. }
  65. return 0;
  66. }
  67. void Atm_led::action( int id ) {
  68. switch ( id ) {
  69. case ENT_INIT:
  70. counter.set( repeat_count );
  71. return;
  72. case ENT_ON:
  73. if ( on_timer.value > 0 ) { // Never turn if on_timer is zero (duty cycle 0 must be dark)
  74. if ( activeLow ) {
  75. digitalWrite( pin, LOW );
  76. } else {
  77. if ( level == toHigh ) {
  78. digitalWrite( pin, HIGH );
  79. } else {
  80. analogWrite( pin, mapLevel( level ) );
  81. }
  82. }
  83. }
  84. return;
  85. case ENT_OFF:
  86. counter.decrement();
  87. if ( !activeLow ) {
  88. digitalWrite( pin, LOW );
  89. } else {
  90. if ( level == toHigh ) {
  91. digitalWrite( pin, HIGH );
  92. } else {
  93. analogWrite( pin, mapLevel( level ) );
  94. }
  95. }
  96. return;
  97. case EXT_CHAIN:
  98. onfinish.push( 0 );
  99. return;
  100. }
  101. }
  102. int Atm_led::mapLevel( int level ) {
  103. if ( levelMapSize ) {
  104. return levelMap[level];
  105. } else {
  106. return map( level, toLow, toHigh, 0, 255 );
  107. }
  108. }
  109. Atm_led& Atm_led::on( void ) {
  110. trigger( EVT_ON );
  111. return *this;
  112. }
  113. Atm_led& Atm_led::off( void ) {
  114. trigger( EVT_OFF );
  115. return *this;
  116. }
  117. Atm_led& Atm_led::toggle( void ) {
  118. trigger( EVT_TOGGLE );
  119. return *this;
  120. }
  121. Atm_led& Atm_led::toggleBlink( void ) {
  122. trigger( EVT_TOGGLE_BLINK );
  123. return *this;
  124. }
  125. Atm_led& Atm_led::start( void ) {
  126. trigger( EVT_BLINK );
  127. return *this;
  128. }
  129. Atm_led& Atm_led::onFinish( Machine& machine, int event /* = 0 */ ) {
  130. onfinish.set( &machine, event );
  131. return *this;
  132. }
  133. Atm_led& Atm_led::onFinish( atm_cb_push_t callback, int idx /* = 0 */ ) {
  134. onfinish.set( callback, idx );
  135. return *this;
  136. }
  137. Atm_led& Atm_led::blink( uint32_t duration, uint32_t pause_duration, uint16_t repeat_count /* = ATM_COUNTER_OFF */ ) {
  138. blink( duration ); // Time in which led is fully on
  139. pause( pause_duration );
  140. repeat( repeat_count );
  141. return *this;
  142. }
  143. Atm_led& Atm_led::blink( uint32_t duration ) {
  144. on_timer.set( duration ); // Time in which led is fully on
  145. return *this;
  146. }
  147. Atm_led& Atm_led::blink( void ) {
  148. trigger( EVT_BLINK );
  149. return *this;
  150. }
  151. Atm_led& Atm_led::range( int toLow, int toHigh, bool wrap /* = false */ ) {
  152. this->toLow = toLow;
  153. this->toHigh = toHigh;
  154. this->wrap = wrap;
  155. level = toHigh;
  156. return *this;
  157. }
  158. Atm_led& Atm_led::levels( unsigned char* map, int mapsize, bool wrap /* = false */ ) {
  159. this->levelMap = map;
  160. levelMapSize = mapsize;
  161. range( 0, mapsize - 1, wrap );
  162. return *this;
  163. }
  164. Atm_led& Atm_led::pause( uint32_t duration ) { // Time in which led is fully off
  165. off_timer.set( duration ? duration : 1 ); // Make sure off_timer is never 0 (work around)
  166. return *this;
  167. }
  168. Atm_led& Atm_led::fade( int fade ) {
  169. return *this;
  170. } // Dummy for method compatibility with Atm_fade
  171. Atm_led& Atm_led::lead( uint32_t ms ) {
  172. lead_timer.set( ms );
  173. return *this;
  174. }
  175. Atm_led& Atm_led::repeat( uint16_t repeat ) {
  176. counter.set( repeat_count = repeat );
  177. return *this;
  178. }
  179. int Atm_led::brightness( int level /* = -1 */ ) {
  180. if ( level > -1 ) {
  181. this->level = level;
  182. if ( current == ON || current == START ) {
  183. analogWrite( pin, mapLevel( level ) );
  184. }
  185. }
  186. return this->level;
  187. }
  188. int Atm_led::brighten( int v ) {
  189. if ( abs( v ) == 1 ) {
  190. int br = (int)this->level + v;
  191. if ( br > toHigh )
  192. br = wrap ? toLow : toHigh;
  193. if ( br < toLow )
  194. br = wrap ? toHigh : toLow;
  195. brightness( br );
  196. }
  197. return this->level;
  198. }
  199. Atm_led& Atm_led::trigger( int event ) {
  200. if ( event > ELSE ) {
  201. brighten( event == EVT_BRUP ? 1 : -1 );
  202. } else {
  203. Machine::trigger( event );
  204. }
  205. return *this;
  206. }
  207. Atm_led& Atm_led::trace( Stream& stream ) {
  208. setTrace( &stream, atm_serial_debug::trace,
  209. "LED\0EVT_ON_TIMER\0EVT_OFF_TIMER\0EVT_WT_TIMER\0EVT_COUNTER\0EVT_ON\0EVT_OFF\0EVT_"
  210. "BLINK\0EVT_TOGGLE\0EVT_TOGGLE_BLINK\0ELSE\0"
  211. "IDLE\0ON\0START\0BLINK_OFF\0LOOP\0DONE\0OFF\0WT_ON\0WT_START" );
  212. return *this;
  213. }