Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "FastSerial.h"
00034 #include "WProgram.h"
00035
00036 #if defined(UDR3)
00037 # define FS_MAX_PORTS 4
00038 #elif defined(UDR2)
00039 # define FS_MAX_PORTS 3
00040 #elif defined(UDR1)
00041 # define FS_MAX_PORTS 2
00042 #else
00043 # define FS_MAX_PORTS 1
00044 #endif
00045
00046 FastSerial::Buffer __FastSerial__rxBuffer[FS_MAX_PORTS];
00047 FastSerial::Buffer __FastSerial__txBuffer[FS_MAX_PORTS];
00048
00049
00050 #define RX_BUFFER_SIZE 128
00051 #define TX_BUFFER_SIZE 64
00052 #define BUFFER_MAX 512
00053
00054
00055
00056 FastSerial::FastSerial(const uint8_t portNumber,
00057 volatile uint8_t *ubrrh,
00058 volatile uint8_t *ubrrl,
00059 volatile uint8_t *ucsra,
00060 volatile uint8_t *ucsrb,
00061 const uint8_t u2x,
00062 const uint8_t portEnableBits,
00063 const uint8_t portTxBits)
00064 {
00065 _ubrrh = ubrrh;
00066 _ubrrl = ubrrl;
00067 _ucsra = ucsra;
00068 _ucsrb = ucsrb;
00069 _u2x = u2x;
00070 _portEnableBits = portEnableBits;
00071 _portTxBits = portTxBits;
00072
00073
00074 _rxBuffer = &__FastSerial__rxBuffer[portNumber];
00075 _txBuffer->head = _txBuffer->tail = 0;
00076 _txBuffer = &__FastSerial__txBuffer[portNumber];
00077 _rxBuffer->head = _rxBuffer->tail = 0;
00078 }
00079
00080
00081
00082 void FastSerial::begin(long baud)
00083 {
00084 unsigned int rxb, txb;
00085
00086
00087
00088 if (_open) {
00089 rxb = _rxBuffer->mask + 1;
00090 txb = _txBuffer->mask + 1;
00091 } else {
00092 rxb = RX_BUFFER_SIZE;
00093 txb = TX_BUFFER_SIZE;
00094 }
00095
00096 begin(baud, RX_BUFFER_SIZE, TX_BUFFER_SIZE);
00097 }
00098
00099 void FastSerial::begin(long baud, unsigned int rxSpace, unsigned int txSpace)
00100 {
00101 uint16_t ubrr;
00102 bool use_u2x = false;
00103 int ureg, u2;
00104 long breg, b2, dreg, d2;
00105
00106
00107 if (_open)
00108 end();
00109
00110
00111 if (!_allocBuffer(_rxBuffer, rxSpace ? : RX_BUFFER_SIZE) ||
00112 !_allocBuffer(_txBuffer, txSpace ? : TX_BUFFER_SIZE)) {
00113 end();
00114 return;
00115 }
00116 _open = true;
00117
00118
00119 if (baud > F_CPU / 16) {
00120 use_u2x = true;
00121 ubrr = F_CPU / (8 * baud) - 1;
00122 } else {
00123
00124
00125
00126
00127 ureg = F_CPU / 16 / baud - 1;
00128 breg = F_CPU / 16 / (ureg + 1);
00129 dreg = abs(baud - breg);
00130
00131
00132 u2 = F_CPU / 8 / baud - 1;
00133 b2 = F_CPU / 8 / (u2 + 1);
00134 d2 = abs(baud - b2);
00135
00136
00137
00138
00139 if (dreg <= d2) {
00140 ubrr = ureg;
00141 } else {
00142 ubrr = u2;
00143 use_u2x = true;
00144 }
00145 }
00146
00147 *_ucsra = use_u2x ? _BV(_u2x) : 0;
00148 *_ubrrh = ubrr >> 8;
00149 *_ubrrl = ubrr;
00150 *_ucsrb |= _portEnableBits;
00151 }
00152
00153 void FastSerial::end()
00154 {
00155 *_ucsrb &= ~(_portEnableBits | _portTxBits);
00156
00157 _freeBuffer(_rxBuffer);
00158 _freeBuffer(_txBuffer);
00159 _open = false;
00160 }
00161
00162 int
00163 FastSerial::available(void)
00164 {
00165 if (!_open)
00166 return(-1);
00167 return((_rxBuffer->head - _rxBuffer->tail) & _rxBuffer->mask);
00168 }
00169
00170 int
00171 FastSerial::read(void)
00172 {
00173 uint8_t c;
00174
00175
00176 if (!_open || (_rxBuffer->head == _rxBuffer->tail))
00177 return(-1);
00178
00179
00180 c = _rxBuffer->bytes[_rxBuffer->tail];
00181 _rxBuffer->tail = (_rxBuffer->tail + 1) & _rxBuffer->mask;
00182
00183 return(c);
00184 }
00185
00186 int
00187 FastSerial::peek(void)
00188 {
00189
00190
00191 if (!_open || (_rxBuffer->head == _rxBuffer->tail))
00192 return(-1);
00193
00194
00195 return(_rxBuffer->bytes[_rxBuffer->tail]);
00196 }
00197
00198
00199 void
00200 FastSerial::flush(void)
00201 {
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 _rxBuffer->head = _rxBuffer->tail;
00212
00213
00214
00215
00216 _txBuffer->tail = _rxBuffer->head;
00217 }
00218
00219 void
00220 FastSerial::write(uint8_t c)
00221 {
00222 int16_t i;
00223
00224 if (!_open)
00225 return;
00226
00227
00228 i = (_txBuffer->head + 1) & _txBuffer->mask;
00229 while (i == _txBuffer->tail)
00230 ;
00231
00232
00233 _txBuffer->bytes[_txBuffer->head] = c;
00234 _txBuffer->head = i;
00235
00236
00237 *_ucsrb |= _portTxBits;
00238 }
00239
00240
00241
00242 bool
00243 FastSerial::_allocBuffer(Buffer *buffer, unsigned int size)
00244 {
00245 uint8_t shift;
00246
00247
00248 buffer->head = buffer->tail = 0;
00249
00250
00251
00252
00253
00254 for (shift = 1; (1U << shift) < min(BUFFER_MAX, size); shift++)
00255 ;
00256 buffer->mask = (1 << shift) - 1;
00257
00258
00259 buffer->bytes = (uint8_t *)malloc(buffer->mask + 1);
00260
00261 return(buffer->bytes != NULL);
00262 }
00263
00264 void
00265 FastSerial::_freeBuffer(Buffer *buffer)
00266 {
00267 buffer->head = buffer->tail = 0;
00268 buffer->mask = 0;
00269 if (NULL != buffer->bytes) {
00270 free(buffer->bytes);
00271 buffer->bytes = NULL;
00272 }
00273 }
00274