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.

154 lines
3.2KB

  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. // Templates for using full ports or half-ports for parallel output
  19. #ifndef AVRLIB_PARALLEL_H_
  20. #define AVRLIB_PARALLEL_H_
  21. #include <avr/io.h>
  22. #include "avrlib/gpio.h"
  23. namespace avrlib {
  24. enum ParallelPortMode {
  25. PARALLEL_BYTE,
  26. PARALLEL_NIBBLE_HIGH,
  27. PARALLEL_NIBBLE_LOW,
  28. PARALLEL_TRIPLE_HIGHEST,
  29. PARALLEL_TRIPLE_HIGH,
  30. PARALLEL_TRIPLE_LOW,
  31. PARALLEL_DOUBLE_HIGH,
  32. PARALLEL_DOUBLE_MIDHIGH,
  33. PARALLEL_DOUBLE_MIDLOW,
  34. PARALLEL_DOUBLE_LOW
  35. };
  36. template<ParallelPortMode mode>
  37. struct ShiftMasks {
  38. enum Masks {
  39. mask = 0xff,
  40. shift = 0
  41. };
  42. };
  43. template<>
  44. struct ShiftMasks<PARALLEL_NIBBLE_HIGH> {
  45. enum Masks {
  46. mask = 0xf0,
  47. shift = 4,
  48. };
  49. };
  50. template<>
  51. struct ShiftMasks<PARALLEL_NIBBLE_LOW> {
  52. enum Masks {
  53. mask = 0x0f,
  54. shift = 0,
  55. };
  56. };
  57. template<>
  58. struct ShiftMasks<PARALLEL_TRIPLE_HIGHEST> {
  59. enum Masks {
  60. mask = 0xe0,
  61. shift = 5,
  62. };
  63. };
  64. template<>
  65. struct ShiftMasks<PARALLEL_TRIPLE_HIGH> {
  66. enum Masks {
  67. mask = 0x38,
  68. shift = 3,
  69. };
  70. };
  71. template<>
  72. struct ShiftMasks<PARALLEL_TRIPLE_LOW> {
  73. enum Masks {
  74. mask = 0x07,
  75. shift = 0,
  76. };
  77. };
  78. template<>
  79. struct ShiftMasks<PARALLEL_DOUBLE_HIGH> {
  80. enum Masks {
  81. mask = 0xc0,
  82. shift = 6,
  83. };
  84. };
  85. template<>
  86. struct ShiftMasks<PARALLEL_DOUBLE_MIDHIGH> {
  87. enum Masks {
  88. mask = 0x30,
  89. shift = 4,
  90. };
  91. };
  92. template<>
  93. struct ShiftMasks<PARALLEL_DOUBLE_MIDLOW> {
  94. enum Masks {
  95. mask = 0x0c,
  96. shift = 2,
  97. };
  98. };
  99. template<>
  100. struct ShiftMasks<PARALLEL_DOUBLE_LOW> {
  101. enum Masks {
  102. mask = 0x03,
  103. shift = 0,
  104. };
  105. };
  106. template<typename Port, ParallelPortMode parallel_mode = PARALLEL_BYTE>
  107. struct ParallelPort {
  108. typedef ShiftMasks<parallel_mode> Masks;
  109. // Mode change.
  110. static inline void set_mode(uint8_t mode) {
  111. uint8_t preserve = (*Port::Mode::ptr() & ~Masks::mask);
  112. if (mode == DIGITAL_INPUT) {
  113. *Port::Mode::ptr() = preserve;
  114. } else if (mode == DIGITAL_OUTPUT) {
  115. *Port::Mode::ptr() = preserve | Masks::mask;
  116. }
  117. }
  118. static inline void Write(uint8_t value) {
  119. uint8_t preserve = *Port::Output::ptr() & ~Masks::mask;
  120. *Port::Output::ptr() = preserve | (value << Masks::shift);
  121. }
  122. static inline void EnablePullUpResistors() {
  123. uint8_t preserve = *Port::Output::ptr();
  124. *Port::Output::ptr() = preserve | Masks::mask;
  125. }
  126. static inline uint8_t Read() {
  127. return (*Port::Input::ptr() & Masks::mask) >> Masks::shift;
  128. }
  129. };
  130. } // namespace avrlib
  131. #endif // AVRLIB_PARALLEL_H_