Atm_encoder.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. #include "Atm_encoder.hpp"
  2. #include <limits.h>
  3. // Loosely based on https://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino (Oleg Mazurov)
  4. const char Atm_encoder::enc_states[16] = {0, (char)-1, 1, 0, 1, 0, 0, (char)-1, (char)-1, 0, 0, 1, 0, 1, (char)-1, 0};
  5. Atm_encoder& Atm_encoder::begin( int pin1, int pin2, int divider /* = 1 */ ) {
  6. // clang-format off
  7. const static state_t state_table[] PROGMEM = {
  8. /* ON_ENTER ON_LOOP ON_EXIT EVT_UP EVT_DOWN ELSE */
  9. /* IDLE */ -1, LP_IDLE, -1, UP, DOWN, -1,
  10. /* UP */ ENT_UP, -1, -1, -1, -1, IDLE,
  11. /* DOWN */ ENT_DOWN, -1, -1, -1, -1, IDLE,
  12. };
  13. // clang-format on
  14. Machine::begin( state_table, ELSE );
  15. this->pin1 = pin1;
  16. this->pin2 = pin2;
  17. this->divider = divider;
  18. pinMode( pin1, INPUT );
  19. pinMode( pin2, INPUT );
  20. digitalWrite( pin1, HIGH );
  21. digitalWrite( pin2, HIGH );
  22. min = INT_MIN;
  23. max = INT_MAX;
  24. value = 0;
  25. return *this;
  26. }
  27. int Atm_encoder::event( int id ) {
  28. switch ( id ) {
  29. case EVT_UP:
  30. return enc_direction == +1 && ( enc_counter % divider == 0 );
  31. case EVT_DOWN:
  32. return enc_direction == -1 && ( enc_counter % divider == 0 );
  33. }
  34. return 0;
  35. }
  36. void Atm_encoder::action( int id ) {
  37. switch ( id ) {
  38. case LP_IDLE:
  39. enc_bits = ( ( enc_bits << 2 ) | ( digitalRead( pin1 ) << 1 ) | ( digitalRead( pin2 ) ) ) & 0x0f;
  40. enc_direction = enc_states[enc_bits];
  41. if ( enc_direction != 0 ) {
  42. enc_counter = enc_counter + enc_direction;
  43. if ( ( enc_counter != 0 ) && ( enc_counter % divider == 0 ) ) {
  44. if ( !count( enc_direction ) ) {
  45. enc_direction = 0;
  46. }
  47. }
  48. }
  49. return;
  50. case ENT_UP:
  51. onup.push( state(), 1 );
  52. return;
  53. case ENT_DOWN:
  54. ondown.push( state(), 0 );
  55. return;
  56. }
  57. }
  58. Atm_encoder& Atm_encoder::range( int min, int max, bool wrap /* = false */ ) {
  59. if ( min > max ) {
  60. range_invert = true;
  61. this->min = max;
  62. this->max = min;
  63. } else {
  64. range_invert = false;
  65. this->min = min;
  66. this->max = max;
  67. }
  68. this->wrap = wrap;
  69. if ( value < min || value > max ) {
  70. value = min;
  71. }
  72. return *this;
  73. }
  74. Atm_encoder& Atm_encoder::set( int value ) {
  75. this->value = range_invert ? map( value, min, max, max, min ) : value;
  76. return *this;
  77. }
  78. Atm_encoder& Atm_encoder::onChange( Machine& machine, int event /* = 0 */ ) {
  79. onup.set( &machine, event );
  80. ondown.set( &machine, event );
  81. return *this;
  82. }
  83. Atm_encoder& Atm_encoder::onChange( atm_cb_push_t callback, int idx /* = 0 */ ) {
  84. onup.set( callback, idx );
  85. ondown.set( callback, idx );
  86. return *this;
  87. }
  88. Atm_encoder& Atm_encoder::onChange( bool status, Machine& machine, int event /* = 0 */ ) {
  89. if ( status ) {
  90. onup.set( &machine, event );
  91. } else {
  92. ondown.set( &machine, event );
  93. }
  94. return *this;
  95. }
  96. Atm_encoder& Atm_encoder::onChange( bool status, atm_cb_push_t callback, int idx /* = 0 */ ) {
  97. if ( status ) {
  98. onup.set( callback, idx );
  99. } else {
  100. ondown.set( callback, idx );
  101. }
  102. return *this;
  103. }
  104. int Atm_encoder::state( void ) {
  105. return range_invert ? map( value, min, max, max, min ) : value;
  106. }
  107. bool Atm_encoder::count( int direction ) {
  108. if ( (long)value + direction > max ) {
  109. if ( wrap ) {
  110. value = min;
  111. } else {
  112. return false;
  113. }
  114. } else if ( (long)value + direction < min ) {
  115. if ( wrap ) {
  116. value = max;
  117. } else {
  118. return false;
  119. }
  120. } else {
  121. value += direction;
  122. }
  123. return true;
  124. }
  125. Atm_encoder& Atm_encoder::trace( Stream& stream ) {
  126. Machine::setTrace( &stream, atm_serial_debug::trace, "ENCODER\0EVT_UP\0EVT_DOWN\0ELSE\0IDLE\0UP\0DOWN" );
  127. return *this;
  128. }