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.

139 lines
4.5KB

  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. // Controller for an array of analog or digital inputs behind a multiplexer
  19. // controlled by a shift register. Stores an array reflecting the current value
  20. // of each input. A readout returns an "Event" object with the latest value of
  21. // the controller, a flag indicating how it changed with respect to the
  22. // previous value, and a timestamp.
  23. //
  24. // When event = EVENT_NONE, the time is the idle time (how many ms since an
  25. // event occurred).
  26. // When event != EVENT_NONE, the time is the time spent in the previous state.
  27. #ifndef AVRLIB_DEVICES_INPUT_ARRAY_H_
  28. #define AVRLIB_DEVICES_INPUT_ARRAY_H_
  29. #include "avrlib/size_to_type.h"
  30. #include "avrlib/time.h"
  31. namespace avrlib {
  32. enum InputEvent {
  33. EVENT_NONE = 0,
  34. EVENT_CHANGED = 1,
  35. };
  36. template<typename Input, uint8_t num_inputs, uint8_t low_threshold = 8>
  37. class InputArray {
  38. public:
  39. InputArray() { }
  40. typedef typename DataTypeForSize<Input::data_size>::Type T;
  41. typedef struct {
  42. uint8_t id;
  43. uint8_t event; // Could have been InputEvent but I want the extra byte.
  44. T value;
  45. uint32_t time;
  46. } Event;
  47. static void Init() {
  48. // No need to initialize anything - the first cycle of readouts will take
  49. // care of this.
  50. active_input_ = 0;
  51. starting_up_ = num_inputs * 2;
  52. Input::Init();
  53. }
  54. static void Lock(uint16_t threshold) {
  55. for (uint8_t i = 0; i < num_inputs; ++i) {
  56. thresholds_[i] = threshold;
  57. }
  58. }
  59. static void Touch() {
  60. last_event_time_ = milliseconds();
  61. }
  62. static Event Read() {
  63. Event e;
  64. e.id = active_input_;
  65. // Read a value from the ADC and check if something occurred.
  66. e.value = Input::Read(active_input_);
  67. uint8_t same;
  68. int16_t delta = static_cast<int16_t>(values_[active_input_]) -
  69. static_cast<int16_t>(e.value);
  70. if (delta < 0) {
  71. delta = -delta;
  72. }
  73. same = delta < thresholds_[active_input_];
  74. uint32_t now = milliseconds();
  75. e.time = now - last_event_time_;
  76. if (same) {
  77. e.event = EVENT_NONE;
  78. } else {
  79. // Since the input has been touched and the event has been recorded,
  80. // lower the threshold.
  81. thresholds_[active_input_] = low_threshold;
  82. values_[active_input_] = e.value;
  83. last_event_time_ = now;
  84. e.event = EVENT_CHANGED;
  85. }
  86. // The next call to Read() will read the next input.
  87. ++active_input_;
  88. if (active_input_ == num_inputs) {
  89. active_input_ = 0;
  90. }
  91. // During the first cycle, do not raise any event - just record the values.
  92. if (starting_up_) {
  93. --starting_up_;
  94. e.event = EVENT_NONE;
  95. e.time = 0;
  96. }
  97. return e;
  98. }
  99. static uint8_t active_input() { return active_input_; }
  100. private:
  101. static T values_[num_inputs];
  102. static T thresholds_[num_inputs];
  103. static uint8_t active_input_;
  104. static uint8_t starting_up_;
  105. static uint32_t last_event_time_;
  106. DISALLOW_COPY_AND_ASSIGN(InputArray);
  107. };
  108. template<typename Input, uint8_t num_inputs, uint8_t low_threshold>
  109. typename InputArray<Input, num_inputs, low_threshold>::T
  110. InputArray<Input, num_inputs, low_threshold>::values_[num_inputs];
  111. template<typename Input, uint8_t num_inputs, uint8_t low_threshold>
  112. typename InputArray<Input, num_inputs, low_threshold>::T
  113. InputArray<Input, num_inputs, low_threshold>::thresholds_[num_inputs];
  114. template<typename Input, uint8_t num_inputs, uint8_t low_threshold>
  115. uint8_t InputArray<Input, num_inputs, low_threshold>::active_input_;
  116. template<typename Input, uint8_t num_inputs, uint8_t low_threshold>
  117. uint32_t InputArray<Input, num_inputs, low_threshold>::last_event_time_;
  118. template<typename Input, uint8_t num_inputs, uint8_t low_threshold>
  119. uint8_t InputArray<Input, num_inputs, low_threshold>::starting_up_;
  120. } // namespace avrlib
  121. #endif // AVRLIB_DEVICES_INPUT_ARRAY_H_