Serial Port
Arduino/libraries/SerialPort/SerialPort.cpp
Go to the documentation of this file.
00001 /* Arduino SerialPort Library
00002  * Copyright (C) 2011 by William Greiman
00003  *
00004  * This file is part of the Arduino SerialPort Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino SerialPort Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00024 #include <SerialPort.h>
00025 //------------------------------------------------------------------------------
00030 int SerialRingBuffer::available() {
00031   uint8_t s = SREG;
00032   cli();
00033   int n = head_ - tail_;
00034   SREG = s;
00035   return n < 0 ? size_ + n : n;
00036 }
00037 //------------------------------------------------------------------------------
00042 void SerialRingBuffer::flush() {
00043   uint8_t s = SREG;
00044   cli();
00045   head_ = tail_ = 0;
00046   SREG = s;
00047 }
00048 //------------------------------------------------------------------------------
00054 bool SerialRingBuffer::get(uint8_t* b) {
00055   buf_size_t t = tail_;
00056   if (head_ == t) return false;
00057   *b = buf_[t++];
00058   tail_ = t < size_ ? t : 0;
00059   return true;
00060 }
00061 //------------------------------------------------------------------------------
00072 SerialRingBuffer::buf_size_t SerialRingBuffer::get(uint8_t* b, buf_size_t n) {
00073   buf_size_t nr;
00074   cli();
00075   buf_size_t h = head_;
00076   sei();
00077   buf_size_t t = tail_;
00078   if (h < t) {
00079     nr = size_ - t;
00080   } else if (t < h) {
00081     nr = h - t;
00082   } else {
00083     return 0;
00084   }
00085   if (nr > n) nr = n;
00086   memcpy(b, &buf_[t], nr);
00087   t += nr;
00088   tail_ = t < size_ ? t : t - size_;
00089   return nr;
00090 }
00091 //------------------------------------------------------------------------------
00096 void SerialRingBuffer::init(uint8_t* b, buf_size_t s) {
00097   buf_ = b;
00098   size_ = s;
00099   head_ = tail_ = 0;
00100 }
00101 //------------------------------------------------------------------------------
00105 int SerialRingBuffer::peek() {
00106   return empty() ? -1 : buf_[tail_];
00107 }
00108 //------------------------------------------------------------------------------
00115 bool SerialRingBuffer::put(uint8_t b) {
00116   buf_size_t h = head_;
00117   // OK to store here even if ring is full.
00118   buf_[h++] = b;
00119   if (h >= size_) h = 0;
00120   if (h == tail_) return false;
00121   head_ = h;
00122   return true;
00123 }
00124 //------------------------------------------------------------------------------
00135 SerialRingBuffer::buf_size_t
00136   SerialRingBuffer::put(const uint8_t* b, buf_size_t n) {
00137   cli();
00138   buf_size_t t = tail_;
00139   sei();
00140   buf_size_t space;  // space in ring buffer
00141   buf_size_t h = head_;
00142   if (h < t) {
00143     space = t - h - 1;
00144   } else {
00145     space = size_ - h;
00146     if (t == 0) space -= 1;
00147   }
00148   if (n > space) n = space;
00149   memcpy(&buf_[h], b, n);
00150   h += n;
00151   head_ = h < size_ ? h : h - size_;
00152   return n;
00153 }
00154 //------------------------------------------------------------------------------
00165 SerialRingBuffer::buf_size_t SerialRingBuffer::put_P(PGM_P b, buf_size_t n) {
00166   cli();
00167   buf_size_t t = tail_;
00168   sei();
00169   buf_size_t space;  // space in ring buffer
00170   buf_size_t h = head_;
00171   if (h < t) {
00172     space = t - h - 1;
00173   } else {
00174     space = size_ - h;
00175     if (t == 0) space -= 1;
00176   }
00177   if (n > space) n = space;
00178   memcpy_P(&buf_[h], b, n);
00179   h += n;
00180   head_ = h < size_ ? h : h - size_;
00181   return n;
00182 }
00183 //==============================================================================
00184 // global data and ISRs
00185 #if ENABLE_RX_ERROR_CHECKING
00186 //
00187 uint8_t rxErrorBits[SERIAL_PORT_COUNT];
00188 #endif  // ENABLE_RX_ERROR_CHECKING
00189 //------------------------------------------------------------------------------
00190 #if BUFFERED_RX
00191 //------------------------------------------------------------------------------
00192 SerialRingBuffer rxRingBuf[SERIAL_PORT_COUNT];
00193 //------------------------------------------------------------------------------
00194 #if ENABLE_RX_ERROR_CHECKING
00195 inline static void rx_isr(uint8_t n) {
00196   uint8_t e = *usart[n].ucsra & SP_UCSRA_ERROR_MASK;
00197   uint8_t b = *usart[n].udr;
00198   if (!rxRingBuf[n].put(b)) e |= SP_RX_BUF_OVERRUN;
00199   rxErrorBits[n] |= e;
00200 }
00201 #else  // ENABLE_RX_ERROR_CHECKING
00202 inline static void rx_isr(uint8_t n) {
00203   uint8_t b = *usart[n].udr;
00204   rxRingBuf[n].put(b);
00205 }
00206 #endif  // ENABLE_RX_ERROR_CHECKING
00207 //------------------------------------------------------------------------------
00208 // SerialRingBuffer rxbuf0;
00209 #if defined(USART_RX_vect)
00210 ISR(USART_RX_vect) {
00211   rx_isr(0);
00212 }
00213 #elif defined(SIG_USART0_RECV)
00214 ISR(SIG_USART0_RECV) {
00215   rx_isr(0);
00216 }
00217 #elif defined(SIG_UART0_RECV)
00218 ISR(SIG_UART0_RECV) {
00219   rx_isr(0);
00220 }
00221 #elif defined(USART0_RX_vect)
00222 ISR(USART0_RX_vect) {
00223   rx_isr(0);
00224 }
00225 #elif defined(SIG_UART_RECV)
00226 ISR(SIG_UART_RECV) {
00227   rx_isr(0);
00228 }
00229 #endif  // vector USART0
00230 #ifdef USART1_RX_vect
00231 ISR(USART1_RX_vect) {
00232   rx_isr(1);
00233 }
00234 #endif  // USART1_RX_vect
00235 
00236 #ifdef USART2_RX_vect
00237 ISR(USART2_RX_vect) {
00238   rx_isr(2);
00239 }
00240 #endif  // USART2_RX_vect
00241 
00242 #ifdef USART3_RX_vect
00243 ISR(USART3_RX_vect) {
00244   rx_isr(3);
00245 }
00246 #endif  // USART3_RX_vect
00247 #endif  // BUFFERED_RX
00248 //------------------------------------------------------------------------------
00249 #if BUFFERED_TX
00250 //------------------------------------------------------------------------------
00251 SerialRingBuffer txRingBuf[SERIAL_PORT_COUNT];
00252 //------------------------------------------------------------------------------
00253 inline static void tx_isr(uint8_t n) {
00254   uint8_t b;
00255   if (txRingBuf[n].get(&b)) {
00256     *usart[n].udr = b;
00257   } else {
00258     // no data - disable interrupts
00259     *usart[n].ucsrb &= ~M_UDRIE;
00260   }
00261 }
00262 #if defined(UART0_UDRE_vect)
00263 ISR(UART0_UDRE_vect) {
00264   tx_isr(0);
00265 }
00266 #elif defined(UART_UDRE_vect)
00267 ISR(UART_UDRE_vect) {
00268   tx_isr(0);
00269 }
00270 #elif defined(USART0_UDRE_vect)
00271 ISR(USART0_UDRE_vect) {
00272   tx_isr(0);
00273 }
00274 #elif defined(USART_UDRE_vect)
00275 ISR(USART_UDRE_vect) {
00276   tx_isr(0);
00277 }
00278 #endif  // USART0 TX
00279 
00280 #ifdef USART1_UDRE_vect
00281 ISR(USART1_UDRE_vect) {
00282   tx_isr(1);
00283 }
00284 #endif  // USART1_UDRE_vect
00285 
00286 #ifdef USART2_UDRE_vect
00287 ISR(USART2_UDRE_vect) {
00288   tx_isr(2);
00289 }
00290 #endif  // USART2_UDRE_vect
00291 
00292 #ifdef USART3_UDRE_vect
00293 ISR(USART3_UDRE_vect) {
00294   tx_isr(3);
00295 }
00296 #endif  // USART3_UDRE_vect
00297 #endif  // BUFFERED_TX
 All Classes Files Functions Variables Typedefs Defines