gpio.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
  2. // Copyright (C) 2013 Henner Zeller <h.zeller@acm.org>
  3. //
  4. // This program is free software; you can redistribute it and/or modify
  5. // it under the terms of the GNU General Public License as published by
  6. // the Free Software Foundation version 2.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program. If not, see <http://gnu.org/licenses/gpl-2.0.txt>
  15. #ifndef RPI_GPIO_INTERNAL_H
  16. #define RPI_GPIO_INTERNAL_H
  17. #include "gpio-bits.h"
  18. #include <vector>
  19. // Putting this in our namespace to not collide with other things called like
  20. // this.
  21. namespace rgb_matrix {
  22. // For now, everything is initialized as output.
  23. class GPIO {
  24. public:
  25. GPIO();
  26. // Initialize before use. Returns 'true' if successful, 'false' otherwise
  27. // (e.g. due to a permission problem).
  28. bool Init(int
  29. #if RGB_SLOWDOWN_GPIO
  30. slowdown = RGB_SLOWDOWN_GPIO
  31. #else
  32. slowdown = 1
  33. #endif
  34. );
  35. // Initialize outputs.
  36. // Returns the bits that were available and could be set for output.
  37. // (never use the optional adafruit_hack_needed parameter, it is used
  38. // internally to this library).
  39. gpio_bits_t InitOutputs(gpio_bits_t outputs,
  40. bool adafruit_hack_needed = false);
  41. // Request given bitmap of GPIO inputs.
  42. // Returns the bits that were available and could be reserved.
  43. gpio_bits_t RequestInputs(gpio_bits_t inputs);
  44. // Set the bits that are '1' in the output. Leave the rest untouched.
  45. inline void SetBits(gpio_bits_t value) {
  46. if (!value) return;
  47. WriteSetBits(value);
  48. for (int i = 0; i < slowdown_; ++i) {
  49. WriteSetBits(value);
  50. }
  51. }
  52. // Clear the bits that are '1' in the output. Leave the rest untouched.
  53. inline void ClearBits(gpio_bits_t value) {
  54. if (!value) return;
  55. WriteClrBits(value);
  56. for (int i = 0; i < slowdown_; ++i) {
  57. WriteClrBits(value);
  58. }
  59. }
  60. // Write all the bits of "value" mentioned in "mask". Leave the rest untouched.
  61. inline void WriteMaskedBits(gpio_bits_t value, gpio_bits_t mask) {
  62. // Writing a word is two operations. The IO is actually pretty slow, so
  63. // this should probably be unnoticable.
  64. ClearBits(~value & mask);
  65. SetBits(value & mask);
  66. }
  67. inline gpio_bits_t Read() const { return ReadRegisters() & input_bits_; }
  68. private:
  69. inline gpio_bits_t ReadRegisters() const {
  70. return (static_cast<gpio_bits_t>(*gpio_read_bits_low_)
  71. #ifdef ENABLE_WIDE_GPIO_COMPUTE_MODULE
  72. | (static_cast<gpio_bits_t>(*gpio_read_bits_low_) << 32)
  73. #endif
  74. );
  75. }
  76. inline void WriteSetBits(gpio_bits_t value) {
  77. *gpio_set_bits_low_ = static_cast<uint32_t>(value & 0xFFFFFFFF);
  78. #ifdef ENABLE_WIDE_GPIO_COMPUTE_MODULE
  79. if (uses_64_bit_)
  80. *gpio_set_bits_high_ = static_cast<uint32_t>(value >> 32);
  81. #endif
  82. }
  83. inline void WriteClrBits(gpio_bits_t value) {
  84. *gpio_clr_bits_low_ = static_cast<uint32_t>(value & 0xFFFFFFFF);
  85. #ifdef ENABLE_WIDE_GPIO_COMPUTE_MODULE
  86. if (uses_64_bit_)
  87. *gpio_clr_bits_high_ = static_cast<uint32_t>(value >> 32);
  88. #endif
  89. }
  90. private:
  91. gpio_bits_t output_bits_;
  92. gpio_bits_t input_bits_;
  93. gpio_bits_t reserved_bits_;
  94. int slowdown_;
  95. volatile uint32_t *gpio_set_bits_low_;
  96. volatile uint32_t *gpio_clr_bits_low_;
  97. volatile uint32_t *gpio_read_bits_low_;
  98. #ifdef ENABLE_WIDE_GPIO_COMPUTE_MODULE
  99. bool uses_64_bit_;
  100. volatile uint32_t *gpio_set_bits_high_;
  101. volatile uint32_t *gpio_clr_bits_high_;
  102. volatile uint32_t *gpio_read_bits_high_;
  103. #endif
  104. };
  105. // A PinPulser is a utility class that pulses a GPIO pin. There can be various
  106. // implementations.
  107. class PinPulser {
  108. public:
  109. // Factory for a PinPulser. Chooses the right implementation depending
  110. // on the context (CPU and which pins are affected).
  111. // "gpio_mask" is the mask that should be output (since we only
  112. // need negative pulses, this is what it does)
  113. // "nano_wait_spec" contains a list of time periods we'd like
  114. // invoke later. This can be used to pre-process timings if needed.
  115. static PinPulser *Create(GPIO *io, gpio_bits_t gpio_mask,
  116. bool allow_hardware_pulsing,
  117. const std::vector<int> &nano_wait_spec);
  118. virtual ~PinPulser() {}
  119. // Send a pulse with a given length (index into nano_wait_spec array).
  120. virtual void SendPulse(int time_spec_number) = 0;
  121. // If SendPulse() is asynchronously implemented, wait for pulse to finish.
  122. virtual void WaitPulseFinished() {}
  123. };
  124. // Get rolling over microsecond counter. We get this from a hardware register
  125. // if possible and a terrible slow fallback otherwise.
  126. uint32_t GetMicrosecondCounter();
  127. } // end namespace rgb_matrix
  128. #endif // RPI_GPIO_INGERNALH