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 46 #ifndef AVRLIB_SERIAL_H_ 47 #define AVRLIB_SERIAL_H_ 48 49 #include "avrlib/avrlib.h" 50 #include "avrlib/gpio.h" 51 #include "avrlib/ring_buffer.h" 52 53 namespace avrlib { 54 55 const uint8_t kSerialOutputBufferSize = 32; 56 const uint8_t kSerialInputBufferSize = 32; 57 58 // Low-level interface to the low-level UART registers. Several specializations 59 // may be declared for each serial port. This class could theoretically be used 60 // for non-blocking write or polling reads. 61 template<typename TxEnableBit, typename TxReadyBit, 62 typename RxEnableBit, typename RxReadyBit, 63 typename RxInterruptBit, 64 typename TurboBit, 65 typename PrescalerRegisterH, typename PrescalerRegisterL, 66 typename DataRegister, 67 uint8_t input_buffer_size_, 68 uint8_t output_buffer_size_> 69 struct SerialPort { 70 typedef TxEnableBit Tx; 71 typedef RxEnableBit Rx; 72 typedef RxInterruptBit RxInterrupt; 73 typedef TurboBit Turbo; 74 enum { 75 input_buffer_size = input_buffer_size_, 76 output_buffer_size = output_buffer_size_ 77 }; set_prescalerSerialPort78 static inline void set_prescaler(uint16_t value) { 79 *PrescalerRegisterH::ptr() = value >> 8; 80 *PrescalerRegisterL::ptr() = value; 81 } tx_readySerialPort82 static inline uint8_t tx_ready() { return TxReadyBit::value(); } rx_readySerialPort83 static inline uint8_t rx_ready() { return RxReadyBit::value(); } dataSerialPort84 static inline uint8_t data() { return *DataRegister::ptr(); } set_dataSerialPort85 static inline void set_data(uint8_t value) { *DataRegister::ptr() = value; } 86 }; 87 88 template<typename SerialPort> 89 struct SerialInput : public Input { 90 enum { 91 buffer_size = SerialPort::input_buffer_size, 92 data_size = 8 93 }; 94 typedef uint8_t Value; 95 96 // Blocking! ReadSerialInput97 static inline Value Read() { while (!readable()); return ImmediateRead(); } 98 99 // Number of bytes available for read. readableSerialInput100 static inline uint8_t readable() { return SerialPort::rx_ready(); } 101 102 // A byte, or -1 if reading failed. NonBlockingReadSerialInput103 static inline int16_t NonBlockingRead() { return readable() ? Read() : -1; } 104 105 // No check for ready state. ImmediateReadSerialInput106 static inline Value ImmediateRead() { return SerialPort::data(); } 107 108 // Called in data reception interrupt. ReceivedSerialInput109 static inline void Received() { 110 if (!readable()) { 111 return; 112 } 113 // This will discard data if the buffer is full. 114 RingBuffer<SerialInput<SerialPort> >::NonBlockingWrite(ImmediateRead()); 115 } 116 }; 117 118 template<typename SerialPort> 119 struct SerialOutput : public Output { 120 enum { 121 buffer_size = SerialPort::output_buffer_size, 122 data_size = 8 123 }; 124 typedef uint8_t Value; 125 126 // Blocking! WriteSerialOutput127 static inline void Write(Value v) { while (!writable()); Overwrite(v); } 128 129 // Number of bytes that can be fed. writableSerialOutput130 static inline uint8_t writable() { return SerialPort::tx_ready(); } 131 132 // 1 if success. NonBlockingWriteSerialOutput133 static inline uint8_t NonBlockingWrite(Value v) { 134 if (!writable()) { 135 return 0; 136 } 137 Overwrite(v); 138 return 1; 139 } 140 141 // No check for ready state. OverwriteSerialOutput142 static inline void Overwrite(Value v) { SerialPort::set_data(v); } 143 144 // Called in data emission interrupt. RequestedSerialOutput145 static inline Value Requested() { 146 Value v = RingBuffer<SerialOutput<SerialPort> >::NonBlockingRead(); 147 if (v >= 0) { 148 Overwrite(v); 149 } 150 } 151 }; 152 153 template<typename SerialPort, PortMode input = POLLED, PortMode output = POLLED> 154 struct SerialImplementation { }; 155 156 template<typename SerialPort> 157 struct SerialImplementation<SerialPort, DISABLED, DISABLED> { 158 typedef InputOutput<DisabledInput, DisabledOutput> IO; 159 }; 160 template<typename SerialPort> 161 struct SerialImplementation<SerialPort, DISABLED, POLLED> { 162 typedef InputOutput<DisabledInput, SerialOutput<SerialPort> > IO; 163 }; 164 template<typename SerialPort> 165 struct SerialImplementation<SerialPort, DISABLED, BUFFERED> { 166 typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer; 167 typedef InputOutput<DisabledInput, OutputBuffer > IO; 168 }; 169 template<typename SerialPort> 170 struct SerialImplementation<SerialPort, POLLED, DISABLED> { 171 typedef InputOutput<SerialInput<SerialPort>, DisabledOutput> IO; 172 }; 173 template<typename SerialPort> 174 struct SerialImplementation<SerialPort, POLLED, POLLED> { 175 typedef InputOutput<SerialInput<SerialPort>, SerialOutput<SerialPort> > IO; 176 }; 177 template<typename SerialPort> 178 struct SerialImplementation<SerialPort, POLLED, BUFFERED> { 179 typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer; 180 typedef InputOutput<SerialInput<SerialPort>, OutputBuffer> IO; 181 }; 182 template<typename SerialPort> 183 struct SerialImplementation<SerialPort, BUFFERED, DISABLED> { 184 typedef RingBuffer<SerialInput<SerialPort> > InputBuffer; 185 typedef InputOutput<InputBuffer, DisabledOutput> IO; 186 }; 187 template<typename SerialPort> 188 struct SerialImplementation<SerialPort, BUFFERED, POLLED> { 189 typedef RingBuffer<SerialInput<SerialPort> > InputBuffer; 190 typedef InputOutput<InputBuffer, SerialOutput<SerialPort> > IO; 191 }; 192 template<typename SerialPort> 193 struct SerialImplementation<SerialPort, BUFFERED, BUFFERED> { 194 typedef RingBuffer<SerialInput<SerialPort> > InputBuffer; 195 typedef RingBuffer<SerialOutput<SerialPort> > OutputBuffer; 196 typedef InputOutput<InputBuffer, OutputBuffer> IO; 197 }; 198 199 template<typename SerialPort, uint32_t baud_rate, PortMode input = POLLED, 200 PortMode output = POLLED, bool turbo = false> 201 struct Serial { 202 typedef SerialImplementation<SerialPort, input, output> Impl; 203 typedef uint8_t Value; 204 typedef typename Impl::IO::Input Input; 205 typedef typename Impl::IO::Output Output; 206 static inline void Init() { 207 Init<baud_rate>(); 208 } 209 template<uint32_t new_baud_rate> 210 static inline void Init() { 211 if (turbo) { 212 SerialPort::Turbo::set(); 213 uint16_t prescaler = F_CPU / (8L * baud_rate) - 1; 214 SerialPort::set_prescaler(prescaler); 215 } else { 216 SerialPort::Turbo::clear(); 217 uint16_t prescaler = F_CPU / (16 * baud_rate) - 1; 218 SerialPort::set_prescaler(prescaler); 219 } 220 if (output != DISABLED) { 221 SerialPort::Tx::set(); 222 } 223 if (input != DISABLED) { 224 SerialPort::Rx::set(); 225 } 226 if (input == BUFFERED) { 227 SerialPort::RxInterrupt::set(); 228 } 229 } 230 231 static inline void Disable() { 232 SerialPort::Tx::clear(); 233 SerialPort::Rx::clear(); 234 SerialPort::RxInterrupt::clear(); 235 } 236 237 static inline void Write(Value v) { Impl::IO::Write(v); } 238 static inline uint8_t writable() { return Impl::IO::writable(); } 239 static inline uint8_t NonBlockingWrite(Value v) { 240 return Impl::IO::NonBlockingWrite(v); 241 } 242 static inline void Overwrite(Value v) { Impl::IO::Overwrite(v); } 243 static inline Value Read() { return Impl::IO::Read(); } 244 static inline uint8_t readable() { return Impl::IO::readable(); } 245 static inline int16_t NonBlockingRead() { 246 return Impl::IO::NonBlockingRead(); 247 } 248 static inline Value ImmediateRead() { return Impl::IO::ImmediateRead(); } 249 }; 250 251 252 #ifdef HAS_USART0 253 254 IORegister(UBRR0H); 255 IORegister(UBRR0L); 256 IORegister16(UBRR0); 257 IORegister(UCSR0A); 258 IORegister(UCSR0B); 259 IORegister(UCSR0C); 260 IORegister(UDR0); 261 262 typedef SerialPort< 263 BitInRegister<UCSR0BRegister, TXEN0>, 264 BitInRegister<UCSR0ARegister, UDRE0>, 265 BitInRegister<UCSR0BRegister, RXEN0>, 266 BitInRegister<UCSR0ARegister, RXC0>, 267 BitInRegister<UCSR0BRegister, RXCIE0>, 268 BitInRegister<UCSR0ARegister, U2X0>, 269 UBRR0HRegister, 270 UBRR0LRegister, 271 UDR0Register, 272 kSerialOutputBufferSize, 273 kSerialInputBufferSize> SerialPort0; 274 275 #endif // #ifdef HAS_USART0 276 277 278 #ifdef HAS_USART1 279 280 IORegister(UBRR1H); 281 IORegister(UBRR1L); 282 IORegister16(UBRR1); 283 IORegister(UCSR1A); 284 IORegister(UCSR1B); 285 IORegister(UCSR1C); 286 IORegister(UDR1); 287 288 typedef SerialPort< 289 BitInRegister<UCSR1BRegister, TXEN1>, 290 BitInRegister<UCSR1ARegister, UDRE1>, 291 BitInRegister<UCSR1BRegister, RXEN1>, 292 BitInRegister<UCSR1ARegister, RXC1>, 293 BitInRegister<UCSR1BRegister, RXCIE1>, 294 BitInRegister<UCSR1ARegister, U2X1>, 295 UBRR1HRegister, 296 UBRR1LRegister, 297 UDR1Register, 298 kSerialOutputBufferSize, 299 kSerialInputBufferSize> SerialPort1; 300 301 #endif // #ifdef HAS_USART1 302 303 304 #ifdef HAS_USART2 305 306 IORegister(UBRR2H); 307 IORegister(UBRR2L); 308 IORegister16(UBRR2); 309 IORegister(UCSR2A); 310 IORegister(UCSR2B); 311 IORegister(UCSR2C); 312 IORegister(UDR2); 313 314 typedef SerialPort< 315 BitInRegister<UCSR2BRegister, TXEN2>, 316 BitInRegister<UCSR2ARegister, UDRE2>, 317 BitInRegister<UCSR2BRegister, RXEN2>, 318 BitInRegister<UCSR2ARegister, RXC2>, 319 BitInRegister<UCSR2BRegister, RXCIE2>, 320 BitInRegister<UCSR2ARegister, U2X2>, 321 UBRR2HRegister, 322 UBRR2LRegister, 323 UDR2Register, 324 kSerialOutputBufferSize, 325 kSerialInputBufferSize> SerialPort2; 326 327 #endif // #ifdef HAS_USART2 328 329 #ifdef HAS_USART3 330 331 IORegister(UBRR3H); 332 IORegister(UBRR3L); 333 IORegister16(UBRR3); 334 IORegister(UCSR3A); 335 IORegister(UCSR3B); 336 IORegister(UCSR3C); 337 IORegister(UDR3); 338 339 typedef SerialPort< 340 BitInRegister<UCSR3BRegister, TXEN3>, 341 BitInRegister<UCSR3ARegister, UDRE3>, 342 BitInRegister<UCSR3BRegister, RXEN3>, 343 BitInRegister<UCSR3ARegister, RXC3>, 344 BitInRegister<UCSR3BRegister, RXCIE3>, 345 BitInRegister<UCSR3ARegister, U2X3>, 346 UBRR3HRegister, 347 UBRR3LRegister, 348 UDR3Register, 349 kSerialOutputBufferSize, 350 kSerialInputBufferSize> SerialPort3; 351 352 #endif // #ifdef HAS_USART3 353 354 } // namespace avrlib 355 356 357 #endif // AVRLIB_SERIAL_H_ 358