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@0:5d5265391846, 2012-08-13 (annotated)
- Committer:
- kamilion
- Date:
- Mon Aug 13 07:05:57 2012 +0000
- Revision:
- 0:5d5265391846
initial import of old repo
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kamilion | 0:5d5265391846 | 1 | |
kamilion | 0:5d5265391846 | 2 | // Line utility functions |
kamilion | 0:5d5265391846 | 3 | // 02/13/2011 |
kamilion | 0:5d5265391846 | 4 | |
kamilion | 0:5d5265391846 | 5 | |
kamilion | 0:5d5265391846 | 6 | /* |
kamilion | 0:5d5265391846 | 7 | |
kamilion | 0:5d5265391846 | 8 | Utility functions for dealing with incoming data |
kamilion | 0:5d5265391846 | 9 | |
kamilion | 0:5d5265391846 | 10 | */ |
kamilion | 0:5d5265391846 | 11 | |
kamilion | 0:5d5265391846 | 12 | #include "mbed.h" |
kamilion | 0:5d5265391846 | 13 | #include "line_util.h" |
kamilion | 0:5d5265391846 | 14 | |
kamilion | 0:5d5265391846 | 15 | static LINE_T SLines[NUM_LINES]; |
kamilion | 0:5d5265391846 | 16 | |
kamilion | 0:5d5265391846 | 17 | // Cirular buffer head pointer |
kamilion | 0:5d5265391846 | 18 | static unsigned int HeadLines = 0; |
kamilion | 0:5d5265391846 | 19 | |
kamilion | 0:5d5265391846 | 20 | // Circular buffer tail pointer |
kamilion | 0:5d5265391846 | 21 | static unsigned int TailLines = 0; |
kamilion | 0:5d5265391846 | 22 | |
kamilion | 0:5d5265391846 | 23 | // Allow inserting things into the queue? |
kamilion | 0:5d5265391846 | 24 | static bool AllowInsert = false; |
kamilion | 0:5d5265391846 | 25 | |
kamilion | 0:5d5265391846 | 26 | // These are the source type names when output into a line struct. |
kamilion | 0:5d5265391846 | 27 | const char* const LINE_SRC_NAMES[] = |
kamilion | 0:5d5265391846 | 28 | { |
kamilion | 0:5d5265391846 | 29 | "INVALID", |
kamilion | 0:5d5265391846 | 30 | "DBG", |
kamilion | 0:5d5265391846 | 31 | "KIS", |
kamilion | 0:5d5265391846 | 32 | "GPS", |
kamilion | 0:5d5265391846 | 33 | "IMU", |
kamilion | 0:5d5265391846 | 34 | "WHL", |
kamilion | 0:5d5265391846 | 35 | "BUT", |
kamilion | 0:5d5265391846 | 36 | "NONE" |
kamilion | 0:5d5265391846 | 37 | }; |
kamilion | 0:5d5265391846 | 38 | |
kamilion | 0:5d5265391846 | 39 | // Strips any carrage returns or line feeds from incoming lines, once received |
kamilion | 0:5d5265391846 | 40 | unsigned int strip_crlf(char* src) |
kamilion | 0:5d5265391846 | 41 | { |
kamilion | 0:5d5265391846 | 42 | |
kamilion | 0:5d5265391846 | 43 | unsigned int i = 0; |
kamilion | 0:5d5265391846 | 44 | |
kamilion | 0:5d5265391846 | 45 | while(src[i] != 0) { |
kamilion | 0:5d5265391846 | 46 | |
kamilion | 0:5d5265391846 | 47 | if((src[i] == '\n') || (src[i] == '\r')) { |
kamilion | 0:5d5265391846 | 48 | src[i] = 0; |
kamilion | 0:5d5265391846 | 49 | return i; |
kamilion | 0:5d5265391846 | 50 | } |
kamilion | 0:5d5265391846 | 51 | |
kamilion | 0:5d5265391846 | 52 | i++; |
kamilion | 0:5d5265391846 | 53 | } |
kamilion | 0:5d5265391846 | 54 | |
kamilion | 0:5d5265391846 | 55 | return i; |
kamilion | 0:5d5265391846 | 56 | } |
kamilion | 0:5d5265391846 | 57 | |
kamilion | 0:5d5265391846 | 58 | |
kamilion | 0:5d5265391846 | 59 | // Line Buffers: Get the current level of queue fullness in # of lines |
kamilion | 0:5d5265391846 | 60 | unsigned int SLines_get_fill() |
kamilion | 0:5d5265391846 | 61 | { |
kamilion | 0:5d5265391846 | 62 | unsigned int ret; |
kamilion | 0:5d5265391846 | 63 | |
kamilion | 0:5d5265391846 | 64 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 65 | |
kamilion | 0:5d5265391846 | 66 | ret = (TailLines >= HeadLines ? |
kamilion | 0:5d5265391846 | 67 | TailLines - HeadLines : |
kamilion | 0:5d5265391846 | 68 | NUM_LINES - (HeadLines - TailLines)); |
kamilion | 0:5d5265391846 | 69 | |
kamilion | 0:5d5265391846 | 70 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 71 | |
kamilion | 0:5d5265391846 | 72 | return ret; |
kamilion | 0:5d5265391846 | 73 | } |
kamilion | 0:5d5265391846 | 74 | |
kamilion | 0:5d5265391846 | 75 | |
kamilion | 0:5d5265391846 | 76 | // Line Buffers: Get the current capacity of the queue |
kamilion | 0:5d5265391846 | 77 | unsigned int SLines_get_capacity() |
kamilion | 0:5d5265391846 | 78 | { |
kamilion | 0:5d5265391846 | 79 | return (NUM_LINES - 1); |
kamilion | 0:5d5265391846 | 80 | } |
kamilion | 0:5d5265391846 | 81 | |
kamilion | 0:5d5265391846 | 82 | |
kamilion | 0:5d5265391846 | 83 | // Line Buffers: Put a line into the queue |
kamilion | 0:5d5265391846 | 84 | LINE_T* SLine_put(LINE_T* line) |
kamilion | 0:5d5265391846 | 85 | { |
kamilion | 0:5d5265391846 | 86 | unsigned int fill; |
kamilion | 0:5d5265391846 | 87 | LINE_T* ret; // Empty struct to return |
kamilion | 0:5d5265391846 | 88 | |
kamilion | 0:5d5265391846 | 89 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 90 | |
kamilion | 0:5d5265391846 | 91 | // Are we allowing inserts? If not, just Return a NULL struct early. |
kamilion | 0:5d5265391846 | 92 | if (!AllowInsert) { |
kamilion | 0:5d5265391846 | 93 | ret = NULL; |
kamilion | 0:5d5265391846 | 94 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 95 | |
kamilion | 0:5d5265391846 | 96 | return ret; |
kamilion | 0:5d5265391846 | 97 | } |
kamilion | 0:5d5265391846 | 98 | |
kamilion | 0:5d5265391846 | 99 | fill = (TailLines >= HeadLines ? |
kamilion | 0:5d5265391846 | 100 | TailLines - HeadLines : |
kamilion | 0:5d5265391846 | 101 | NUM_LINES - (HeadLines - TailLines)); |
kamilion | 0:5d5265391846 | 102 | |
kamilion | 0:5d5265391846 | 103 | if (fill != (NUM_LINES - 1)) { |
kamilion | 0:5d5265391846 | 104 | TailLines = (TailLines + 1) % NUM_LINES; |
kamilion | 0:5d5265391846 | 105 | memcpy(&(SLines[TailLines]), line, sizeof(LINE_T)); |
kamilion | 0:5d5265391846 | 106 | ret = &(SLines[TailLines]); |
kamilion | 0:5d5265391846 | 107 | } |
kamilion | 0:5d5265391846 | 108 | else { |
kamilion | 0:5d5265391846 | 109 | ret = NULL; |
kamilion | 0:5d5265391846 | 110 | } |
kamilion | 0:5d5265391846 | 111 | |
kamilion | 0:5d5265391846 | 112 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 113 | |
kamilion | 0:5d5265391846 | 114 | return ret; |
kamilion | 0:5d5265391846 | 115 | } |
kamilion | 0:5d5265391846 | 116 | |
kamilion | 0:5d5265391846 | 117 | // Line Buffers: Get a line from the queue |
kamilion | 0:5d5265391846 | 118 | LINE_T* SLine_get() |
kamilion | 0:5d5265391846 | 119 | { |
kamilion | 0:5d5265391846 | 120 | bool empty; // Is the queue empty? |
kamilion | 0:5d5265391846 | 121 | LINE_T* ret; // Pointer to the line we're about to return |
kamilion | 0:5d5265391846 | 122 | |
kamilion | 0:5d5265391846 | 123 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 124 | |
kamilion | 0:5d5265391846 | 125 | // Check to see if the queue is empty. |
kamilion | 0:5d5265391846 | 126 | empty = (HeadLines == TailLines ? true : false); |
kamilion | 0:5d5265391846 | 127 | |
kamilion | 0:5d5265391846 | 128 | if (!empty) { // if the queue is not empty |
kamilion | 0:5d5265391846 | 129 | ret = &(SLines[HeadLines]); // Return a line. |
kamilion | 0:5d5265391846 | 130 | } |
kamilion | 0:5d5265391846 | 131 | else { // the queue was empty. |
kamilion | 0:5d5265391846 | 132 | ret = NULL; // Return an empty struct. |
kamilion | 0:5d5265391846 | 133 | } |
kamilion | 0:5d5265391846 | 134 | |
kamilion | 0:5d5265391846 | 135 | // Note that the pointer to the line struct that we're returning is only |
kamilion | 0:5d5265391846 | 136 | // guaranteed good until it is removed. In fact, the preservation of |
kamilion | 0:5d5265391846 | 137 | // the data pointed to is the only reason that "get" and "remove" are |
kamilion | 0:5d5265391846 | 138 | // seperate operations. |
kamilion | 0:5d5265391846 | 139 | |
kamilion | 0:5d5265391846 | 140 | __enable_irq(); |
kamilion | 0:5d5265391846 | 141 | |
kamilion | 0:5d5265391846 | 142 | return ret; |
kamilion | 0:5d5265391846 | 143 | } |
kamilion | 0:5d5265391846 | 144 | |
kamilion | 0:5d5265391846 | 145 | |
kamilion | 0:5d5265391846 | 146 | // Line Buffers: Remove the line from the queue once a GET succeeds |
kamilion | 0:5d5265391846 | 147 | void SLine_remove() |
kamilion | 0:5d5265391846 | 148 | { |
kamilion | 0:5d5265391846 | 149 | bool empty; // Is the queue empty? |
kamilion | 0:5d5265391846 | 150 | |
kamilion | 0:5d5265391846 | 151 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 152 | |
kamilion | 0:5d5265391846 | 153 | // Check to see if the queue is empty. |
kamilion | 0:5d5265391846 | 154 | empty = (HeadLines == TailLines ? true : false); |
kamilion | 0:5d5265391846 | 155 | |
kamilion | 0:5d5265391846 | 156 | if (!empty) { // If the queue is not empty... |
kamilion | 0:5d5265391846 | 157 | HeadLines = (HeadLines + 1) % NUM_LINES; // The axe falls, the line expires. |
kamilion | 0:5d5265391846 | 158 | |
kamilion | 0:5d5265391846 | 159 | // The tricky part, of course, is that the data is not |
kamilion | 0:5d5265391846 | 160 | // immediately invalidated. Any pointers to the now-removed line |
kamilion | 0:5d5265391846 | 161 | // will point to valid data until a put() operation overwrites |
kamilion | 0:5d5265391846 | 162 | // the line in question. Of course, the code that removes the line |
kamilion | 0:5d5265391846 | 163 | // won't typically be the code that also performs insertions, so it |
kamilion | 0:5d5265391846 | 164 | // will never know when that happens. Moral of the story: finish what |
kamilion | 0:5d5265391846 | 165 | // you're doing with a gotten line before removing it. |
kamilion | 0:5d5265391846 | 166 | } |
kamilion | 0:5d5265391846 | 167 | |
kamilion | 0:5d5265391846 | 168 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 169 | } |
kamilion | 0:5d5265391846 | 170 | |
kamilion | 0:5d5265391846 | 171 | |
kamilion | 0:5d5265391846 | 172 | // Line Buffers: Clear the queue |
kamilion | 0:5d5265391846 | 173 | void SLine_clear() |
kamilion | 0:5d5265391846 | 174 | { |
kamilion | 0:5d5265391846 | 175 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 176 | HeadLines = TailLines = 0; // Set both ends of the snake at oroboros. |
kamilion | 0:5d5265391846 | 177 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 178 | } |
kamilion | 0:5d5265391846 | 179 | |
kamilion | 0:5d5265391846 | 180 | |
kamilion | 0:5d5265391846 | 181 | // Line Buffers: Open or Close the queue to incoming lines |
kamilion | 0:5d5265391846 | 182 | void SLine_put_control(bool gate) |
kamilion | 0:5d5265391846 | 183 | { |
kamilion | 0:5d5265391846 | 184 | __disable_irq(); // IRQs off, don't bother us, we're working. |
kamilion | 0:5d5265391846 | 185 | AllowInsert = gate; // Set one end of the snake open. |
kamilion | 0:5d5265391846 | 186 | __enable_irq(); // Back to reality, more data calls. |
kamilion | 0:5d5265391846 | 187 | } |