From dc6f5a897ad9a6d75119fa0c88f53ce26107f43d Mon Sep 17 00:00:00 2001 From: srlm Date: Mon, 16 Dec 2013 03:13:19 -0500 Subject: [PATCH] Added stream interfaces so that we can abstract the output device. --- libpropeller/serial/serial.h | 171 ++------------ libpropeller/serial/serial.test.h | 214 +----------------- .../streaminterface/streaminterface.h | 37 +++ 3 files changed, 57 insertions(+), 365 deletions(-) create mode 100644 libpropeller/streaminterface/streaminterface.h diff --git a/libpropeller/serial/serial.h b/libpropeller/serial/serial.h index 5f70c0c..9fdddac 100644 --- a/libpropeller/serial/serial.h +++ b/libpropeller/serial/serial.h @@ -5,6 +5,10 @@ #include #include "libpropeller/numbers/numbers.h" +#include "libpropeller/streaminterface/streaminterface.h" + +#include "libpropeller/printstream/printstream.h" + extern char _load_start_serial_cog[]; /** A high speed and high accuracy serial driver. @@ -26,7 +30,9 @@ extern char _load_start_serial_cog[]; * @author SRLM (srlm@srlmproductions.com) * */ -class Serial { +class Serial : public InputStream, public OutputStream{ +//class Serial : public StreamInterface{ +//class Serial{ public: /** Size of the RX buffer in bytes. No restrictions on size (well, Hub RAM @@ -53,8 +59,7 @@ class Serial { * @param ctspin cts is an input for control of flow from the tx pin. If high, it disables transmissions. * @return Returns true if the cog started OK, false otherwise */ - bool Start(const int rxpin, const int txpin, const int rate, - const int ctspin = -1) { + bool Start(const int rxpin, const int txpin, const int rate, const int ctspin = -1) { // Prevent garbage collection of the ASM code volatile void * asm_driver_reference = NULL; @@ -103,7 +108,7 @@ class Serial { SetBaud(rate); SetDriverLong(&Period_ptr, (int) &half_bit_period_); - memset((void *) &rx_buffer_, 0, 1 * (kBufferLength)); + memset((void *) &rx_buffer_, 0, kBufferLength); SetDriverLong(&Rx_head_ptr, (int) &rx_buffer_); SetDriverLong(&Rx_end_ptr, (int) &rx_buffer_ + kBufferLength); @@ -200,155 +205,7 @@ class Serial { return Put(buffer_ptr, strlen(buffer_ptr)); } - /** Transmit a string (printf function-alike). - * - * This function is based on the requirements found on this page: - * http://www.cplusplus.com/reference/cstdio/printf/ - * - * @warning This function does not implement the full printf functionality. - * - * Formatters must follow the following prototype: - * %[flags][width]specifier - * The following flags are supported - * - 0 (only with x,X,b,B). Sets padding to the 0 character instead of space. - * This function supports the following specifiers: - - * - d or i : signed decimal integer. The width specifier will pad with - * spaces if necessary. - * - x or X : hexadecimal integer. All caps (with either). The width - * specifier will pad with spaces (or 0s if the 0 flag is set) if - * necessary - * - c : output a single character. - * - s : output a string of characters, 0 terminated. - * - % : output a % symbol. - * - * Each specifier must have a matching typed optional argument. - * - * Behavior is undefined if % is used without a specifier. - * - * @param format the string to send, optionally with specifiers. - * @param ... additional arguments. Depending on the format string, the - * function may expect a sequence of additional arguments. - * @returns on success, the total number of characters written. On - * error, a negative number is returned. - */ - int PutFormatted(const char * format, ...) { - if (format == NULL) { - return 0; - } - - int bytesWritten = 0; - - va_list list; - va_start(list, format); - - - for (int stringIndex = 0; format[stringIndex] != 0; stringIndex++) { - - if (format[stringIndex] == '%') { - //Found formatter! - stringIndex++; - //Check for flags: - bool padZero = false; - int padAmount = 0; - if (format[stringIndex] == '0') { - padZero = true; - stringIndex++; - } - if (format[stringIndex] >= '1' and format[stringIndex] <= '9') { - char paddingBuffer[5]; - int paddingIndex = 0; - - - //Non freezing version. - if (format[stringIndex] >= '0' and format[stringIndex] <= '9') { - paddingBuffer[paddingIndex++] = format[stringIndex++]; - if (format[stringIndex] >= '0' and format[stringIndex] <= '9') { - paddingBuffer[paddingIndex++] = format[stringIndex++]; - if (format[stringIndex] >= '0' and format[stringIndex] <= '9') { - paddingBuffer[paddingIndex++] = format[stringIndex++]; - if (format[stringIndex] >= '0' and format[stringIndex] <= '9') { - paddingBuffer[paddingIndex++] = format[stringIndex++]; - } - } - } - } - - //TO DO(SRLM): figure out what is happening with the freezing version. - //I think it freezes because of the CMM and fcache combination. - //Freezing version: - // while(format[stringIndex] >= '0' and format[stringIndex] <= '9'){ - // paddingBuffer[paddingIndex++] = format[stringIndex]; - //// printf("+%c+", format[stringIndex]); - // stringIndex++; - // } - paddingBuffer[paddingIndex] = 0; - padAmount = Numbers::Dec(paddingBuffer); - // printf("paddingBuffer[0] = %c\r\n", paddingBuffer[0]); - // printf("paddingBuffer[1] = %c\r\n", paddingBuffer[1]); - // printf("paddingIndex = %i\r\n", paddingIndex); - // printf("padAmount: %i\r\n", padAmount); - - - } - - - - if (format[stringIndex] == 0) { - // Throw away the '%' character if it's at the end of the string. - break; - } - if (format[stringIndex] == 'd' || format[stringIndex] == 'i') { - int number = va_arg(list, int); - int digits = Numbers::DecDigits(number); - if (padAmount > 0) { - for (int i = padAmount - digits; i > 0; --i) { - Put(' '); - } - } - - PutFormatted(Numbers::Dec(number)); - bytesWritten += digits; - } else if (format[stringIndex] == 'x' || format[stringIndex] == 'X') { - int number = va_arg(list, int); - int digits = Numbers::HexDigits(number); - if (padAmount > 0) { - for (int i = padAmount - digits; i > 0; --i) { - if (padZero) { - Put('0'); - } else { - Put(' '); - } - } - } - - PutFormatted(Numbers::Hex(number, digits)); - bytesWritten += digits; - } else if (format[stringIndex] == 'c') { - char character = (char) (va_arg(list, int)); - Put(character); - bytesWritten++; - } else if (format[stringIndex] == 's') { - char * string = (char *) (va_arg(list, int)); - while (*string != 0) { - Put(*string++); - bytesWritten++; - } - } else if (format[stringIndex] == '%') { - Put('%'); - bytesWritten++; - } - - } else { - Put(format[stringIndex]); - bytesWritten++; - } - } - - va_end(list); - return bytesWritten; - } /** Receive a byte (wait) or timeout. * @@ -447,6 +304,16 @@ class Serial { return kBufferLength - tail + head; } } + + int PutFormatted(const char * formatString, ...){ + PrintStream ps(this); + + va_list list; + va_start(list, formatString); + int result = ps.Format(formatString, list); + va_end(list); + return result; + } private: diff --git a/libpropeller/serial/serial.test.h b/libpropeller/serial/serial.test.h index 443d0ca..e7ecb3c 100644 --- a/libpropeller/serial/serial.test.h +++ b/libpropeller/serial/serial.test.h @@ -185,57 +185,12 @@ class UnityTests { // String and Long Buffer Tests // ----------------------------------------------------------------------------- - static void test_PutBufferFormatted(void) { - // sut.GetFlush(); - - TEST_ASSERT_EQUAL_INT(3, sut.PutFormatted("abc")); - - - - TEST_ASSERT_EQUAL_INT('a', sut.Get(MAXTIME)); - TEST_ASSERT_EQUAL_INT('b', sut.Get(MAXTIME)); - TEST_ASSERT_EQUAL_INT('c', sut.Get(MAXTIME)); - TEST_ASSERT_EQUAL_INT(-1, sut.Get(MAXTIME)); - } - - //static void test_PutBufferNoSize(void) - //{ - // sut.Put("abc", 0); - // TEST_ASSERT_EQUAL_INT(-1, sut.Get(MAXTIME)); - //} - static void test_PutBufferNoPointer(void) { TEST_ASSERT_EQUAL_INT(0, sut.PutFormatted((char *) NULL)); TEST_ASSERT_EQUAL_INT(-1, sut.Get(MAXTIME)); } - //static void test_PutBufferNoWaitActuallyDoesntWait(void) - //{ - // //If this test fails, it's possible because PutBufferNoWait() ends up waiting, - // //so that the GetFlush empties out all the bytes it will receive. In that - // //case, there are no bytes left to receive and it times out. - // sut.PutBufferNoWait("123456789012345678901234567890", 30); - // sut.GetFlush(); - // int result = sut.Get(MAXTIME); - // TEST_ASSERT_TRUE(result != -1); - //} - static void test_PutS(void) { - // char * volatile temp = new char(6); - // temp[0] = 'H'; - // temp[1] = 'e'; - // temp[2] = 'l'; - // temp[3] = 'l'; - // temp[4] = 'o'; - // temp[5] = '\0'; - // - // - // TEST_ASSERT_EQUAL_INT(5, sut.Put(temp)); - // - // volatile char message[] = "Hello"; - // sut.PutBuffer(message); - - TEST_ASSERT_EQUAL_INT(5, sut.PutFormatted("Hello")); TEST_ASSERT_EQUAL_INT('H', sut.Get(MAXTIME)); TEST_ASSERT_EQUAL_INT('e', sut.Get(MAXTIME)); @@ -294,174 +249,7 @@ class UnityTests { TEST_ASSERT_TRUE(sut.SetBaudClock(9600, 80000000)); } - // ----------------------------------------------------------------------------- - - static void test_PutPrintfReturnsWrittenBytes(void) { - int size = 30; - char inputBuffer[size]; - - TEST_ASSERT_EQUAL_INT(17, sut.PutFormatted("My:%i, Your:%i", 123, -531)); - TEST_ASSERT_EQUAL_INT(17, sut.Get(inputBuffer, 17, MAXTIME)); - sut.GetFlush(); - } - - static void test_PutPrintfBasic(void) { - - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - - sut.PutFormatted("My number: %i.", 123); - sut.Get(inputBuffer, 15, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My number: 123.", inputBuffer); - - - } - - static void test_PutPrintfMultipleIntegers(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - - sut.PutFormatted("My:%i, Your:%i", 123, -531); - sut.Get(inputBuffer, 17, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:123, Your:-531", inputBuffer); - } - - static void test_PutPrintfNoSpecifiers(void) { - char string[] = "Hello, World."; - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - - sut.PutFormatted(string); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING(string, inputBuffer); - } - - static void test_PutPrintfHexSpecifiers(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%x, Your:%X", 0xAB, 0xCDE); - sut.Get(inputBuffer, 15, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:AB, Your:CDE", inputBuffer); - } - - static void test_PutPrintfDecpad(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%10d", 1234); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My: 1234", inputBuffer); - } - - static void test_PutPrintfDecpadSmaller(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%2d", 1234); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:1234", inputBuffer); - } - - static void test_PutPrinfHexpad(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%10x", 0x1234); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My: 1234", inputBuffer); - } - - static void test_PutPrinfHexpadTooSmall(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%2x", 0x1234); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:1234", inputBuffer); - } - - static void test_PutPrinfHexpadZero(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%010x", 0x1234); - sut.Get(inputBuffer, 13, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:0000001234", inputBuffer); - } - - static void test_PutPrintfChar(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%c", 'a'); - sut.Get(inputBuffer, 4, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:a", inputBuffer); - } - - static void test_PutPrintfString(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("My:%s", "World"); - sut.Get(inputBuffer, 8, MAXTIME); - TEST_ASSERT_EQUAL_STRING("My:World", inputBuffer); - } - - static void test_PutPrinfAllTogether(void) { - int size = 30; - char inputBuffer[size]; - for (int i = 0; i < size; i++) { - inputBuffer[i] = 0; - } - sut.PutFormatted("%x%i%s%c%03x%4i", 0x23, 32, "hello", 'w', 0xF, 13); - sut.Get(inputBuffer, 17, MAXTIME); - TEST_ASSERT_EQUAL_STRING("2332hellow00F 13", inputBuffer); - } - - static void test_PutPrintfPercentSignAtEndOfStringDisappears(void) { - const int size = strlen("Hello"); - char inputBuffer[size]; - sut.PutFormatted("Hello'%"); - sut.Put("'"); - sut.Get(inputBuffer, size, MAXTIME); - TEST_ASSERT_EQUAL_MEMORY("Hello''", inputBuffer, size); - - } - - static void test_PutPrintfTwoPercentSigns(void) { - const int size = strlen("Hello% "); - char inputBuffer[size]; - sut.PutFormatted("Hello%% "); - sut.Get(inputBuffer, size, MAXTIME); - TEST_ASSERT_EQUAL_MEMORY("Hello% ", inputBuffer, size); - - } + // ----------------------------------------------------------------------------- static void test_GetBuffer(void) { diff --git a/libpropeller/streaminterface/streaminterface.h b/libpropeller/streaminterface/streaminterface.h new file mode 100644 index 0000000..24e9207 --- /dev/null +++ b/libpropeller/streaminterface/streaminterface.h @@ -0,0 +1,37 @@ +#ifndef LIBPROPELLER_STREAMINTERFACE_H_ +#define LIBPROPELLER_STREAMINTERFACE_H_ + +template +struct InputStream{ + int Get(const int timeout = -1){ + return static_cast(this)->Get(timeout); + } + + int Get(char * const buffer, const int length, const int timeout = -1){ + return static_cast(this)->Get(buffer, length, timeout); + } + + int Get(char * const buffer, const char terminator = '\n'){ + return static_cast(this)->Get(buffer, terminator); + } + + +}; + +template +struct OutputStream{ + void Put(const char character){ + static_cast(this)->Put(character); + } + + int Put(const char * buffer_ptr){ + return static_cast(this)->Put(buffer_ptr); + } + + int Put(const char * buffer_ptr, const int count){ + return static_cast(this)->Put(buffer_ptr, count); + } +}; + +#endif // LIBPROPELLER_STREAMINTERFACE_H_ +