Benjamin Hepp / BufferedSerial

Dependencies:   Buffer

Fork of BufferedSerial by Sam Grove

Committer:
bhepp
Date:
Mon Apr 04 11:19:49 2016 +0000
Revision:
14:2150f1edc9bc
Parent:
13:b4080afc8cd5
Fixed some issues.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 0:a977d0a3d81e 1 /**
bhepp 12:c7947d444267 2 * Adapted by Benjamin Hepp (benjamin.hepp@inf.ethz.ch) to include blocking when write-buffer is full.
bhepp 12:c7947d444267 3 *
sam_grove 0:a977d0a3d81e 4 * @file BufferedSerial.cpp
sam_grove 0:a977d0a3d81e 5 * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
sam_grove 0:a977d0a3d81e 6 * @author sam grove
sam_grove 0:a977d0a3d81e 7 * @version 1.0
sam_grove 4:2ba4d2e1f05d 8 * @see
sam_grove 0:a977d0a3d81e 9 *
sam_grove 0:a977d0a3d81e 10 * Copyright (c) 2013
sam_grove 0:a977d0a3d81e 11 *
sam_grove 0:a977d0a3d81e 12 * Licensed under the Apache License, Version 2.0 (the "License");
sam_grove 0:a977d0a3d81e 13 * you may not use this file except in compliance with the License.
sam_grove 0:a977d0a3d81e 14 * You may obtain a copy of the License at
sam_grove 0:a977d0a3d81e 15 *
sam_grove 0:a977d0a3d81e 16 * http://www.apache.org/licenses/LICENSE-2.0
sam_grove 0:a977d0a3d81e 17 *
sam_grove 0:a977d0a3d81e 18 * Unless required by applicable law or agreed to in writing, software
sam_grove 0:a977d0a3d81e 19 * distributed under the License is distributed on an "AS IS" BASIS,
sam_grove 0:a977d0a3d81e 20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sam_grove 0:a977d0a3d81e 21 * See the License for the specific language governing permissions and
sam_grove 0:a977d0a3d81e 22 * limitations under the License.
sam_grove 0:a977d0a3d81e 23 */
sam_grove 0:a977d0a3d81e 24
sam_grove 0:a977d0a3d81e 25 #include "BufferedSerial.h"
sam_grove 0:a977d0a3d81e 26 #include <stdarg.h>
sam_grove 0:a977d0a3d81e 27
bhepp 12:c7947d444267 28 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size)
bhepp 12:c7947d444267 29 : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf(buf_size), _buffered_bytes(0)
sam_grove 0:a977d0a3d81e 30 {
sam_grove 11:779304f9c5d2 31 RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
bhepp 14:2150f1edc9bc 32 RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
bhepp 14:2150f1edc9bc 33 this->_buf_size = buf_size - 1;
bhepp 12:c7947d444267 34 }
bhepp 12:c7947d444267 35
bhepp 12:c7947d444267 36 BufferedSerial::BufferedSerial(PinName tx, PinName rx, int baud_rate, uint32_t buf_size)
bhepp 12:c7947d444267 37 : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf(buf_size), _buffered_bytes(0)
bhepp 12:c7947d444267 38 {
bhepp 12:c7947d444267 39 baud(baud_rate);
bhepp 12:c7947d444267 40 RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
bhepp 14:2150f1edc9bc 41 RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
bhepp 14:2150f1edc9bc 42 this->_buf_size = buf_size - 1;
sam_grove 0:a977d0a3d81e 43 }
sam_grove 0:a977d0a3d81e 44
sam_grove 0:a977d0a3d81e 45 BufferedSerial::~BufferedSerial(void)
sam_grove 0:a977d0a3d81e 46 {
sam_grove 11:779304f9c5d2 47 RawSerial::attach(NULL, RawSerial::RxIrq);
sam_grove 11:779304f9c5d2 48 RawSerial::attach(NULL, RawSerial::TxIrq);
sam_grove 0:a977d0a3d81e 49 }
sam_grove 0:a977d0a3d81e 50
sam_grove 0:a977d0a3d81e 51 int BufferedSerial::readable(void)
sam_grove 0:a977d0a3d81e 52 {
sam_grove 0:a977d0a3d81e 53 return _rxbuf.available(); // note: look if things are in the buffer
sam_grove 0:a977d0a3d81e 54 }
sam_grove 0:a977d0a3d81e 55
sam_grove 0:a977d0a3d81e 56 int BufferedSerial::writeable(void)
sam_grove 0:a977d0a3d81e 57 {
bhepp 13:b4080afc8cd5 58 return _buffered_bytes < this->_buf_size;
sam_grove 0:a977d0a3d81e 59 }
sam_grove 0:a977d0a3d81e 60
sam_grove 0:a977d0a3d81e 61 int BufferedSerial::getc(void)
sam_grove 0:a977d0a3d81e 62 {
sam_grove 3:6b76fcf27545 63 return _rxbuf;
sam_grove 0:a977d0a3d81e 64 }
sam_grove 0:a977d0a3d81e 65
bhepp 14:2150f1edc9bc 66 // TODO
bhepp 14:2150f1edc9bc 67 //int BufferedSerial::putc(int c)
bhepp 14:2150f1edc9bc 68 //{
bhepp 14:2150f1edc9bc 69 // RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
bhepp 14:2150f1edc9bc 70 //
bhepp 14:2150f1edc9bc 71 // // Wait for free space in buffer
bhepp 14:2150f1edc9bc 72 //// __disable_irq();
bhepp 14:2150f1edc9bc 73 //// if (!RawSerial::writeable()) {
bhepp 14:2150f1edc9bc 74 //// blocking_printf("serial_writeable: %d\r\n", RawSerial::writeable());
bhepp 14:2150f1edc9bc 75 //// blocking_printf("putc(0x%x), buffered_bytes=%d\r\n", c, _buffered_bytes);
bhepp 14:2150f1edc9bc 76 //// }
bhepp 14:2150f1edc9bc 77 //
bhepp 14:2150f1edc9bc 78 // while (_buffered_bytes >= this->_buf_size) {
bhepp 14:2150f1edc9bc 79 //// prime();
bhepp 14:2150f1edc9bc 80 //// __enable_irq();
bhepp 14:2150f1edc9bc 81 // while (_buffered_bytes >= this->_buf_size) { }
bhepp 14:2150f1edc9bc 82 //// __disable_irq();
bhepp 14:2150f1edc9bc 83 // }
bhepp 14:2150f1edc9bc 84 //
bhepp 14:2150f1edc9bc 85 // _txbuf = (char)c;
bhepp 14:2150f1edc9bc 86 // ++_buffered_bytes;
bhepp 14:2150f1edc9bc 87 //
bhepp 14:2150f1edc9bc 88 // while (RawSerial::writeable() && _txbuf.available()) {
bhepp 14:2150f1edc9bc 89 // RawSerial::putc((int)_txbuf.get());
bhepp 14:2150f1edc9bc 90 // --_buffered_bytes;
bhepp 14:2150f1edc9bc 91 // }
bhepp 14:2150f1edc9bc 92 //
bhepp 14:2150f1edc9bc 93 //// txIrq();
bhepp 14:2150f1edc9bc 94 //// RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
bhepp 14:2150f1edc9bc 95 //
bhepp 14:2150f1edc9bc 96 //// while (_txbuf.available()) {
bhepp 14:2150f1edc9bc 97 //// while (!serial_writable(&_serial)) { }
bhepp 14:2150f1edc9bc 98 //// serial_putc(&_serial, (int)_txbuf.get());
bhepp 14:2150f1edc9bc 99 //// --_buffered_bytes;
bhepp 14:2150f1edc9bc 100 //// }
bhepp 14:2150f1edc9bc 101 //
bhepp 14:2150f1edc9bc 102 //// BufferedSerial::prime();
bhepp 14:2150f1edc9bc 103 //
bhepp 14:2150f1edc9bc 104 //// __enable_irq();
bhepp 14:2150f1edc9bc 105 //
bhepp 14:2150f1edc9bc 106 // return c;
bhepp 14:2150f1edc9bc 107 //}
bhepp 14:2150f1edc9bc 108
sam_grove 0:a977d0a3d81e 109 int BufferedSerial::putc(int c)
sam_grove 0:a977d0a3d81e 110 {
bhepp 14:2150f1edc9bc 111 while (_buffered_bytes >= this->_buf_size) {
bhepp 14:2150f1edc9bc 112 BufferedSerial::prime();
bhepp 14:2150f1edc9bc 113 }
bhepp 14:2150f1edc9bc 114
bhepp 14:2150f1edc9bc 115 __disable_irq();
bhepp 14:2150f1edc9bc 116
sam_grove 0:a977d0a3d81e 117 _txbuf = (char)c;
bhepp 12:c7947d444267 118 ++_buffered_bytes;
bhepp 14:2150f1edc9bc 119
bhepp 14:2150f1edc9bc 120 __enable_irq();
bhepp 14:2150f1edc9bc 121
sam_grove 1:57a11fb5d529 122 BufferedSerial::prime();
sam_grove 4:2ba4d2e1f05d 123
sam_grove 0:a977d0a3d81e 124 return c;
sam_grove 0:a977d0a3d81e 125 }
sam_grove 0:a977d0a3d81e 126
sam_grove 0:a977d0a3d81e 127 int BufferedSerial::puts(const char *s)
sam_grove 0:a977d0a3d81e 128 {
ansond 7:6fa214b41d73 129 if (s != NULL) {
ansond 7:6fa214b41d73 130 const char* ptr = s;
bhepp 12:c7947d444267 131
bhepp 12:c7947d444267 132 while (*(ptr) != 0) {
bhepp 12:c7947d444267 133 // Wait for free space in buffer
bhepp 12:c7947d444267 134 while (_buffered_bytes >= this->_buf_size) {}
ansond 7:6fa214b41d73 135 _txbuf = *(ptr++);
bhepp 12:c7947d444267 136 ++_buffered_bytes;
ansond 7:6fa214b41d73 137 }
ansond 7:6fa214b41d73 138 _txbuf = '\n'; // done per puts definition
ansond 7:6fa214b41d73 139 BufferedSerial::prime();
bhepp 12:c7947d444267 140
ansond 7:6fa214b41d73 141 return (ptr - s) + 1;
sam_grove 0:a977d0a3d81e 142 }
ansond 7:6fa214b41d73 143 return 0;
sam_grove 0:a977d0a3d81e 144 }
sam_grove 0:a977d0a3d81e 145
sam_grove 0:a977d0a3d81e 146 int BufferedSerial::printf(const char* format, ...)
sam_grove 0:a977d0a3d81e 147 {
ansond 10:9ee15ae3d1a3 148 char buffer[this->_buf_size];
bhepp 12:c7947d444267 149 memset(buffer, 0, this->_buf_size);
sam_grove 0:a977d0a3d81e 150 int r = 0;
sam_grove 4:2ba4d2e1f05d 151
sam_grove 0:a977d0a3d81e 152 va_list arg;
sam_grove 0:a977d0a3d81e 153 va_start(arg, format);
bhepp 12:c7947d444267 154 r = vsnprintf(buffer, this->_buf_size, format, arg);
sam_grove 0:a977d0a3d81e 155 // this may not hit the heap but should alert the user anyways
ansond 10:9ee15ae3d1a3 156 if(r > this->_buf_size) {
bhepp 12:c7947d444267 157 error("%s %d buffer to small (buf_size: %d, required: %d)!\r\n", __FILE__, __LINE__, this->_buf_size, r);
ansond 7:6fa214b41d73 158 va_end(arg);
ansond 7:6fa214b41d73 159 return 0;
sam_grove 0:a977d0a3d81e 160 }
sam_grove 4:2ba4d2e1f05d 161 va_end(arg);
ansond 10:9ee15ae3d1a3 162 r = BufferedSerial::write(buffer, r);
sam_grove 4:2ba4d2e1f05d 163
sam_grove 0:a977d0a3d81e 164 return r;
sam_grove 0:a977d0a3d81e 165 }
sam_grove 0:a977d0a3d81e 166
bhepp 13:b4080afc8cd5 167 int BufferedSerial::printf(const char* format, va_list args)
bhepp 13:b4080afc8cd5 168 {
bhepp 13:b4080afc8cd5 169 char buffer[this->_buf_size];
bhepp 13:b4080afc8cd5 170 memset(buffer, 0, this->_buf_size);
bhepp 13:b4080afc8cd5 171 int r = 0;
bhepp 13:b4080afc8cd5 172
bhepp 13:b4080afc8cd5 173 r = vsnprintf(buffer, this->_buf_size, format, args);
bhepp 13:b4080afc8cd5 174 // this may not hit the heap but should alert the user anyways
bhepp 13:b4080afc8cd5 175 if(r > this->_buf_size) {
bhepp 13:b4080afc8cd5 176 error("%s %d buffer to small (buf_size: %d, required: %d)!\r\n", __FILE__, __LINE__, this->_buf_size, r);
bhepp 13:b4080afc8cd5 177 return 0;
bhepp 13:b4080afc8cd5 178 }
bhepp 13:b4080afc8cd5 179 r = BufferedSerial::write(buffer, r);
bhepp 13:b4080afc8cd5 180
bhepp 13:b4080afc8cd5 181 return r;
bhepp 13:b4080afc8cd5 182 }
bhepp 13:b4080afc8cd5 183
sam_grove 2:7e8a450a9101 184 ssize_t BufferedSerial::write(const void *s, size_t length)
sam_grove 2:7e8a450a9101 185 {
ansond 7:6fa214b41d73 186 if (s != NULL && length > 0) {
ansond 7:6fa214b41d73 187 const char* ptr = (const char*)s;
ansond 7:6fa214b41d73 188 const char* end = ptr + length;
bhepp 12:c7947d444267 189
ansond 7:6fa214b41d73 190 while (ptr != end) {
bhepp 12:c7947d444267 191 // Wait for free space in buffer
bhepp 12:c7947d444267 192 while (_buffered_bytes >= this->_buf_size) {}
ansond 7:6fa214b41d73 193 _txbuf = *(ptr++);
bhepp 12:c7947d444267 194 ++_buffered_bytes;
ansond 7:6fa214b41d73 195 }
ansond 7:6fa214b41d73 196 BufferedSerial::prime();
bhepp 12:c7947d444267 197
ansond 7:6fa214b41d73 198 return ptr - (const char*)s;
sam_grove 2:7e8a450a9101 199 }
ansond 7:6fa214b41d73 200 return 0;
sam_grove 2:7e8a450a9101 201 }
sam_grove 2:7e8a450a9101 202
sam_grove 2:7e8a450a9101 203
sam_grove 0:a977d0a3d81e 204 void BufferedSerial::rxIrq(void)
sam_grove 0:a977d0a3d81e 205 {
sam_grove 3:6b76fcf27545 206 // read from the peripheral and make sure something is available
bhepp 12:c7947d444267 207 if (serial_readable(&_serial)) {
sam_grove 0:a977d0a3d81e 208 _rxbuf = serial_getc(&_serial); // if so load them into a buffer
sam_grove 0:a977d0a3d81e 209 }
sam_grove 0:a977d0a3d81e 210 }
sam_grove 0:a977d0a3d81e 211
sam_grove 0:a977d0a3d81e 212 void BufferedSerial::txIrq(void)
sam_grove 0:a977d0a3d81e 213 {
sam_grove 3:6b76fcf27545 214 // see if there is room in the hardware fifo and if something is in the software fifo
bhepp 14:2150f1edc9bc 215 while (_txbuf.available() && RawSerial::writeable()) {
bhepp 14:2150f1edc9bc 216 RawSerial::putc((int)_txbuf.get());
bhepp 13:b4080afc8cd5 217 --_buffered_bytes;
sam_grove 0:a977d0a3d81e 218 }
sam_grove 0:a977d0a3d81e 219 }
sam_grove 0:a977d0a3d81e 220
sam_grove 1:57a11fb5d529 221 void BufferedSerial::prime(void)
sam_grove 1:57a11fb5d529 222 {
sam_grove 2:7e8a450a9101 223 // if already busy then the irq will pick this up
bhepp 14:2150f1edc9bc 224 if (RawSerial::writeable()) {
bhepp 14:2150f1edc9bc 225 __disable_irq();
bhepp 14:2150f1edc9bc 226 // TODO
bhepp 14:2150f1edc9bc 227 // RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq
sam_grove 3:6b76fcf27545 228 BufferedSerial::txIrq(); // only write to hardware in one place
bhepp 14:2150f1edc9bc 229 // RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq);
bhepp 14:2150f1edc9bc 230 __enable_irq();
bhepp 14:2150f1edc9bc 231
sam_grove 2:7e8a450a9101 232 }
sam_grove 1:57a11fb5d529 233 }