00001 /* 00002 * buffered_serial.h 00003 * 00004 * Implements a variable size buffer for received serial data 00005 * 00006 * Author: Nick Young (9/26/10) 00007 * Portions of code by: Richard Sewel (11/17/09) 00008 * 00009 */ 00010 00011 #include "mbed.h" 00012 #include "buffered_serial.h" 00013 00014 /** 00015 * Constructs a BufferedSerial object 00016 * 00017 * Creates a BufferedSerial with default settings of 9600 8N1. 00018 * Valid (TX/RX) pairs are {(USBTX/USBRX), (9/10), (13/14), (28/27)}. 00019 * Valid baud rates are {110, 300, 600, 1200, 2400, 4800, 9600, 14400, 00020 * 19200, 38400, 57600, 115200, 230400, 460800, 921600}. 00021 * Maximum buffer size is 256 bytes. 00022 * 00023 * @param PinName tx 00024 * The transmit out (TXO) pin for this serial port 00025 * @param PinName rx 00026 * The receive in (RXI) pin for this serial port 00027 * @param uint8_t buffer_size 00028 * The desired size of the circular buffer 00029 */ 00030 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint8_t buffer_size) : 00031 Serial(tx, rx), 00032 has_callback_(false) 00033 { 00034 buffer_size_ = 0; 00035 content_start_ = 0; 00036 content_end_ = 0; 00037 available_bytes_ = 0; 00038 00039 attach(this, &BufferedSerial::handleInterrupt); 00040 00041 buffer_ = (uint8_t *) malloc(buffer_size + 1); 00042 if(buffer_ != NULL) 00043 { 00044 buffer_size_ = buffer_size + 1; 00045 } 00046 } 00047 00048 BufferedSerial::~BufferedSerial() 00049 { 00050 if(buffer_) 00051 free(buffer_); 00052 } 00053 00054 /** 00055 * Checks if there are bytes ready to be read 00056 * 00057 * @return bool 00058 * true if there are bytes ready to be read 00059 * false otherwise 00060 */ 00061 bool BufferedSerial::readable() 00062 { 00063 return (content_start_ != content_end_); 00064 } 00065 00066 /** 00067 * Checks how many bytes are ready to be read 00068 * 00069 * @return uint8_t 00070 * The number of bytes ready to be read 00071 */ 00072 uint8_t BufferedSerial::availableBytes() 00073 { 00074 return available_bytes_; 00075 } 00076 00077 /** 00078 * Reads the next available byte without removing it from the buffer 00079 * 00080 * Reads a single byte from the front of the circular buffer (without 00081 * removing it from the buffer and returns its value. This method 00082 * will block until a single byte is available. 00083 * 00084 * @return uint8_t 00085 * The frontmost byte in the circular receive buffer 00086 */ 00087 uint8_t BufferedSerial::peek() 00088 { 00089 //block until a byte is available 00090 while(content_start_ == content_end_) { wait_us(1); } 00091 00092 return buffer_[content_start_]; 00093 } 00094 00095 /** 00096 * Reads the next available received byte 00097 * 00098 * Removes a single byte from the front of the circular buffer and 00099 * returns its value. This method will block until a single byte 00100 * is available. 00101 * 00102 * @return uint8_t 00103 * The frontmost byte in the circular receive buffer 00104 */ 00105 uint8_t BufferedSerial::getc() 00106 { 00107 //block until a byte is available 00108 while(content_start_ == content_end_) { wait_us(1); } 00109 00110 //read the byte and remove it from the buffer 00111 uint8_t result = buffer_[content_start_++]; 00112 content_start_ = content_start_ % buffer_size_; 00113 available_bytes_--; 00114 00115 return result; 00116 } 00117 00118 /** 00119 * Reads the next four bytes into a long data type 00120 * 00121 * Reads the next four bytes and stores them into a signed long data 00122 * type. This method will block until four bytes are available. The 00123 * first byte is considered to be the MSB, and the last byte is 00124 * considered to be the LSB. 00125 * 00126 * @return long 00127 * The front most four bytes in the buffer as a long 00128 */ 00129 long BufferedSerial::readLong() 00130 { 00131 long result = (getc() << 24) | 00132 (getc() << 16) | 00133 (getc() << 8 ) | 00134 (getc() ); 00135 return result; 00136 } 00137 00138 /** 00139 * Reads requested_bytes bytes into a provided buffer 00140 * 00141 * Reads a specified number of bytes into a caller-supplied buffer. 00142 * This method will block until requested_bytes bytes are available. 00143 * The reads are performed byte-wise and will remove the byte from 00144 * the circular buffer as it is added to the destination buffer. 00145 * 00146 * @param uint8_t* bytes 00147 * The pre-allocated destination buffer 00148 * @param size_t requested_bytes 00149 * The number of bytes to move into the buffer 00150 */ 00151 void BufferedSerial::readBytes(uint8_t *bytes, size_t requested_bytes) 00152 { 00153 for (size_t index = 0; index < requested_bytes; index++) 00154 bytes[index] = getc(); 00155 } 00156 00157 /** 00158 * Flushes the receive buffer 00159 */ 00160 void BufferedSerial::flushBuffer() 00161 { 00162 content_end_ = content_start_; 00163 available_bytes_ = 0; 00164 } 00165 00166 void BufferedSerial::writeLong(long data) 00167 { 00168 putc((data >> 24) & 0xFF); 00169 putc((data >> 16) & 0xFF); 00170 putc((data >> 8) & 0xFF); 00171 putc((data ) & 0xFF); 00172 } 00173 00174 /** 00175 * Serial receive interrupt handler 00176 * 00177 * On receipt of data, this method is run to empty 00178 * the hardware buffer and fill the circular buffer 00179 * with the received data. If the circular buffer is 00180 * full, incoming data will be dropped. 00181 */ 00182 void BufferedSerial::handleInterrupt() 00183 { 00184 while(Serial::readable()) 00185 { 00186 if (content_start_ == (content_end_ + 1) % buffer_size_) 00187 Serial::getc(); 00188 else 00189 { 00190 buffer_[content_end_++] = Serial::getc(); 00191 content_end_ = content_end_ % buffer_size_; 00192 available_bytes_++; 00193 } 00194 //if the buffer is full, then callback the object 00195 if (has_callback_ && (content_start_ == (content_end_ + 1) % buffer_size_) ) 00196 callback_.call(); 00197 } 00198 }