xyControl  0.1
Quadrotor Flight Controller on AVR Basis
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Groups
serial.c
Go to the documentation of this file.
1 /*
2  * serial.c
3  *
4  * Copyright (c) 2012, 2013, Thomas Buck <xythobuz@me.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * - Redistributions of source code must retain the above copyright notice,
12  * this list of conditions and the following disclaimer.
13  *
14  * - Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include <avr/io.h>
31 #include <avr/interrupt.h>
32 #include <stdint.h>
33 
34 #include "serial.h"
35 #include "serial_device.h"
36 #include "config.h"
37 
52 // #define SERIALINJECTCR
53 
54 #ifndef RX_BUFFER_SIZE
55 #define RX_BUFFER_SIZE 32
56 #endif
57 
58 #ifndef TX_BUFFER_SIZE
59 #define TX_BUFFER_SIZE 16
60 #endif
61 
63 #define FLOWCONTROL
64 
65 #define FLOWMARK 5
66 #define XON 0x11
67 #define XOFF 0x13
69 #if (RX_BUFFER_SIZE < 2) || (TX_BUFFER_SIZE < 2)
70 #error SERIAL BUFFER TOO SMALL!
71 #endif
72 
73 #ifdef FLOWCONTROL
74 #if (RX_BUFFER_SIZE < 8) || (TX_BUFFER_SIZE < 8)
75 #error SERIAL BUFFER TOO SMALL!
76 #endif
77 #endif
78 
79 #if ((RX_BUFFER_SIZE + TX_BUFFER_SIZE) * UART_COUNT) >= (RAMEND - 0x60)
80 #error SERIAL BUFFER TOO LARGE!
81 #endif
82 
83 // serialRegisters
84 #define SERIALDATA 0
85 #define SERIALB 1
86 #define SERIALC 2
87 #define SERIALA 3
88 #define SERIALUBRRH 4
89 #define SERIALUBRRL 5
90 
91 // serialBits
92 #define SERIALUCSZ0 0
93 #define SERIALUCSZ1 1
94 #define SERIALRXCIE 2
95 #define SERIALRXEN 3
96 #define SERIALTXEN 4
97 #define SERIALUDRIE 5
98 #define SERIALUDRE 6
99 
100 uint8_t volatile rxBuffer[UART_COUNT][RX_BUFFER_SIZE];
101 uint8_t volatile txBuffer[UART_COUNT][TX_BUFFER_SIZE];
102 uint16_t volatile rxRead[UART_COUNT];
103 uint16_t volatile rxWrite[UART_COUNT];
104 uint16_t volatile txRead[UART_COUNT];
105 uint16_t volatile txWrite[UART_COUNT];
106 uint8_t volatile shouldStartTransmission[UART_COUNT];
107 
108 #ifdef FLOWCONTROL
109 uint8_t volatile sendThisNext[UART_COUNT];
110 uint8_t volatile flow[UART_COUNT];
111 uint8_t volatile rxBufferElements[UART_COUNT];
112 #endif
113 
114 uint8_t serialAvailable(void) {
115  return UART_COUNT;
116 }
117 
118 void serialInit(uint8_t uart, uint16_t baud) {
119  if (uart >= UART_COUNT)
120  return;
121 
122  // Initialize state variables
123  rxRead[uart] = 0;
124  rxWrite[uart] = 0;
125  txRead[uart] = 0;
126  txWrite[uart] = 0;
127  shouldStartTransmission[uart] = 1;
128 #ifdef FLOWCONTROL
129  sendThisNext[uart] = 0;
130  flow[uart] = 1;
131  rxBufferElements[uart] = 0;
132 #endif
133 
134  // Default Configuration: 8N1
135  *serialRegisters[uart][SERIALC] = (1 << serialBits[uart][SERIALUCSZ0]) | (1 << serialBits[uart][SERIALUCSZ1]);
136 
137  // Set baudrate
138 #if SERIALBAUDBIT == 8
139  *serialRegisters[uart][SERIALUBRRH] = (baud >> 8);
140  *serialRegisters[uart][SERIALUBRRL] = baud;
141 #else
142  *serialBaudRegisters[uart] = baud;
143 #endif
144 
145  *serialRegisters[uart][SERIALB] = (1 << serialBits[uart][SERIALRXCIE]); // Enable Interrupts
146  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALRXEN]) | (1 << serialBits[uart][SERIALTXEN]); // Enable Receiver/Transmitter
147 }
148 
149 void serialClose(uint8_t uart) {
150  if (uart >= UART_COUNT)
151  return;
152 
153  uint8_t sreg = SREG;
154  sei();
155  while (!serialTxBufferEmpty(uart));
156  while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE])); // Wait while Transmit Interrupt is on
157  cli();
158  *serialRegisters[uart][SERIALB] = 0;
159  *serialRegisters[uart][SERIALC] = 0;
160  SREG = sreg;
161 }
162 
163 #ifdef FLOWCONTROL
164 void setFlow(uint8_t uart, uint8_t on) {
165  if (uart >= UART_COUNT)
166  return;
167 
168  if (flow[uart] != on) {
169  if (on == 1) {
170  // Send XON
171  while (sendThisNext[uart] != 0);
172  sendThisNext[uart] = XON;
173  flow[uart] = 1;
174  if (shouldStartTransmission[uart]) {
175  shouldStartTransmission[uart] = 0;
176  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
177  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
178  }
179  } else {
180  // Send XOFF
181  sendThisNext[uart] = XOFF;
182  flow[uart] = 0;
183  if (shouldStartTransmission[uart]) {
184  shouldStartTransmission[uart] = 0;
185  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]);
186  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
187  }
188  }
189  // Wait till it's transmitted
190  while (*serialRegisters[uart][SERIALB] & (1 << serialBits[uart][SERIALUDRIE]));
191  }
192 }
193 #endif
194 
195 // ---------------------
196 // | Reception |
197 // ---------------------
198 
199 uint8_t serialHasChar(uint8_t uart) {
200  if (uart >= UART_COUNT)
201  return 0;
202 
203  if (rxRead[uart] != rxWrite[uart]) { // True if char available
204  return 1;
205  } else {
206  return 0;
207  }
208 }
209 
210 uint8_t serialGetBlocking(uint8_t uart) {
211  if (uart >= UART_COUNT)
212  return 0;
213 
214  while(!serialHasChar(uart));
215  return serialGet(uart);
216 }
217 
218 uint8_t serialGet(uint8_t uart) {
219  if (uart >= UART_COUNT)
220  return 0;
221 
222  uint8_t c;
223 
224 #ifdef FLOWCONTROL
225  rxBufferElements[uart]--;
226  if ((flow[uart] == 0) && (rxBufferElements[uart] <= FLOWMARK)) {
227  while (sendThisNext[uart] != 0);
228  sendThisNext[uart] = XON;
229  flow[uart] = 1;
230  if (shouldStartTransmission[uart]) {
231  shouldStartTransmission[uart] = 0;
232  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
233  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
234  }
235  }
236 #endif
237 
238  if (rxRead[uart] != rxWrite[uart]) {
239  c = rxBuffer[uart][rxRead[uart]];
240  rxBuffer[uart][rxRead[uart]] = 0;
241  if (rxRead[uart] < (RX_BUFFER_SIZE - 1)) {
242  rxRead[uart]++;
243  } else {
244  rxRead[uart] = 0;
245  }
246  return c;
247  } else {
248  return 0;
249  }
250 }
251 
252 uint8_t serialRxBufferFull(uint8_t uart) {
253  if (uart >= UART_COUNT)
254  return 0;
255 
256  return (((rxWrite[uart] + 1) == rxRead[uart]) || ((rxRead[uart] == 0) && ((rxWrite[uart] + 1) == RX_BUFFER_SIZE)));
257 }
258 
259 uint8_t serialRxBufferEmpty(uint8_t uart) {
260  if (uart >= UART_COUNT)
261  return 0;
262 
263  if (rxRead[uart] != rxWrite[uart]) {
264  return 0;
265  } else {
266  return 1;
267  }
268 }
269 
270 // ----------------------
271 // | Transmission |
272 // ----------------------
273 
274 void serialWrite(uint8_t uart, uint8_t data) {
275  if (uart >= UART_COUNT)
276  return;
277 
278 #ifdef SERIALINJECTCR
279  if (data == '\n') {
280  serialWrite(uart, '\r');
281  }
282 #endif
283  while (serialTxBufferFull(uart));
284 
285  txBuffer[uart][txWrite[uart]] = data;
286  if (txWrite[uart] < (TX_BUFFER_SIZE - 1)) {
287  txWrite[uart]++;
288  } else {
289  txWrite[uart] = 0;
290  }
291  if (shouldStartTransmission[uart]) {
292  shouldStartTransmission[uart] = 0;
293  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
294  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
295  }
296 }
297 
298 void serialWriteString(uint8_t uart, const char *data) {
299  if (uart >= UART_COUNT)
300  return;
301 
302  if (data == 0) {
303  serialWriteString(uart, "NULL");
304  } else {
305  while (*data != '\0') {
306  serialWrite(uart, *data++);
307  }
308  }
309 }
310 
311 uint8_t serialTxBufferFull(uint8_t uart) {
312  if (uart >= UART_COUNT)
313  return 0;
314 
315  return (((txWrite[uart] + 1) == txRead[uart]) || ((txRead[uart] == 0) && ((txWrite[uart] + 1) == TX_BUFFER_SIZE)));
316 }
317 
318 uint8_t serialTxBufferEmpty(uint8_t uart) {
319  if (uart >= UART_COUNT)
320  return 0;
321 
322  if (txRead[uart] != txWrite[uart]) {
323  return 0;
324  } else {
325  return 1;
326  }
327 }
328 
329 void serialReceiveInterrupt(uint8_t uart) {
330  rxBuffer[uart][rxWrite[uart]] = *serialRegisters[uart][SERIALDATA];
331  if (rxWrite[uart] < (RX_BUFFER_SIZE - 1)) {
332  rxWrite[uart]++;
333  } else {
334  rxWrite[uart] = 0;
335  }
336 
337 #ifdef FLOWCONTROL
338  rxBufferElements[uart]++;
339  if ((flow[uart] == 1) && (rxBufferElements[uart] >= (RX_BUFFER_SIZE - FLOWMARK))) {
340  sendThisNext[uart] = XOFF;
341  flow[uart] = 0;
342  if (shouldStartTransmission[uart]) {
343  shouldStartTransmission[uart] = 0;
344  *serialRegisters[uart][SERIALB] |= (1 << serialBits[uart][SERIALUDRIE]); // Enable Interrupt
345  *serialRegisters[uart][SERIALA] |= (1 << serialBits[uart][SERIALUDRE]); // Trigger Interrupt
346  }
347  }
348 #endif
349 }
350 
351 void serialTransmitInterrupt(uint8_t uart) {
352 #ifdef FLOWCONTROL
353  if (sendThisNext[uart]) {
354  *serialRegisters[uart][SERIALDATA] = sendThisNext[uart];
355  sendThisNext[uart] = 0;
356  } else {
357 #endif
358  if (txRead[uart] != txWrite[uart]) {
359  *serialRegisters[uart][SERIALDATA] = txBuffer[uart][txRead[uart]];
360  if (txRead[uart] < (TX_BUFFER_SIZE -1)) {
361  txRead[uart]++;
362  } else {
363  txRead[uart] = 0;
364  }
365  } else {
366  shouldStartTransmission[uart] = 1;
367  *serialRegisters[uart][SERIALB] &= ~(1 << serialBits[uart][SERIALUDRIE]); // Disable Interrupt
368  }
369 #ifdef FLOWCONTROL
370  }
371 #endif
372 }
373 
374 ISR(SERIALRECIEVEINTERRUPT) { // Receive complete
375  serialReceiveInterrupt(0);
376 }
377 
378 ISR(SERIALTRANSMITINTERRUPT) { // Data register empty
379  serialTransmitInterrupt(0);
380 }
381 
382 #if UART_COUNT > 1
383 ISR(SERIALRECIEVEINTERRUPT1) { // Receive complete
384  serialReceiveInterrupt(1);
385 }
386 
387 ISR(SERIALTRANSMITINTERRUPT1) { // Data register empty
388  serialTransmitInterrupt(1);
389 }
390 #endif
391 
392 #if UART_COUNT > 2
393 ISR(SERIALRECIEVEINTERRUPT2) { // Receive complete
394  serialReceiveInterrupt(2);
395 }
396 
397 ISR(SERIALTRANSMITINTERRUPT2) { // Data register empty
398  serialTransmitInterrupt(2);
399 }
400 #endif
401 
402 #if UART_COUNT > 3
403 ISR(SERIALRECIEVEINTERRUPT3) { // Receive complete
404  serialReceiveInterrupt(3);
405 }
406 
407 ISR(SERIALTRANSMITINTERRUPT3) { // Data register empty
408  serialTransmitInterrupt(3);
409 }
410 #endif
411