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

line_util.cpp

Committer:
kamilion
Date:
2014-11-06
Revision:
1:29f6c660d174
Parent:
0:5d5265391846

File content as of revision 1:29f6c660d174:


// 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.
}