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.

358 lines
11KB

  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. // Fast serial (for the onboard UART), using compile time optimizations.
  19. //
  20. // Can be used in buffered mode, or in polled mode (to save space or avoid
  21. // interruptions if there is an even higher priority task than the serial I/O).
  22. //
  23. // Usage:
  24. //
  25. // Set-up:
  26. // typedef Serial<SerialPort0, 31250, BUFFERED, POLLED> Serial;
  27. // then, in the setup() hook: Serial::Init()
  28. //
  29. // Write:
  30. // Serial::Write(40) // Will block until data is written.
  31. // write_has_succeeded = Serial::NonBlockingWrite(40) // Will not block.
  32. //
  33. // Buffer manipulation (for buffered I/O):
  34. // Serial::available() // Number of bytes ready to be read. For polled read too
  35. // my_value = Serial::Read() // Will wait until data arrives.
  36. // my_value = Serial::NonBlockingRead() // Will return -1 if no data is there.
  37. // my_value = Serial::ImmediateRead() // Assumes you are sure about what you
  38. // are doing and you know that data is here.
  39. //
  40. // Flushing a buffer:
  41. // Serial::InputBuffer::Flush()
  42. //
  43. // TODO(pichenettes): Buffered writes not supported for now (should look up
  44. // the right interrupt handler).
  45. #ifndef AVRLIB_SERIAL_H_
  46. #define AVRLIB_SERIAL_H_
  47. #include "avrlib/avrlib.h"
  48. #include "avrlib/gpio.h"
  49. #include "avrlib/ring_buffer.h"
  50. namespace avrlib {
  51. const uint8_t kSerialOutputBufferSize = 32;
  52. const uint8_t kSerialInputBufferSize = 32;
  53. // Low-level interface to the low-level UART registers. Several specializations
  54. // may be declared for each serial port. This class could theoretically be used
  55. // for non-blocking write or polling reads.
  56. template<typename TxEnableBit, typename TxReadyBit,
  57. typename RxEnableBit, typename RxReadyBit,
  58. typename RxInterruptBit,
  59. typename TurboBit,
  60. typename PrescalerRegisterH, typename PrescalerRegisterL,
  61. typename DataRegister,
  62. uint8_t input_buffer_size_,
  63. uint8_t output_buffer_size_>
  64. struct SerialPort {
  65. typedef TxEnableBit Tx;
  66. typedef RxEnableBit Rx;
  67. typedef RxInterruptBit RxInterrupt;
  68. typedef TurboBit Turbo;
  69. enum {
  70. input_buffer_size = input_buffer_size_,
  71. output_buffer_size = output_buffer_size_
  72. };
  73. static inline void set_prescaler(uint16_t value) {
  74. *PrescalerRegisterH::ptr() = value >> 8;
  75. *PrescalerRegisterL::ptr() = value;
  76. }
  77. static inline uint8_t tx_ready() { return TxReadyBit::value(); }
  78. static inline uint8_t rx_ready() { return RxReadyBit::value(); }
  79. static inline uint8_t data() { return *DataRegister::ptr(); }
  80. static inline void set_data(uint8_t value) { *DataRegister::ptr() = value; }
  81. };
  82. template<typename SerialPort>
  83. struct SerialInput : public Input {
  84. enum {
  85. buffer_size = SerialPort::input_buffer_size,
  86. data_size = 8
  87. };
  88. typedef uint8_t Value;
  89. // Blocking!
  90. static inline Value Read() { while (!readable()); return ImmediateRead(); }
  91. // Number of bytes available for read.
  92. static inline uint8_t readable() { return SerialPort::rx_ready(); }
  93. // A byte, or -1 if reading failed.
  94. static inline int16_t NonBlockingRead() { return readable() ? Read() : -1; }
  95. // No check for ready state.
  96. static inline Value ImmediateRead() { return SerialPort::data(); }
  97. // Called in data reception interrupt.
  98. static inline void Received() {
  99. if (!readable()) {
  100. return;
  101. }
  102. // This will discard data if the buffer is full.
  103. RingBuffer<SerialInput<SerialPort> >::NonBlockingWrite(ImmediateRead());
  104. }
  105. };
  106. template<typename SerialPort>
  107. struct SerialOutput : public Output {
  108. enum {
  109. buffer_size = SerialPort::output_buffer_size,
  110. data_size = 8
  111. };
  112. typedef uint8_t Value;
  113. // Blocking!
  114. static inline void Write(Value v) { while (!writable()); Overwrite(v); }
  115. // Number of bytes that can be fed.
  116. static inline uint8_t writable() { return SerialPort::tx_ready(); }
  117. // 1 if success.
  118. static inline uint8_t NonBlockingWrite(Value v) {
  119. if (!writable()) {
  120. return 0;
  121. }
  122. Overwrite(v);
  123. return 1;
  124. }
  125. // No check for ready state.
  126. static inline void Overwrite(Value v) { SerialPort::set_data(v); }
  127. // Called in data emission interrupt.
  128. static inline Value Requested() {
  129. Value v = RingBuffer<SerialOutput<SerialPort> >::NonBlockingRead();
  130. if (v >= 0) {
  131. Overwrite(v);
  132. }
  133. }
  134. };
  135. template<typename SerialPort, PortMode input = POLLED, PortMode output = POLLED>
  136. struct SerialImplementation { };
  137. template<typename SerialPort>
  138. struct SerialImplementation<SerialPort, DISABLED, DISABLED> {
  139. typedef InputOutput<DisabledInput, DisabledOutput> IO;
  140. };
  141. template<typename SerialPort>
  142. struct SerialImplementation<SerialPort, DISABLED, POLLED> {
  143. typedef InputOutput<DisabledInput, SerialOutput<SerialPort> > IO;
  144. };
  145. template<typename SerialPort>
  146. struct SerialImplementation<SerialPort, DISABLED, BUFFERED> {
  147. typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer;
  148. typedef InputOutput<DisabledInput, OutputBuffer > IO;
  149. };
  150. template<typename SerialPort>
  151. struct SerialImplementation<SerialPort, POLLED, DISABLED> {
  152. typedef InputOutput<SerialInput<SerialPort>, DisabledOutput> IO;
  153. };
  154. template<typename SerialPort>
  155. struct SerialImplementation<SerialPort, POLLED, POLLED> {
  156. typedef InputOutput<SerialInput<SerialPort>, SerialOutput<SerialPort> > IO;
  157. };
  158. template<typename SerialPort>
  159. struct SerialImplementation<SerialPort, POLLED, BUFFERED> {
  160. typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer;
  161. typedef InputOutput<SerialInput<SerialPort>, OutputBuffer> IO;
  162. };
  163. template<typename SerialPort>
  164. struct SerialImplementation<SerialPort, BUFFERED, DISABLED> {
  165. typedef RingBuffer<SerialInput<SerialPort> > InputBuffer;
  166. typedef InputOutput<InputBuffer, DisabledOutput> IO;
  167. };
  168. template<typename SerialPort>
  169. struct SerialImplementation<SerialPort, BUFFERED, POLLED> {
  170. typedef RingBuffer<SerialInput<SerialPort> > InputBuffer;
  171. typedef InputOutput<InputBuffer, SerialOutput<SerialPort> > IO;
  172. };
  173. template<typename SerialPort>
  174. struct SerialImplementation<SerialPort, BUFFERED, BUFFERED> {
  175. typedef RingBuffer<SerialInput<SerialPort> > InputBuffer;
  176. typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer;
  177. typedef InputOutput<InputBuffer, OutputBuffer> IO;
  178. };
  179. template<typename SerialPort, uint32_t baud_rate, PortMode input = POLLED,
  180. PortMode output = POLLED, bool turbo = false>
  181. struct Serial {
  182. typedef SerialImplementation<SerialPort, input, output> Impl;
  183. typedef uint8_t Value;
  184. typedef typename Impl::IO::Input Input;
  185. typedef typename Impl::IO::Output Output;
  186. static inline void Init() {
  187. Init<baud_rate>();
  188. }
  189. template<uint32_t new_baud_rate>
  190. static inline void Init() {
  191. if (turbo) {
  192. SerialPort::Turbo::set();
  193. uint16_t prescaler = F_CPU / (8L * baud_rate) - 1;
  194. SerialPort::set_prescaler(prescaler);
  195. } else {
  196. SerialPort::Turbo::clear();
  197. uint16_t prescaler = F_CPU / (16 * baud_rate) - 1;
  198. SerialPort::set_prescaler(prescaler);
  199. }
  200. if (output != DISABLED) {
  201. SerialPort::Tx::set();
  202. }
  203. if (input != DISABLED) {
  204. SerialPort::Rx::set();
  205. }
  206. if (input == BUFFERED) {
  207. SerialPort::RxInterrupt::set();
  208. }
  209. }
  210. static inline void Disable() {
  211. SerialPort::Tx::clear();
  212. SerialPort::Rx::clear();
  213. SerialPort::RxInterrupt::clear();
  214. }
  215. static inline void Write(Value v) { Impl::IO::Write(v); }
  216. static inline uint8_t writable() { return Impl::IO::writable(); }
  217. static inline uint8_t NonBlockingWrite(Value v) {
  218. return Impl::IO::NonBlockingWrite(v);
  219. }
  220. static inline void Overwrite(Value v) { Impl::IO::Overwrite(v); }
  221. static inline Value Read() { return Impl::IO::Read(); }
  222. static inline uint8_t readable() { return Impl::IO::readable(); }
  223. static inline int16_t NonBlockingRead() {
  224. return Impl::IO::NonBlockingRead();
  225. }
  226. static inline Value ImmediateRead() { return Impl::IO::ImmediateRead(); }
  227. };
  228. #ifdef HAS_USART0
  229. IORegister(UBRR0H);
  230. IORegister(UBRR0L);
  231. IORegister16(UBRR0);
  232. IORegister(UCSR0A);
  233. IORegister(UCSR0B);
  234. IORegister(UCSR0C);
  235. IORegister(UDR0);
  236. typedef SerialPort<
  237. BitInRegister<UCSR0BRegister, TXEN0>,
  238. BitInRegister<UCSR0ARegister, UDRE0>,
  239. BitInRegister<UCSR0BRegister, RXEN0>,
  240. BitInRegister<UCSR0ARegister, RXC0>,
  241. BitInRegister<UCSR0BRegister, RXCIE0>,
  242. BitInRegister<UCSR0ARegister, U2X0>,
  243. UBRR0HRegister,
  244. UBRR0LRegister,
  245. UDR0Register,
  246. kSerialOutputBufferSize,
  247. kSerialInputBufferSize> SerialPort0;
  248. #endif // #ifdef HAS_USART0
  249. #ifdef HAS_USART1
  250. IORegister(UBRR1H);
  251. IORegister(UBRR1L);
  252. IORegister16(UBRR1);
  253. IORegister(UCSR1A);
  254. IORegister(UCSR1B);
  255. IORegister(UCSR1C);
  256. IORegister(UDR1);
  257. typedef SerialPort<
  258. BitInRegister<UCSR1BRegister, TXEN1>,
  259. BitInRegister<UCSR1ARegister, UDRE1>,
  260. BitInRegister<UCSR1BRegister, RXEN1>,
  261. BitInRegister<UCSR1ARegister, RXC1>,
  262. BitInRegister<UCSR1BRegister, RXCIE1>,
  263. BitInRegister<UCSR1ARegister, U2X1>,
  264. UBRR1HRegister,
  265. UBRR1LRegister,
  266. UDR1Register,
  267. kSerialOutputBufferSize,
  268. kSerialInputBufferSize> SerialPort1;
  269. #endif // #ifdef HAS_USART1
  270. #ifdef HAS_USART2
  271. IORegister(UBRR2H);
  272. IORegister(UBRR2L);
  273. IORegister16(UBRR2);
  274. IORegister(UCSR2A);
  275. IORegister(UCSR2B);
  276. IORegister(UCSR2C);
  277. IORegister(UDR2);
  278. typedef SerialPort<
  279. BitInRegister<UCSR2BRegister, TXEN2>,
  280. BitInRegister<UCSR2ARegister, UDRE2>,
  281. BitInRegister<UCSR2BRegister, RXEN2>,
  282. BitInRegister<UCSR2ARegister, RXC2>,
  283. BitInRegister<UCSR2BRegister, RXCIE2>,
  284. BitInRegister<UCSR2ARegister, U2X2>,
  285. UBRR2HRegister,
  286. UBRR2LRegister,
  287. UDR2Register,
  288. kSerialOutputBufferSize,
  289. kSerialInputBufferSize> SerialPort2;
  290. #endif // #ifdef HAS_USART2
  291. #ifdef HAS_USART3
  292. IORegister(UBRR3H);
  293. IORegister(UBRR3L);
  294. IORegister16(UBRR3);
  295. IORegister(UCSR3A);
  296. IORegister(UCSR3B);
  297. IORegister(UCSR3C);
  298. IORegister(UDR3);
  299. typedef SerialPort<
  300. BitInRegister<UCSR3BRegister, TXEN3>,
  301. BitInRegister<UCSR3ARegister, UDRE3>,
  302. BitInRegister<UCSR3BRegister, RXEN3>,
  303. BitInRegister<UCSR3ARegister, RXC3>,
  304. BitInRegister<UCSR3BRegister, RXCIE3>,
  305. BitInRegister<UCSR3ARegister, U2X3>,
  306. UBRR3HRegister,
  307. UBRR3LRegister,
  308. UDR3Register,
  309. kSerialOutputBufferSize,
  310. kSerialInputBufferSize> SerialPort3;
  311. #endif // #ifdef HAS_USART3
  312. } // namespace avrlib
  313. #endif // AVRLIB_SERIAL_H_