COSA
An Object-Oriented Platform for Arduino Programming
UART.cpp
Go to the documentation of this file.
1 
21 #include "Cosa/Board.hh"
22 #include "Cosa/UART.hh"
23 
24 #if defined(BOARD_ATTINY)
25 // Default is serial output only (UAT)
26 // static IOBuffer<Soft::UART::RX_BUFFER_MAX> ibuf;
27 // Soft::UART __attribute__ ((weak)) uart(Board::D2, Board::PCI1, &ibuf);
28 Soft::UAT __attribute__ ((weak)) uart(Board::D2);
29 #else
30 
31 #include <avr/power.h>
32 
33 #if defined(USBCON)
34 #undef uart
35 #else
36 #include "Cosa/IOBuffer.hh"
39 UART __attribute__ ((weak)) uart(0, &ibuf, &obuf);
40 #endif
41 
43 
44 bool
45 UART::begin(uint32_t baudrate, uint8_t format)
46 {
47  // Power up the device
48  powerup();
49 
50  // Check if double rate is not possible
51  uint16_t setting = ((F_CPU / 4 / baudrate) - 1) / 2;
52  if (setting > 4095) {
53  setting = ((F_CPU / 8 / baudrate) - 1) / 2;
54  *UCSRnA() = 0;
55  } else {
56  *UCSRnA() = _BV(U2X0);
57  }
58 
59  // Set baudrate and format
60  *UBRRn() = setting;
61  *UCSRnC() = format;
62 
63  // Enable receiver and transmitter interrupt
64  *UCSRnB() = (_BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0));
65  return (true);
66 }
67 
68 bool
70 {
71  // Flush an output
72  flush();
73 
74  // Disable receiver and transmitter interrupt
75  *UCSRnB() &= ~(_BV(RXCIE0) | _BV(RXEN0) | _BV(TXEN0));
76 
77  // Powerdown the device
78  powerdown();
79  return (true);
80 }
81 
82 // A fast track direct to the hardware pipeline is possible when it is
83 // idle. At 500 Kbps the effective baud-rate increases from 84% to
84 // 99.9%, 1 Mbps from 42% to 88%, and 2 Mbps from 21% to 88%. Does not
85 // effect lower baud-rates more than the pipeline is started faster.
86 #define USE_FAST_TRACK
87 
88 // A short delay improves synchronization with hardware pipeline at
89 // 1 Mbps. The effective baud-rate increases at 1 Mbps from 88% to
90 // 99.5% and at 2 Mbps from 88% to 90%. Note that the delay is tuned
91 // for program memory string write (at 1 Mbps).
92 #define USE_SYNC_DELAY
93 
94 int
96 {
97  // Flag that transitter is used
98  m_idle = false;
99 
100 #if defined(USE_FAST_TRACK)
101  // Fast track when transmitter is idle; put directly into the pipeline
102  if (((*UCSRnB() & _BV(UDRIE0)) == 0) && ((*UCSRnA() & _BV(UDRE0)) != 0)) {
103  synchronized {
104  *UDRn() = c;
105  *UCSRnA() |= _BV(TXC0);
106  }
107 #if defined(USE_SYNC_DELAY)
108  // A short delay to make things even faster; optimized for program
109  // memory string write (approx. 5 us)
110  if (UNLIKELY(*UBRRn() == 1)) {
111  _delay_loop_1(25);
112  nop();
113  nop();
114  }
115 #endif
116  return (c & 0xff);
117  }
118 #endif
119 
120  // Check if the buffer is full
121  while (m_obuf->putchar(c) == IOStream::EOF)
122  yield();
123 
124  // Enable the transmitter
125  *UCSRnB() |= _BV(UDRIE0);
126  return (c & 0xff);
127 }
128 
129 int
131 {
132  // Check for idle transmitter; nothing to flush
133  if (m_idle) return (0);
134 
135  // Wait for transmission to complete
136  while ((*UCSRnB() & _BV(UDRIE0)) != 0)
137  yield();
138 
139  // Wait for the last character to be transmitted
140  while ((*UCSRnA() & _BV(TXC0)) == 0)
141  ;
142  *UCSRnA() |= _BV(TXC0);
143 
144  // Mark as idle again
145  m_idle = true;
146  return (0);
147 }
148 
149 void
151 {
152  switch (m_port) {
153 #if defined(power_usart0_enable)
154  case 0:
155  power_usart0_enable();
156  break;
157 #endif
158 #if defined(power_usart1_enable)
159  case 1:
160  power_usart1_enable();
161  break;
162 #endif
163 #if defined(power_usart2_enable)
164  case 2:
165  power_usart2_enable();
166  break;
167 #endif
168 #if defined(power_usart3_enable)
169  case 3:
170  power_usart3_enable();
171  break;
172 #endif
173  default:
174  break;
175  }
176 }
177 
178 void
180 {
181  switch (m_port) {
182 #if defined(power_usart0_disable)
183  case 0:
184  power_usart0_disable();
185  break;
186 #endif
187 #if defined(power_usart1_disable)
188  case 1:
189  power_usart1_disable();
190  break;
191 #endif
192 #if defined(power_usart2_disable)
193  case 2:
194  power_usart2_disable();
195  break;
196 #endif
197 #if defined(power_usart3_disable)
198  case 3:
199  power_usart3_disable();
200  break;
201 #endif
202  default:
203  break;
204  }
205 }
206 
207 void
209 {
210  int c = m_obuf->getchar();
211  if (c != IOStream::EOF) {
212  *UDRn() = c;
213  *UCSRnA() |= _BV(TXC0);
214  }
215  else {
216  *UCSRnB() &= ~_BV(UDRIE0);
217  }
218 }
219 
220 void
222 {
223  m_ibuf->putchar(*UDRn());
224 }
225 
226 #define UART_ISR(vec,nr) \
227 ISR(vec ## _UDRE_vect) \
228 { \
229  if (UNLIKELY(UART::uart[nr] == NULL)) return; \
230  UART::uart[nr]->on_udre_interrupt(); \
231 } \
232  \
233 ISR(vec ## _RX_vect) \
234 { \
235  if (UNLIKELY(UART::uart[nr] == NULL)) return; \
236  UART::uart[nr]->on_rx_interrupt(); \
237 } \
238 
239 #if defined(USART_UDRE_vect)
240 UART_ISR(USART, 0)
241 #endif
242 #if defined(USART1_UDRE_vect)
243 UART_ISR(USART1, 1)
244 #endif
245 #if defined(USART2_UDRE_vect)
246 UART_ISR(USART2, 2)
247 #endif
248 #if defined(USART3_UDRE_vect)
249 UART_ISR(USART3, 3)
250 #endif
251 
252 #endif
253 
#define TXC0
Definition: Leonardo.hh:296
virtual int putchar(char c)
virtual int flush()
Definition: UART.cpp:130
IOStream::Device * m_obuf
Output Buffer/Device.
Definition: UART.hh:196
volatile uint8_t * UCSRnA() const
Definition: UART.hh:209
#define RXEN0
Definition: Leonardo.hh:298
volatile uint8_t * UCSRnC() const
Definition: UART.hh:227
#define NULL
Definition: Types.h:101
virtual void powerup()
Definition: UART.cpp:150
virtual void powerdown()
Definition: UART.cpp:179
#define U2X0
Definition: Leonardo.hh:295
UART uart(0,&ibuf,&obuf)
virtual bool begin(uint32_t baudrate=DEFAULT_BAUDRATE, uint8_t format=DEFAULT_FORMAT)
Definition: UART.cpp:45
bool m_idle
Flag idle mode.
Definition: UART.hh:197
virtual bool end()
Definition: UART.cpp:69
static UART * uart[Board::UART_MAX]
Definition: UART.hh:203
volatile uint16_t * UBRRn() const
Definition: UART.hh:236
virtual void on_udre_interrupt()
Definition: UART.cpp:208
#define nop()
Definition: Types.h:305
static IOBuffer< UART::TX_BUFFER_MAX > obuf
Definition: UART.cpp:38
IOStream::Device * m_ibuf
Input Buffer/Device.
Definition: UART.hh:195
#define UDRE0
Definition: Leonardo.hh:300
void(* yield)()
Definition: UART.hh:59
static const int EOF
Definition: IOStream.hh:33
#define RXCIE0
Definition: Leonardo.hh:297
virtual void on_rx_interrupt()
Definition: UART.cpp:221
#define UDRIE0
Definition: Leonardo.hh:301
virtual int getchar()
#define UART_ISR(vec, nr)
Definition: UART.cpp:226
static IOBuffer< UART::RX_BUFFER_MAX > ibuf
Definition: UART.cpp:37
#define UNLIKELY(x)
Definition: Types.h:153
uint8_t m_port
UART port index.
Definition: UART.hh:193
volatile uint8_t * UCSRnB() const
Definition: UART.hh:218
volatile uint8_t * UDRn() const
Definition: UART.hh:245
#define TXEN0
Definition: Leonardo.hh:299
virtual int putchar(char c)
Definition: UART.cpp:95