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.6KB

  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_SPI_H_
  16. #define AVRLIBX_IO_USART_SPI_H_
  17. #include <avr/io.h>
  18. #include "avrlibx/avrlibx.h"
  19. #include "avrlibx/io/gpio.h"
  20. #include "avrlibx/io/spi.h"
  21. #include "avrlibx/io/usart.h"
  22. namespace avrlibx {
  23. template<typename Port, uint8_t index>
  24. struct UsartSPIPorts { };
  25. template<typename Port>
  26. struct UsartSPIPorts<Port, 0> {
  27. typedef Gpio<Port, 1> XCK;
  28. typedef Gpio<Port, 2> RX;
  29. typedef Gpio<Port, 3> TX;
  30. };
  31. template<typename Port>
  32. struct UsartSPIPorts<Port, 1> {
  33. typedef Gpio<Port, 5> XCK;
  34. typedef Gpio<Port, 6> RX;
  35. typedef Gpio<Port, 7> TX;
  36. };
  37. template<
  38. typename Port,
  39. uint8_t index,
  40. typename SlaveSelect,
  41. DataOrder order = MSB_FIRST,
  42. uint8_t speed = SPI_PRESCALER_CLK_4>
  43. struct UsartSPIMaster {
  44. typedef USARTWrapper<Port, index> USART;
  45. typedef typename UsartSPIPorts<Port, index>::XCK XCK;
  46. typedef typename UsartSPIPorts<Port, index>::RX RX;
  47. typedef typename UsartSPIPorts<Port, index>::TX TX;
  48. static inline void Init() {
  49. XCK::set_direction(OUTPUT);
  50. TX::set_direction(OUTPUT);
  51. RX::set_direction(INPUT);
  52. SlaveSelect::set_direction(OUTPUT);
  53. SlaveSelect::High();
  54. uint16_t baud_rate_register_value = speed / 2 - 1;
  55. USART::usart().BAUDCTRLA = baud_rate_register_value & 0xff;
  56. USART::usart().BAUDCTRLB = (baud_rate_register_value >> 8) & 0xf;
  57. USART::usart().CTRLC = USART_CMODE_MSPI_gc;
  58. if (order == LSB_FIRST) {
  59. USART::usart().CTRLC |= 4;
  60. }
  61. USART::usart().CTRLB = USART_RXEN_bm | USART_TXEN_bm;
  62. }
  63. static inline void PullUpRX() {
  64. RX::set_mode(PORT_MODE_PULL_UP);
  65. }
  66. static inline void Begin() {
  67. SlaveSelect::Low();
  68. }
  69. static inline void End() {
  70. SlaveSelect::High();
  71. }
  72. static inline void Strobe() {
  73. SlaveSelect::High();
  74. SlaveSelect::Low();
  75. }
  76. static inline void Write(uint8_t v) {
  77. Begin();
  78. Send(v);
  79. End();
  80. }
  81. static inline uint8_t Read() {
  82. Begin();
  83. uint8_t result = Receive();
  84. End();
  85. return result;
  86. }
  87. static inline void Send(uint8_t v) {
  88. Overwrite(v);
  89. Wait();
  90. }
  91. static inline uint8_t Receive() {
  92. Send(0xff);
  93. return ImmediateRead();
  94. }
  95. static inline uint8_t ImmediateRead() {
  96. return USART::data();
  97. }
  98. static inline void Wait() {
  99. while (!USART::writable());
  100. }
  101. static inline void OptimisticWait() {
  102. while (!USART::writable_buffer());
  103. }
  104. static inline void Overwrite(uint8_t v) {
  105. USART::set_data(v);
  106. }
  107. static inline void WriteWord(uint8_t a, uint8_t b) {
  108. Begin();
  109. Send(a);
  110. Send(b);
  111. End();
  112. }
  113. static inline uint8_t dma_rx_trigger() {
  114. return USART::dma_rx_trigger();
  115. }
  116. static inline uint8_t dma_tx_trigger() {
  117. return USART::dma_rx_trigger();
  118. }
  119. static inline volatile void* dma_data() {
  120. return USART::dma_data();
  121. }
  122. typedef uint8_t Value;
  123. };
  124. } // namespace avrlibx
  125. #endif // AVRLIBX_IO_USART_SPI_H_