Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

131 lines
3.5 KiB

  1. /*
  2. ENCODER MODULE
  3. Copyright (C) 2018 by Xose Pérez <xose dot perez at gmail dot com>
  4. */
  5. #if ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)
  6. #include <Encoder.h>
  7. #include <vector>
  8. typedef struct {
  9. Encoder * encoder;
  10. unsigned char button_pin;
  11. unsigned char button_logic;
  12. unsigned char button_mode;
  13. unsigned char mode;
  14. unsigned char channel1; // default
  15. unsigned char channel2; // only if button defined and pressed
  16. } encoder_t;
  17. std::vector<encoder_t> _encoders;
  18. void _encoderConfigure() {
  19. // Clean previous encoders
  20. for (unsigned char i=0; i<_encoders.size(); i++) {
  21. free(_encoders[i].encoder);
  22. }
  23. _encoders.clear();
  24. unsigned char index = 0;
  25. while (index < MAX_COMPONENTS) {
  26. unsigned char pin1 = getSetting("enc1stGPIO", index, GPIO_NONE).toInt();
  27. unsigned char pin2 = getSetting("enc2ndGPIO", index, GPIO_NONE).toInt();
  28. if (GPIO_NONE == pin1 || GPIO_NONE == pin2) break;
  29. unsigned char button_pin = getSetting("encBtnGPIO", index, GPIO_NONE).toInt();
  30. unsigned char button_logic = getSetting("encBtnLogic", index, GPIO_LOGIC_INVERSE).toInt();
  31. unsigned char button_mode = getSetting("encBtnMode", index, INPUT_PULLUP).toInt();
  32. unsigned char mode = getSetting("encMode", index, ENCODER_MODE_RATIO).toInt();
  33. unsigned char channel1 = getSetting("enc1stCh", index, 0).toInt();
  34. unsigned char channel2 = getSetting("enc2ndCh", index, 1).toInt();
  35. _encoders.push_back({
  36. new Encoder(pin1, pin2),
  37. button_pin, button_logic, button_mode,
  38. mode,
  39. channel1, channel2
  40. });
  41. if (GPIO_NONE != button_pin) {
  42. pinMode(button_pin, button_mode);
  43. }
  44. ++index;
  45. }
  46. DEBUG_MSG_P(PSTR("[ENCODER] Encoders: %u\n"), _encoders.size());
  47. }
  48. void _encoderLoop() {
  49. // for each encoder
  50. for (unsigned char i=0; i<_encoders.size(); i++) {
  51. // get encoder
  52. encoder_t encoder = _encoders[i];
  53. // read encoder
  54. long delta = encoder.encoder->read();
  55. encoder.encoder->write(0);
  56. if (0 == delta) continue;
  57. DEBUG_MSG_P(PSTR("[ENCODER] Delta: %d\n"), delta);
  58. // action
  59. if (encoder.button_pin == GPIO_NONE) {
  60. // if there is no button, the encoder driver the CHANNEL1
  61. lightChannelStep(encoder.channel1, delta);
  62. } else {
  63. // check if button is pressed
  64. bool pressed = (digitalRead(encoder.button_pin) != encoder.button_logic);
  65. if (ENCODER_MODE_CHANNEL == encoder.mode) {
  66. // the button controls what channel we are changing
  67. lightChannelStep(pressed ? encoder.channel2 : encoder.channel1, delta);
  68. } if (ENCODER_MODE_RATIO == encoder.mode) {
  69. // the button controls if we are changing the channel ratio or the overall brightness
  70. if (pressed) {
  71. lightChannelStep(encoder.channel1, delta);
  72. lightChannelStep(encoder.channel2, -delta);
  73. } else {
  74. lightBrightnessStep(delta);
  75. }
  76. }
  77. }
  78. lightUpdate(true, true);
  79. }
  80. }
  81. // -----------------------------------------------------------------------------
  82. void encoderSetup() {
  83. // Configure encoders
  84. _encoderConfigure();
  85. // Main callbacks
  86. espurnaRegisterLoop(_encoderLoop);
  87. espurnaRegisterReload(_encoderConfigure);
  88. }
  89. #endif // ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)