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.

151 lines
4.0KB

  1. // Copyright 2011 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. #ifndef AVRLIBX_IO_USART_H_
  16. #define AVRLIBX_IO_USART_H_
  17. #include <avr/io.h>
  18. #include "avrlibx/avrlibx.h"
  19. namespace avrlibx {
  20. enum RxMode {
  21. RX_DISABLED,
  22. RX_POLLED
  23. };
  24. enum TxMode {
  25. TX_DISABLED,
  26. TX_POLLED
  27. };
  28. template<typename Port, uint8_t index> struct USARTWrapper { };
  29. #define WRAP_USART(port, index) \
  30. template<> \
  31. struct USARTWrapper<Port ## port, index> { \
  32. static inline USART_t& usart() { \
  33. return USART ## port ## index; \
  34. } \
  35. static volatile inline uint8_t data() { \
  36. return USART ## port ## index ## _DATA; \
  37. } \
  38. static inline void set_data(uint16_t value) { \
  39. USART ## port ## index ## _DATA = value; \
  40. } \
  41. static inline uint8_t readable() { \
  42. return USART ## port ## index ## _STATUS & USART_RXCIF_bm; \
  43. } \
  44. static inline uint8_t writable_buffer() { \
  45. return USART ## port ## index ## _STATUS & USART_DREIF_bm; \
  46. } \
  47. static inline uint8_t writable() { \
  48. return USART ## port ## index ## _STATUS & USART_TXCIF_bm; \
  49. } \
  50. static inline uint8_t dma_rx_trigger() { \
  51. return DMA_CH_TRIGSRC_USART ## port ## index ## _RXC_gc; \
  52. } \
  53. static inline uint8_t dma_tx_trigger() { \
  54. return DMA_CH_TRIGSRC_USART ## port ## index ## _DRE_gc; \
  55. } \
  56. static inline volatile void* dma_data() { \
  57. return &(USART ## port ## index ## _DATA); \
  58. } \
  59. };
  60. WRAP_USART(C, 0)
  61. WRAP_USART(C, 1)
  62. WRAP_USART(D, 0)
  63. WRAP_USART(D, 1)
  64. WRAP_USART(E, 0)
  65. #ifdef USARTE1
  66. WRAP_USART(E, 1)
  67. #endif
  68. #ifdef USARTF0
  69. WRAP_USART(F, 0)
  70. #endif
  71. #ifdef USARTF1
  72. WRAP_USART(F, 1)
  73. #endif
  74. template<
  75. typename Port,
  76. uint8_t index,
  77. uint32_t baud_rate,
  78. RxMode rx_mode,
  79. TxMode tx_mode>
  80. struct Usart {
  81. typedef USARTWrapper<Port, index> USART;
  82. static inline void Init() {
  83. Init<baud_rate>();
  84. }
  85. template<uint32_t new_baud_rate>
  86. static inline void Init() {
  87. uint16_t prescaler = F_CPU / (16 * baud_rate) - 1;
  88. USART::usart().BAUDCTRLA = prescaler & 0xff;
  89. USART::usart().BAUDCTRLB = (prescaler >> 8) & 0xf;
  90. uint8_t control;
  91. if (rx_mode != RX_DISABLED) {
  92. control |= USART_RXEN_bm;
  93. }
  94. if (tx_mode != TX_DISABLED) {
  95. if (index == 0) {
  96. Gpio<Port, 3>::set_direction(OUTPUT);
  97. } else {
  98. Gpio<Port, 7>::set_direction(OUTPUT);
  99. }
  100. control |= USART_TXEN_bm;
  101. }
  102. USART::usart().CTRLB = control;
  103. }
  104. static inline void Write(uint8_t v) { while (!writable()); Overwrite(v); }
  105. static inline uint8_t writable() { return USART::writable_buffer(); }
  106. static inline uint8_t NonBlockingWrite(uint8_t v) {
  107. if (!writable()) {
  108. return 0;
  109. }
  110. Overwrite(v);
  111. return 1;
  112. }
  113. static inline void Overwrite(uint8_t v) { USART::set_data(v); }
  114. static inline uint8_t Read() { while (!readable()); return ImmediateRead(); }
  115. static inline uint8_t readable() { return USART::readable(); }
  116. static inline uint16_t NonBlockingRead() {
  117. return readable() ? ImmediateRead() : -1;
  118. }
  119. static inline uint8_t ImmediateRead() { return USART::data(); }
  120. static inline uint8_t dma_rx_trigger() {
  121. return USART::dma_rx_trigger();
  122. }
  123. static inline uint8_t dma_tx_trigger() {
  124. return USART::dma_rx_trigger();
  125. }
  126. static inline volatile void* dma_data() {
  127. return USART::dma_data();
  128. }
  129. typedef uint8_t Value;
  130. };
  131. } // namespace avrlibx
  132. #endif // AVRLIBX_IO_USART_H_