Utility library for MTS Socket Modem Arduino Shield devices from Multi-Tech Systems
Dependents: mtsas mtsas thermostat_fan_demo--fan mtsas ... more
NOTE: MTS-Utils has moved to GitHub. This version will not be updated. For updates, go to the GitHub version.
Revision 3:08a693917d8c, committed 2014-05-19
- Comitter:
- Mike Fiore
- Date:
- Mon May 19 11:16:57 2014 -0500
- Parent:
- 2:7779ede60c3d
- Child:
- 4:f4d3bafc71dd
- Commit message:
- add MTSCircularBuffer and tests
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTSCircularBuffer.cpp Mon May 19 11:16:57 2014 -0500 @@ -0,0 +1,142 @@ +#include "MTSCircularBuffer.h" + +using namespace mts; + +MTSCircularBuffer::MTSCircularBuffer(int bufferSize) : bufferSize(bufferSize), readIndex(0), writeIndex(0), bytes(0), _threshold(-1), _op(GREATER) +{ + buffer = new char[bufferSize]; +} + +MTSCircularBuffer::~MTSCircularBuffer() +{ + delete[] buffer; +} + +int MTSCircularBuffer::read(char* data, int length) +{ + int i = 0; + while ((i < length) && (bytes > 0)) { + if (readIndex == bufferSize) { + readIndex = 0; + } + data[i++] = buffer[readIndex++]; + bytes--; + checkThreshold(); + } + return i; +} + +int MTSCircularBuffer::read(char& data) +{ + if (bytes == 0) { + return 0; + } + if (readIndex == bufferSize) { + readIndex = 0; + } + data = buffer[readIndex++]; + bytes--; + checkThreshold(); + return 1; +} + +int MTSCircularBuffer::write(const char* data, int length) +{ + int i = 0; + while((i < length) && (bytes < bufferSize)) { + if(writeIndex == bufferSize) { + writeIndex = 0; + } + buffer[writeIndex++] = data[i++]; + bytes++; + checkThreshold(); + } + return i; +} + +int MTSCircularBuffer::write(char data) +{ + if (bytes == bufferSize) { + return 0; + } + if(writeIndex == bufferSize) { + writeIndex = 0; + } + buffer[writeIndex++] = data; + bytes++; + checkThreshold(); + return 1; +} + +int MTSCircularBuffer::capacity() +{ + return bufferSize; +} + +int MTSCircularBuffer::remaining() +{ + return bufferSize - bytes; +} + +int MTSCircularBuffer::size() +{ + return bytes; +} + +bool MTSCircularBuffer::isFull() +{ + if (bytes == bufferSize) { + return true; + } else { + return false; + } +} + +bool MTSCircularBuffer::isEmpty() +{ + if (bytes == 0) { + return true; + } else { + return false; + } +} + +void MTSCircularBuffer::clear() +{ + writeIndex = readIndex = bytes = 0; +} + +void MTSCircularBuffer::checkThreshold() +{ + if (_threshold == -1) { + return; + } + switch (_op) { + case GREATER: + if (bytes > _threshold) { + notify.call(); + } + break; + case LESS: + if (bytes < _threshold) { + notify.call(); + } + break; + case GREATER_EQUAL: + if (bytes >= _threshold) { + notify.call(); + } + break; + case LESS_EQUAL: + if (bytes <= _threshold) { + notify.call(); + } + break; + case EQUAL: + if (bytes == _threshold) { + notify.call(); + } + break; + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MTSCircularBuffer.h Mon May 19 11:16:57 2014 -0500 @@ -0,0 +1,159 @@ +#ifndef MTSCIRCULARBUFFER_H +#define MTSCIRCULARBUFFER_H + +#include "mbed.h" +#include "Vars.h" + +namespace mts +{ + +/** This class provides a circular byte buffer meant for temporary storage +* during IO transactions. It contains many of the common methods you +* would expect from a circular buffer like read, write, and various +* methods for checking the size or status. It should be noted that +* this class does not include any special code for thread safety like +* a lock. In most cases this is not problematic, but is something +* to be aware of. +*/ +class MTSCircularBuffer +{ +public: + /** Creates an MTSCircularBuffer object with the specified static size. + * + * @prarm bufferSize size of the buffer in bytes. + */ + MTSCircularBuffer(int bufferSize); + + /** Destructs an MTSCircularBuffer object and frees all related resources. + */ + ~MTSCircularBuffer(); + + /** This method enables bulk reads from the buffer. If more data is + * requested then available it simply returns all remaining data within the + * buffer. + * + * @param data the buffer where data read will be added to. + * @param length the amount of data in bytes to be read into the buffer. + * @returns the total number of bytes that were read. + */ + int read(char* data, int length); + + /** This method reads a single byte from the buffer. + * + * @param data char where the read byte will be stored. + * @returns 1 if byte is read or 0 if no bytes available. + */ + int read(char& data); + + /** This method enables bulk writes to the buffer. If more data + * is requested to be written then space available the method writes + * as much data as possible and returns the actual amount written. + * + * @param data the byte array to be written. + * @param length the length of data to be written from the data paramter. + * @returns the number of bytes written to the buffer, which is 0 if + * the buffer is full. + */ + int write(const char* data, int length); + + /** This method writes a signle byte as a char to the buffer. + * + * @param data the byte to be written as a char. + * @returns 1 if the byte was written or 0 if the buffer was full. + */ + int write(char data); + + /** This method is used to setup a callback funtion when the buffer reaches + * a certain threshold. The threshold condition is checked after every read + * and write call is completed. The condition is made up of both a threshold + * value and operator. An example that would trigger a callback is if the + * threshold was 10, the operator GREATER, and there were 12 bytes added to an + * empty buffer. + * + * @param tptr a pointer to the object to be called when the condition is met. + * @param mptr a pointer to the function within the object to be called when + * the condition is met. + * @param threshold the value in bytes to be used as part of the condition. + * @param op the operator to be used in conjunction with the threshold + * as part of the condition. + */ + template<typename T> + void attach(T *tptr, void( T::*mptr)(void), int threshold, RelationalOperator op) { + _threshold = threshold; + _op = op; + notify.attach(tptr, mptr); + } + + /** This method is used to setup a callback funtion when the buffer reaches + * a certain threshold. The threshold condition is checked after every read + * and write call is completed. The condition is made up of both a threshold + * value and operator. An example that would trigger a callback is if the + * threshold was 10, the operator GREATER, and there were 12 bytes added to an + * empty buffer. + * + * @param fptr a pointer to the static function to be called when the condition + * is met. + * @param threshold the value in bytes to be used as part of the condition. + * @param op the operator to be used in conjunction with the threshold + * as part of the condition. + */ + void attach(void(*fptr)(void), int threshold, RelationalOperator op) { + _threshold = threshold; + _op = op; + notify.attach(fptr); + } + + /** This method returns the size of the storage space currently allocated for + * the buffer. This value is equivalent to the one passed into the constructor. + * This value is equal or greater than the size() of the buffer. + * + * @returns the allocated size of the buffer in bytes. + */ + int capacity(); + + /** This method returns the amount of space left for writing. + * + * @returns numbers of unused bytes in buffer. + */ + int remaining(); + + /** This method returns the number of bytes available for reading. + * + * @returns number of bytes currently in buffer. + */ + int size(); + + /** This method returns whether the buffer is full. + * + * @returns true if full, otherwise false. + */ + bool isFull(); + + /** This method returns whether the buffer is empty. + * + * @returns true if empty, otherwise false. + */ + bool isEmpty(); + + /** This method clears the buffer. This is done through + * setting the internal read and write indexes to the same + * value and is therefore not an expensive operation. + */ + void clear(); + + +private: + int bufferSize; // total size of the buffer + char* buffer; // internal byte buffer as a character buffer + int readIndex; // read index for circular buffer + int writeIndex; // write index for circular buffer + int bytes; // available data + FunctionPointer notify; // function pointer used for the internal callback notification + int _threshold; // threshold for the notification + RelationalOperator _op; // operator that determines the direction of the threshold + void checkThreshold(); // private function that checks thresholds and processes notifications +}; + +} + +#endif /* MTSCIRCULARBUFFER_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Test/TestMTSCircularBuffer.h Mon May 19 11:16:57 2014 -0500 @@ -0,0 +1,64 @@ +#ifndef TESTMTSCIRCULARBUFFER_H +#define TESTMTSCIRCULARBUFFER_H + +#include "MTSCircularBuffer.h" +#include "Vars.h" + + +/* unit tests for the circular buffer class */ + +using namespace mts; + +class TestMTSCircularBuffer : public TestCollection +{ +public: + TestMTSCircularBuffer(); + virtual void run(); +private: + int capacity; + MTSCircularBuffer buffer; +}; + +TestMTSCircularBuffer::TestMTSCircularBuffer() : TestCollection("MTSCircularBuffer"), capacity(0), buffer(5) +{ +} + +void TestMTSCircularBuffer::run() +{ + //Testing capacity method + Test::start("capacity method"); + Test::assertTrue(buffer.capacity() == 5); + Test::end(); + + //Testing getSize method + Test::start("size method"); + Test::assertTrue(buffer.size() == 0); + buffer.write('A'); + Test::assertTrue(buffer.size() == 1); + buffer.clear(); + Test::end(); + + //Testing clear method + Test::start("clear method"); + buffer.write("AT", 2); + buffer.clear(); + Test::assertTrue(buffer.size() == 0); + Test::end(); + + //Test isEmpty method + Test::start("isEmpty method"); + Test::assertTrue(buffer.isEmpty()); + buffer.write('A'); + Test::assertFalse(buffer.isEmpty()); + Test::end(); + + //Test isFull method + Test::start("isFull method"); + Test::assertFalse(buffer.isFull()); + buffer.write("12345", 5); + Test::assertTrue(buffer.isFull()); + buffer.clear(); + Test::end(); +} + +#endif /* TESTMTSCIRCULARBUFFER_H */