Teensy 4.1 core updated for C++20
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.

HardwareSerial.cpp 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* UART (hardware serial) for Teensy & Teensy++
  2. * http://www.pjrc.com/teensy/
  3. * Copyright (c) 2008 PJRC.COM, LLC
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. */
  23. #include <avr/io.h>
  24. #include <avr/interrupt.h>
  25. #include "core_pins.h"
  26. #include "HardwareSerial.h"
  27. #define RX_BUFFER_SIZE 64
  28. static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
  29. static volatile uint8_t rx_buffer_head = 0;
  30. static volatile uint8_t rx_buffer_tail = 0;
  31. #define TX_BUFFER_SIZE 40
  32. static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
  33. static volatile uint8_t tx_buffer_head = 0;
  34. static volatile uint8_t tx_buffer_tail = 0;
  35. static volatile uint8_t transmitting = 0;
  36. static volatile uint8_t tx_enable_pin = 255;
  37. // Public Methods //////////////////////////////////////////////////////////////
  38. void HardwareSerial::_begin(uint16_t baud_count, uint8_t txen_pin)
  39. {
  40. tx_enable_pin = txen_pin;
  41. if (txen_pin < 255) {
  42. pinMode(txen_pin, OUTPUT);
  43. digitalWrite(txen_pin, LOW);
  44. }
  45. if ((baud_count & 1) && baud_count <= 4096) {
  46. UCSR1A = (1<<U2X1);
  47. UBRR1 = baud_count - 1;
  48. } else {
  49. UCSR1A = 0;
  50. UBRR1 = (baud_count >> 1) - 1;
  51. }
  52. if (!(UCSR1B & (1<<TXEN1))) {
  53. rx_buffer_head = 0;
  54. rx_buffer_tail = 0;
  55. tx_buffer_head = 0;
  56. tx_buffer_tail = 0;
  57. transmitting = 0;
  58. UCSR1C = (1<<UCSZ11) | (1<<UCSZ10);
  59. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
  60. }
  61. }
  62. void HardwareSerial::end(void)
  63. {
  64. while (transmitting) ; // wait for buffered data to send
  65. UCSR1B = 0;
  66. rx_buffer_head = 0;
  67. rx_buffer_tail = 0;
  68. }
  69. void HardwareSerial::transmitterEnable(uint8_t pin)
  70. {
  71. while (transmitting) ;
  72. pinMode(pin, OUTPUT);
  73. digitalWrite(pin, LOW);
  74. tx_enable_pin = pin;
  75. }
  76. int HardwareSerial::available(void)
  77. {
  78. uint8_t head, tail;
  79. head = rx_buffer_head;
  80. tail = rx_buffer_tail;
  81. if (head >= tail) return head - tail;
  82. return RX_BUFFER_SIZE + head - tail;
  83. }
  84. int HardwareSerial::availableForWrite(void)
  85. {
  86. uint8_t head, tail;
  87. head = rx_buffer_head;
  88. tail = rx_buffer_tail;
  89. if (head >= tail) return TX_BUFFER_SIZE - 1 - head + tail;
  90. return tail - head - 1;
  91. }
  92. int HardwareSerial::peek(void)
  93. {
  94. uint8_t head, tail;
  95. head = rx_buffer_head;
  96. tail = rx_buffer_tail;
  97. if (head == tail) return -1;
  98. if (++tail >= RX_BUFFER_SIZE) tail = 0;
  99. return rx_buffer[tail];
  100. }
  101. int HardwareSerial::read(void)
  102. {
  103. uint8_t c, i;
  104. if (rx_buffer_head == rx_buffer_tail) return -1;
  105. i = rx_buffer_tail + 1;
  106. if (i >= RX_BUFFER_SIZE) i = 0;
  107. c = rx_buffer[i];
  108. rx_buffer_tail = i;
  109. return c;
  110. }
  111. void HardwareSerial::flush()
  112. {
  113. #if ARDUINO >= 100
  114. while (transmitting) ; // wait for buffered data to send
  115. #else
  116. rx_buffer_head = rx_buffer_tail;
  117. #endif
  118. }
  119. void HardwareSerial::clear()
  120. {
  121. rx_buffer_head = rx_buffer_tail;
  122. }
  123. #if ARDUINO >= 100
  124. size_t HardwareSerial::write(uint8_t c)
  125. #else
  126. void HardwareSerial::write(uint8_t c)
  127. #endif
  128. {
  129. uint8_t i;
  130. if (!(UCSR1B & (1<<TXEN1))) {
  131. #if ARDUINO >= 100
  132. setWriteError();
  133. return 0;
  134. #else
  135. return;
  136. #endif
  137. }
  138. if (tx_enable_pin < 255 && !transmitting) {
  139. digitalWrite(tx_enable_pin, HIGH);
  140. }
  141. i = tx_buffer_head + 1;
  142. if (i >= TX_BUFFER_SIZE) i = 0;
  143. while (tx_buffer_tail == i) ; // wait until space in buffer
  144. tx_buffer[i] = c;
  145. transmitting = 1;
  146. tx_buffer_head = i;
  147. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1) | (1<<UDRIE1);
  148. #if ARDUINO >= 100
  149. return 1;
  150. #endif
  151. }
  152. ISR(USART1_RX_vect)
  153. {
  154. uint8_t c, i;
  155. c = UDR1;
  156. i = rx_buffer_head + 1;
  157. if (i >= RX_BUFFER_SIZE) i = 0;
  158. if (i != rx_buffer_tail) {
  159. rx_buffer[i] = c;
  160. rx_buffer_head = i;
  161. }
  162. }
  163. ISR(USART1_UDRE_vect)
  164. {
  165. uint8_t i;
  166. if (tx_buffer_head == tx_buffer_tail) {
  167. // buffer is empty, disable transmit interrupt
  168. UCSR1B = (1<<RXEN1) | (1<<TXCIE1) | (1<<TXEN1) | (1<<RXCIE1);
  169. } else {
  170. i = tx_buffer_tail + 1;
  171. if (i >= TX_BUFFER_SIZE) i = 0;
  172. UDR1 = tx_buffer[i];
  173. tx_buffer_tail = i;
  174. }
  175. }
  176. ISR(USART1_TX_vect)
  177. {
  178. transmitting = 0;
  179. if (tx_enable_pin < 255) {
  180. digitalWrite(tx_enable_pin, LOW);
  181. }
  182. }
  183. // Preinstantiate Objects //////////////////////////////////////////////////////
  184. HardwareSerial Serial1;