Vergil Cola
/
MQTTGateway2
Fork of my original MQTTGateway
Embed:
(wiki syntax)
Show/hide line numbers
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 extern "C" int BufferedPrintfC(void *stream, int size, const char* format, va_list arg); 00027 00028 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) 00029 : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) 00030 { 00031 RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); 00032 this->_buf_size = buf_size; 00033 this->_tx_multiple = tx_multiple; 00034 return; 00035 } 00036 00037 BufferedSerial::~BufferedSerial(void) 00038 { 00039 RawSerial::attach(NULL, RawSerial::RxIrq); 00040 RawSerial::attach(NULL, RawSerial::TxIrq); 00041 00042 return; 00043 } 00044 00045 int BufferedSerial::readable(void) 00046 { 00047 return _rxbuf.available(); // note: look if things are in the buffer 00048 } 00049 00050 int BufferedSerial::writeable(void) 00051 { 00052 return 1; // buffer allows overwriting by design, always true 00053 } 00054 00055 int BufferedSerial::getc(void) 00056 { 00057 return _rxbuf; 00058 } 00059 00060 int BufferedSerial::putc(int c) 00061 { 00062 _txbuf = (char)c; 00063 BufferedSerial::prime(); 00064 00065 return c; 00066 } 00067 00068 int BufferedSerial::puts(const char *s) 00069 { 00070 if (s != NULL) { 00071 const char* ptr = s; 00072 00073 while(*(ptr) != 0) { 00074 _txbuf = *(ptr++); 00075 } 00076 _txbuf = '\n'; // done per puts definition 00077 BufferedSerial::prime(); 00078 00079 return (ptr - s) + 1; 00080 } 00081 return 0; 00082 } 00083 00084 extern "C" size_t BufferedSerialThunk(void *buf_serial, const void *s, size_t length) 00085 { 00086 BufferedSerial *buffered_serial = (BufferedSerial *)buf_serial; 00087 return buffered_serial->write(s, length); 00088 } 00089 00090 int BufferedSerial::printf(const char* format, ...) 00091 { 00092 va_list arg; 00093 va_start(arg, format); 00094 int r = BufferedPrintfC((void*)this, this->_buf_size, format, arg); 00095 va_end(arg); 00096 return r; 00097 } 00098 00099 ssize_t BufferedSerial::write(const void *s, size_t length) 00100 { 00101 if (s != NULL && length > 0) { 00102 const char* ptr = (const char*)s; 00103 const char* end = ptr + length; 00104 00105 while (ptr != end) { 00106 _txbuf = *(ptr++); 00107 } 00108 BufferedSerial::prime(); 00109 00110 return ptr - (const char*)s; 00111 } 00112 return 0; 00113 } 00114 00115 00116 void BufferedSerial::rxIrq(void) 00117 { 00118 // read from the peripheral and make sure something is available 00119 if(serial_readable(&_serial)) { 00120 _rxbuf = serial_getc(&_serial); // if so load them into a buffer 00121 // trigger callback if necessary 00122 if (_cbs[RxIrq]) { 00123 _cbs[RxIrq](); 00124 } 00125 } 00126 00127 return; 00128 } 00129 00130 void BufferedSerial::txIrq(void) 00131 { 00132 // see if there is room in the hardware fifo and if something is in the software fifo 00133 while(serial_writable(&_serial)) { 00134 if(_txbuf.available()) { 00135 serial_putc(&_serial, (int)_txbuf.get()); 00136 } else { 00137 // disable the TX interrupt when there is nothing left to send 00138 RawSerial::attach(NULL, RawSerial::TxIrq); 00139 // trigger callback if necessary 00140 if (_cbs[TxIrq]) { 00141 _cbs[TxIrq](); 00142 } 00143 break; 00144 } 00145 } 00146 00147 return; 00148 } 00149 00150 void BufferedSerial::prime(void) 00151 { 00152 // if already busy then the irq will pick this up 00153 if(serial_writable(&_serial)) { 00154 RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq 00155 BufferedSerial::txIrq(); // only write to hardware in one place 00156 RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq); 00157 } 00158 00159 return; 00160 } 00161 00162 void BufferedSerial::attach(Callback<void()> func, IrqType type) 00163 { 00164 _cbs[type] = func; 00165 } 00166
Generated on Tue Jul 12 2022 18:06:45 by 1.7.2