Main Code

Dependencies:   DRV8833 PidControllerV3 mbed Buffer

Fork of ApexPID by James Batchelar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BufferedSerial.cpp Source File

BufferedSerial.cpp

Go to the documentation of this file.
00001 /**
00002  * @file    BufferedSerial.cpp
00003  * @brief   Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
00004  * @author  sam grove
00005  * @version 1.0
00006  * @see
00007  *
00008  * Copyright (c) 2013
00009  *
00010  * Licensed under the Apache License, Version 2.0 (the "License");
00011  * you may not use this file except in compliance with the License.
00012  * You may obtain a copy of the License at
00013  *
00014  *     http://www.apache.org/licenses/LICENSE-2.0
00015  *
00016  * Unless required by applicable law or agreed to in writing, software
00017  * distributed under the License is distributed on an "AS IS" BASIS,
00018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00019  * See the License for the specific language governing permissions and
00020  * limitations under the License.
00021  */
00022 
00023 #include "BufferedSerial.h"
00024 #include <stdarg.h>
00025 
00026 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name)
00027     : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size))
00028 {
00029     RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
00030     this->_buf_size = buf_size;
00031     this->_tx_multiple = tx_multiple;   
00032     newlines = 0;
00033     return;
00034 }
00035 
00036 BufferedSerial::~BufferedSerial(void)
00037 {
00038     RawSerial::attach(NULL, RawSerial::RxIrq);
00039     RawSerial::attach(NULL, RawSerial::TxIrq);
00040 
00041     return;
00042 }
00043 
00044 int BufferedSerial::readable(void)
00045 {
00046     return _rxbuf.available();  // note: look if things are in the buffer
00047 }
00048 
00049 int BufferedSerial::writeable(void)
00050 {
00051     return 1;   // buffer allows overwriting by design, always true
00052 }
00053 
00054 int BufferedSerial::getc(void)
00055 {
00056     return _rxbuf;
00057 }
00058 
00059 void BufferedSerial::readLine(char *s)
00060 {
00061     while(! canReadLine());
00062     int i = 0;
00063     while ((s[i]=(char)getc()) != '\n') {
00064         i++;
00065     }
00066     newlines --;
00067     i++;
00068     s[i] = '\0';
00069 }
00070 
00071 
00072 int BufferedSerial::putc(int c)
00073 {
00074     _txbuf = (char)c;
00075     BufferedSerial::prime();
00076 
00077     return c;
00078 }
00079 
00080 int BufferedSerial::puts(const char *s)
00081 {
00082     if (s != NULL) {
00083         const char* ptr = s;
00084     
00085         while(*(ptr) != 0) {
00086             _txbuf = *(ptr++);
00087         }
00088         _txbuf = '\n';  // done per puts definition
00089         BufferedSerial::prime();
00090     
00091         return (ptr - s) + 1;
00092     }
00093     return 0;
00094 }
00095 
00096 int BufferedSerial::printf(const char* format, ...)
00097 {
00098     char buffer[this->_buf_size];
00099     memset(buffer,0,this->_buf_size);
00100     int r = 0;
00101 
00102     va_list arg;
00103     va_start(arg, format);
00104     r = vsprintf(buffer, format, arg);
00105     // this may not hit the heap but should alert the user anyways
00106     if(r > this->_buf_size) {
00107         error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r);
00108         va_end(arg);
00109         return 0;
00110     }
00111     va_end(arg);
00112     r = BufferedSerial::write(buffer, r);
00113 
00114     return r;
00115 }
00116 
00117 ssize_t BufferedSerial::write(const void *s, size_t length)
00118 {
00119     if (s != NULL && length > 0) {
00120         const char* ptr = (const char*)s;
00121         const char* end = ptr + length;
00122     
00123         while (ptr != end) {
00124             _txbuf = *(ptr++);
00125         }
00126         BufferedSerial::prime();
00127     
00128         return ptr - (const char*)s;
00129     }
00130     return 0;
00131 }
00132 
00133 
00134 void BufferedSerial::rxIrq(void)
00135 {
00136     // read from the peripheral and make sure something is available
00137     if(serial_readable(&_serial)) {
00138         char c = serial_getc(&_serial); // if so load them into a buffer
00139         _rxbuf = c;
00140         if (c == '\n') newlines ++;
00141     }
00142     return;
00143 }
00144 
00145 void BufferedSerial::txIrq(void)
00146 {
00147     // see if there is room in the hardware fifo and if something is in the software fifo
00148     while(serial_writable(&_serial)) {
00149         if(_txbuf.available()) {
00150             serial_putc(&_serial, (int)_txbuf.get());
00151         } else {
00152             // disable the TX interrupt when there is nothing left to send
00153             RawSerial::attach(NULL, RawSerial::TxIrq);
00154             break;
00155         }
00156     }
00157 
00158     return;
00159 }
00160 
00161 void BufferedSerial::prime(void)
00162 {
00163     // if already busy then the irq will pick this up
00164     if(serial_writable(&_serial)) {
00165         RawSerial::attach(NULL, RawSerial::TxIrq);    // make sure not to cause contention in the irq
00166         BufferedSerial::txIrq();                // only write to hardware in one place
00167         RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
00168     }
00169 
00170     return;
00171 }
00172 
00173