This application will buffer and send lines from up to three serial devices and USB host when connected to via TCP, with telnet or netcat. Written, 02/10/2011-2/14/2011 by Graham Cantin & Special Guest Appearance from Sasha Jevtic (mostly Sasha)
Dependencies: EthernetNetIf MODDMA MODGPS MODSERIAL NTPClient mbed
Diff: line_util.cpp
- Revision:
- 0:5d5265391846
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/line_util.cpp Mon Aug 13 07:05:57 2012 +0000 @@ -0,0 +1,187 @@ + +// Line utility functions +// 02/13/2011 + + +/* + +Utility functions for dealing with incoming data + +*/ + +#include "mbed.h" +#include "line_util.h" + +static LINE_T SLines[NUM_LINES]; + +// Cirular buffer head pointer +static unsigned int HeadLines = 0; + +// Circular buffer tail pointer +static unsigned int TailLines = 0; + +// Allow inserting things into the queue? +static bool AllowInsert = false; + +// These are the source type names when output into a line struct. +const char* const LINE_SRC_NAMES[] = +{ + "INVALID", + "DBG", + "KIS", + "GPS", + "IMU", + "WHL", + "BUT", + "NONE" +}; + +// Strips any carrage returns or line feeds from incoming lines, once received +unsigned int strip_crlf(char* src) +{ + + unsigned int i = 0; + + while(src[i] != 0) { + + if((src[i] == '\n') || (src[i] == '\r')) { + src[i] = 0; + return i; + } + + i++; + } + + return i; +} + + +// Line Buffers: Get the current level of queue fullness in # of lines +unsigned int SLines_get_fill() +{ + unsigned int ret; + + __disable_irq(); // IRQs off, don't bother us, we're working. + + ret = (TailLines >= HeadLines ? + TailLines - HeadLines : + NUM_LINES - (HeadLines - TailLines)); + + __enable_irq(); // Back to reality, more data calls. + + return ret; +} + + +// Line Buffers: Get the current capacity of the queue +unsigned int SLines_get_capacity() +{ + return (NUM_LINES - 1); +} + + +// Line Buffers: Put a line into the queue +LINE_T* SLine_put(LINE_T* line) +{ + unsigned int fill; + LINE_T* ret; // Empty struct to return + + __disable_irq(); // IRQs off, don't bother us, we're working. + + // Are we allowing inserts? If not, just Return a NULL struct early. + if (!AllowInsert) { + ret = NULL; + __enable_irq(); // Back to reality, more data calls. + + return ret; + } + + fill = (TailLines >= HeadLines ? + TailLines - HeadLines : + NUM_LINES - (HeadLines - TailLines)); + + if (fill != (NUM_LINES - 1)) { + TailLines = (TailLines + 1) % NUM_LINES; + memcpy(&(SLines[TailLines]), line, sizeof(LINE_T)); + ret = &(SLines[TailLines]); + } + else { + ret = NULL; + } + + __enable_irq(); // Back to reality, more data calls. + + return ret; +} + +// Line Buffers: Get a line from the queue +LINE_T* SLine_get() +{ + bool empty; // Is the queue empty? + LINE_T* ret; // Pointer to the line we're about to return + + __disable_irq(); // IRQs off, don't bother us, we're working. + + // Check to see if the queue is empty. + empty = (HeadLines == TailLines ? true : false); + + if (!empty) { // if the queue is not empty + ret = &(SLines[HeadLines]); // Return a line. + } + else { // the queue was empty. + ret = NULL; // Return an empty struct. + } + + // Note that the pointer to the line struct that we're returning is only + // guaranteed good until it is removed. In fact, the preservation of + // the data pointed to is the only reason that "get" and "remove" are + // seperate operations. + + __enable_irq(); + + return ret; +} + + +// Line Buffers: Remove the line from the queue once a GET succeeds +void SLine_remove() +{ + bool empty; // Is the queue empty? + + __disable_irq(); // IRQs off, don't bother us, we're working. + + // Check to see if the queue is empty. + empty = (HeadLines == TailLines ? true : false); + + if (!empty) { // If the queue is not empty... + HeadLines = (HeadLines + 1) % NUM_LINES; // The axe falls, the line expires. + + // The tricky part, of course, is that the data is not + // immediately invalidated. Any pointers to the now-removed line + // will point to valid data until a put() operation overwrites + // the line in question. Of course, the code that removes the line + // won't typically be the code that also performs insertions, so it + // will never know when that happens. Moral of the story: finish what + // you're doing with a gotten line before removing it. + } + + __enable_irq(); // Back to reality, more data calls. +} + + +// Line Buffers: Clear the queue +void SLine_clear() +{ + __disable_irq(); // IRQs off, don't bother us, we're working. + HeadLines = TailLines = 0; // Set both ends of the snake at oroboros. + __enable_irq(); // Back to reality, more data calls. +} + + +// Line Buffers: Open or Close the queue to incoming lines +void SLine_put_control(bool gate) +{ + __disable_irq(); // IRQs off, don't bother us, we're working. + AllowInsert = gate; // Set one end of the snake open. + __enable_irq(); // Back to reality, more data calls. +} \ No newline at end of file