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.

128 lines
3.6KB

  1. // Copyright 2009 Olivier Gillet.
  2. //
  3. // Author: Olivier Gillet (ol.gillet@gmail.com)
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. //
  16. // -----------------------------------------------------------------------------
  17. //
  18. // Debouncing for:
  19. // - A single switch.
  20. // - An array of switches.
  21. #ifndef AVRLIB_DEVICES_SWITCHES_H_
  22. #define AVRLIB_DEVICES_SWITCHES_H_
  23. #include <string.h>
  24. #include "avrlib/devices/shift_register.h"
  25. #include "avrlib/size_to_type.h"
  26. namespace avrlib {
  27. template<typename Input, bool enable_pull_up = true>
  28. class DebouncedSwitch {
  29. public:
  30. DebouncedSwitch() { }
  31. static inline void Init() {
  32. Input::set_mode(DIGITAL_INPUT);
  33. if (enable_pull_up) {
  34. Input::High();
  35. }
  36. state_ = 0xff;
  37. }
  38. // To be called at a rate < 1000 Hz.
  39. static inline uint8_t Read() {
  40. state_ = (state_ << 1) | Input::value();
  41. return state_;
  42. }
  43. static inline uint8_t lowered() { return state_ == 0x80; }
  44. static inline uint8_t raised() { return state_ == 0x7f; }
  45. static inline uint8_t high() { return state_ == 0xff; }
  46. static inline uint8_t low() { return state_ == 0x00; }
  47. static inline uint8_t state() { return state_; }
  48. static inline uint8_t immediate_value() { return Input::value(); }
  49. private:
  50. static uint8_t state_;
  51. DISALLOW_COPY_AND_ASSIGN(DebouncedSwitch);
  52. };
  53. /* static */
  54. template<typename Input, bool enable_pull_up>
  55. uint8_t DebouncedSwitch<Input, enable_pull_up>::state_;
  56. template<typename Load, typename Clock, typename Data, uint8_t num_inputs, DataOrder order = LSB_FIRST>
  57. class DebouncedSwitches {
  58. typedef typename DataTypeForSize<num_inputs>::Type T;
  59. typedef ShiftRegisterInput<
  60. Load, Clock, Data, 8 * sizeof(T), order> Register;
  61. public:
  62. DebouncedSwitches() { }
  63. static inline void Init() {
  64. Register::Init();
  65. memset(state_, 0xff, sizeof(state_));
  66. }
  67. static inline T ReadRegister() {
  68. return Register::Read();
  69. }
  70. static inline void Process(T value) {
  71. T mask = 1 << (num_inputs - 1);
  72. for (uint8_t i = 0; i < num_inputs; ++i) {
  73. state_[i] <<= 1;
  74. if (value & mask) {
  75. state_[i] |= 1;
  76. }
  77. mask >>= 1;
  78. }
  79. }
  80. static inline void Read() {
  81. Process(ReadRegister());
  82. }
  83. static inline uint8_t lowered(uint8_t index) { return state_[index] == 0x80; }
  84. static inline uint8_t raised(uint8_t index) { return state_[index] == 0x7f; }
  85. static inline uint8_t high(uint8_t index) { return state_[index] == 0xff; }
  86. static inline uint8_t low(uint8_t index) { return state_[index] == 0x00; }
  87. static inline uint8_t state(uint8_t index) { return state_[index]; }
  88. static inline int8_t event(uint8_t index) {
  89. if (lowered(index)) {
  90. return -1;
  91. } else if (raised(index)) {
  92. return 1;
  93. }
  94. return 0;
  95. }
  96. private:
  97. static uint8_t state_[num_inputs];
  98. DISALLOW_COPY_AND_ASSIGN(DebouncedSwitches);
  99. };
  100. template<typename Load, typename Clock, typename Data, uint8_t num_inputs, DataOrder order>
  101. uint8_t DebouncedSwitches<Load, Clock, Data, num_inputs, order>::state_[num_inputs];
  102. } // namespace avrlib
  103. #endif // AVRLIB_DEVICES_SWITCHES_H_