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