This is a console for interacting with Vodafone dongles.

Dependencies:   mbed-rtos VodafoneUSBModem mbed

This is a bridge between a serial driven console and a serial driven cellular modem or modem interface. This was written to complement our collaboration with mbed: See https://mbed.org/users/mbed_official/code/VodafoneUSBModem/ for further information.

For example, one can use GNU screen or PuTTY (two popular consoles) to interact with a Vodafone K3770 USB dongle. In the image below I used the UNIX version of PuTTY:

/media/uploads/ashleymills/atcons.png

Support is provided for line-based consoles, which send one line at a time, and for character based consoles.

For character based consoles, the following line-editing features are provided:

  • In-line editing (deletion, left/right arrow keys, insertion)
  • Command history (via up/down arrow keys)

Line buffer length, and command history depth, are compile-time options.

--

How to use:

Compile and save to mbed.

Connect PuTTY or GNU screen to serial port.

If you use GNU screen you probably already know what you are doing.

If you use PuTTY, you need to set the options to specify the serial device and, set the baud rate, and set the "Connection Type" to "Serial":

/media/uploads/ashleymills/putty0.png

You need to set the keyboard to send Control-H for backspace, and use "Linux" function keys and keypad:

/media/uploads/ashleymills/putty1.png

Committer:
ashleymills
Date:
Wed Sep 25 08:43:19 2013 +0000
Revision:
14:3f5fd1d95f5f
Parent:
6:93003e18889c
Updated dependencies.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:6c831cc49d22 1 #include "Console.h"
ashleymills 0:6c831cc49d22 2 //#define DEBUG
ashleymills 0:6c831cc49d22 3
ashleymills 4:6971bded3ebd 4 Console::Console(Serial *terminal, int lineLength, int numLines, bool characterBased)
ashleymills 4:6971bded3ebd 5 : _terminal(terminal), _lineLength(lineLength), _numLines(numLines), _characterBased(characterBased) {
ashleymills 0:6c831cc49d22 6
ashleymills 0:6c831cc49d22 7 _terminal->printf("Console ready!\r\n");
ashleymills 0:6c831cc49d22 8
ashleymills 0:6c831cc49d22 9 // set the buffer timeout
ashleymills 5:6841a01b3a69 10 _bufferWaitTimeout_ms = BUFFER_WAIT_TIMEOUT_MS;
ashleymills 4:6971bded3ebd 11
ashleymills 0:6c831cc49d22 12 // allocate space for current line
ashleymills 0:6c831cc49d22 13 _lineBuffer = (char*)malloc((_lineLength+1)*sizeof(char));
ashleymills 4:6971bded3ebd 14
ashleymills 4:6971bded3ebd 15 // character based consoles need a history
ashleymills 4:6971bded3ebd 16 if(_characterBased) {
ashleymills 4:6971bded3ebd 17 _lines = (char**)malloc(_numLines*sizeof(char*));
ashleymills 4:6971bded3ebd 18 for(int i=0; i<_numLines; i++) {
ashleymills 4:6971bded3ebd 19 _lines[i] = (char*)malloc((_lineLength+1)*sizeof(char));
ashleymills 4:6971bded3ebd 20 }
ashleymills 4:6971bded3ebd 21
ashleymills 4:6971bded3ebd 22 // blank out current line with NULLs
ashleymills 4:6971bded3ebd 23 for(int i=0; i<=_lineLength; i++)
ashleymills 4:6971bded3ebd 24 _lineBuffer[i] = 0x00;
ashleymills 0:6c831cc49d22 25 }
ashleymills 0:6c831cc49d22 26
ashleymills 0:6c831cc49d22 27 // set line position, number of used lines, and line buffer pointer to 0
ashleymills 6:93003e18889c 28 _linePos = 0;
ashleymills 0:6c831cc49d22 29 _prevLinePos = 0;
ashleymills 6:93003e18889c 30 _usedLines = 0;
ashleymills 0:6c831cc49d22 31 _currentLine = 0;
ashleymills 0:6c831cc49d22 32 }
ashleymills 0:6c831cc49d22 33
ashleymills 0:6c831cc49d22 34 // destructor
ashleymills 0:6c831cc49d22 35 Console::~Console() {
ashleymills 0:6c831cc49d22 36 free(_lineBuffer);
ashleymills 0:6c831cc49d22 37 }
ashleymills 0:6c831cc49d22 38
ashleymills 0:6c831cc49d22 39 // store the current lineBuffer in the history
ashleymills 0:6c831cc49d22 40 void Console::storeBuffer() {
ashleymills 0:6c831cc49d22 41 // only do so if history specified
ashleymills 0:6c831cc49d22 42 if(_numLines==0)
ashleymills 0:6c831cc49d22 43 return;
ashleymills 0:6c831cc49d22 44
ashleymills 0:6c831cc49d22 45 // imagine the command history as a FILO buffer
ashleymills 0:6c831cc49d22 46 // here we rightshift the command history
ashleymills 0:6c831cc49d22 47 if(_usedLines==_numLines-1) {
ashleymills 0:6c831cc49d22 48 char* p = _lines[0];
ashleymills 0:6c831cc49d22 49 for(int i=0; i<_numLines-1; i++) {
ashleymills 0:6c831cc49d22 50 _lines[i] = _lines[i+1];
ashleymills 0:6c831cc49d22 51 }
ashleymills 0:6c831cc49d22 52 _lines[_numLines-1] = p;
ashleymills 0:6c831cc49d22 53 }
ashleymills 0:6c831cc49d22 54
ashleymills 0:6c831cc49d22 55 // and insert the current line in the newest position
ashleymills 0:6c831cc49d22 56 strncpy(_lines[_usedLines],_lineBuffer,_lineLength+1);
ashleymills 0:6c831cc49d22 57
ashleymills 0:6c831cc49d22 58 // this just deals with the filling up stage
ashleymills 0:6c831cc49d22 59 if(_usedLines<_numLines-1) {
ashleymills 0:6c831cc49d22 60 _usedLines++;
ashleymills 0:6c831cc49d22 61 if(_currentLine<_usedLines)
ashleymills 0:6c831cc49d22 62 _currentLine = _usedLines;
ashleymills 0:6c831cc49d22 63 } else {
ashleymills 0:6c831cc49d22 64 _currentLine = _usedLines+1;
ashleymills 0:6c831cc49d22 65 }
ashleymills 0:6c831cc49d22 66 }
ashleymills 0:6c831cc49d22 67
ashleymills 0:6c831cc49d22 68 // clear the current-line buffer
ashleymills 0:6c831cc49d22 69 void Console::clearBuffer() {
ashleymills 0:6c831cc49d22 70 _linePos=0;
ashleymills 0:6c831cc49d22 71 for(int i=0; i<=_lineLength; i++)
ashleymills 0:6c831cc49d22 72 _lineBuffer[i] = 0x00;
ashleymills 0:6c831cc49d22 73 }
ashleymills 0:6c831cc49d22 74
ashleymills 0:6c831cc49d22 75 // load the next buffer in the line history (activated by DOWN key)
ashleymills 0:6c831cc49d22 76 void Console::loadNextBuffer() {
ashleymills 0:6c831cc49d22 77 if(_currentLine<_usedLines) {
ashleymills 0:6c831cc49d22 78 _currentLine++;
ashleymills 0:6c831cc49d22 79 } else {
ashleymills 0:6c831cc49d22 80 _linePos=0;
ashleymills 0:6c831cc49d22 81 for(int i=0; i<=_lineLength; i++)
ashleymills 0:6c831cc49d22 82 _lineBuffer[i] = 0x00;
ashleymills 0:6c831cc49d22 83 return;
ashleymills 0:6c831cc49d22 84 }
ashleymills 0:6c831cc49d22 85 strncpy(_lineBuffer,_lines[_currentLine],_lineLength+1);
ashleymills 0:6c831cc49d22 86 _prevLinePos = _linePos;
ashleymills 0:6c831cc49d22 87 _linePos=0;
ashleymills 0:6c831cc49d22 88 while(_lineBuffer[_linePos]!=0x00)
ashleymills 0:6c831cc49d22 89 _linePos++;
ashleymills 0:6c831cc49d22 90 }
ashleymills 0:6c831cc49d22 91
ashleymills 0:6c831cc49d22 92 // load the previous buffer in the line history (activated by UP key)
ashleymills 0:6c831cc49d22 93 void Console::loadPreviousBuffer() {
ashleymills 0:6c831cc49d22 94 if(_currentLine>0) {
ashleymills 0:6c831cc49d22 95 _currentLine--;
ashleymills 0:6c831cc49d22 96 }
ashleymills 0:6c831cc49d22 97 strncpy(_lineBuffer,_lines[_currentLine],_lineLength+1);
ashleymills 0:6c831cc49d22 98 _prevLinePos = _linePos;
ashleymills 0:6c831cc49d22 99 _linePos=0;
ashleymills 0:6c831cc49d22 100 while(_lineBuffer[_linePos]!=0x00)
ashleymills 0:6c831cc49d22 101 _linePos++;
ashleymills 0:6c831cc49d22 102 }
ashleymills 0:6c831cc49d22 103
ashleymills 0:6c831cc49d22 104 // process a command entered (received by CRLF)
ashleymills 0:6c831cc49d22 105 void Console::processCommand() {
ashleymills 0:6c831cc49d22 106 _terminal->printf("Command: \"%s\"\r\n",_lineBuffer);
ashleymills 0:6c831cc49d22 107 }
ashleymills 0:6c831cc49d22 108
ashleymills 0:6c831cc49d22 109 // wait on the console for input, returns false on timeout
ashleymills 0:6c831cc49d22 110 // this is useful for processing escape chars
ashleymills 0:6c831cc49d22 111 bool Console::waitForInput() {
ashleymills 5:6841a01b3a69 112 Timer timer;
ashleymills 5:6841a01b3a69 113 timer.start();
ashleymills 5:6841a01b3a69 114 while(!_terminal->readable()&&timer.read_ms()<_bufferWaitTimeout_ms);
ashleymills 0:6c831cc49d22 115 return _terminal->readable();
ashleymills 0:6c831cc49d22 116 }
ashleymills 0:6c831cc49d22 117
ashleymills 0:6c831cc49d22 118 // print the entire command history
ashleymills 0:6c831cc49d22 119 void Console::printHistory() {
ashleymills 0:6c831cc49d22 120 for(int i=0; i<_numLines; i++)
ashleymills 0:6c831cc49d22 121 printBuffer(i);
ashleymills 0:6c831cc49d22 122 }
ashleymills 0:6c831cc49d22 123
ashleymills 0:6c831cc49d22 124 // print the command at index in the history
ashleymills 0:6c831cc49d22 125 void Console::printBuffer(int index) {
ashleymills 0:6c831cc49d22 126 if(index==_currentLine)
ashleymills 0:6c831cc49d22 127 _terminal->printf("> ");
ashleymills 0:6c831cc49d22 128 else
ashleymills 0:6c831cc49d22 129 _terminal->printf(" ");
ashleymills 0:6c831cc49d22 130 _terminal->printf("%d) \"%s\"\r\n",index,_lines[index]);
ashleymills 0:6c831cc49d22 131 }
ashleymills 0:6c831cc49d22 132
ashleymills 4:6971bded3ebd 133
ashleymills 0:6c831cc49d22 134 void Console::reprintBuffer() {
ashleymills 0:6c831cc49d22 135 _terminal->putc('\r');
ashleymills 0:6c831cc49d22 136 for(int i=0; i<_lineLength; i++) {;
ashleymills 0:6c831cc49d22 137 _terminal->putc(' ');
ashleymills 0:6c831cc49d22 138 }
ashleymills 4:6971bded3ebd 139
ashleymills 0:6c831cc49d22 140 _terminal->putc('\r');
ashleymills 0:6c831cc49d22 141 if(_linePos>0) {
ashleymills 0:6c831cc49d22 142 _terminal->printf("%s",_lineBuffer);
ashleymills 0:6c831cc49d22 143 _terminal->putc('\r');
ashleymills 0:6c831cc49d22 144 for(int i=0; i<_linePos; i++) {;
ashleymills 0:6c831cc49d22 145 _terminal->putc(0x1b);
ashleymills 0:6c831cc49d22 146 _terminal->putc('[');
ashleymills 0:6c831cc49d22 147 _terminal->putc('C');
ashleymills 0:6c831cc49d22 148 }
ashleymills 0:6c831cc49d22 149 }
ashleymills 0:6c831cc49d22 150 }
ashleymills 0:6c831cc49d22 151
ashleymills 0:6c831cc49d22 152 // print the current-line buffer including debugging stuff
ashleymills 0:6c831cc49d22 153 void Console::printLineBuffer() {
ashleymills 0:6c831cc49d22 154 printHistory();
ashleymills 0:6c831cc49d22 155 _terminal->printf("C) \"%s\"\r\n",_lineBuffer);
ashleymills 0:6c831cc49d22 156 _terminal->printf(" \"");
ashleymills 0:6c831cc49d22 157 for(int i=0; i<_linePos; i++) {
ashleymills 0:6c831cc49d22 158 _terminal->printf(" ");
ashleymills 0:6c831cc49d22 159 }
ashleymills 0:6c831cc49d22 160 _terminal->printf("^");
ashleymills 0:6c831cc49d22 161 for(int i=_linePos+1; i<_lineLength; i++) {
ashleymills 0:6c831cc49d22 162 _terminal->printf(" ");
ashleymills 0:6c831cc49d22 163 }
ashleymills 0:6c831cc49d22 164 _terminal->printf("\"\r\n");
ashleymills 0:6c831cc49d22 165 for(int i=0; i<=_lineLength; i++) {
ashleymills 0:6c831cc49d22 166 _terminal->printf("%x ",_lineBuffer[i]);
ashleymills 0:6c831cc49d22 167 }
ashleymills 0:6c831cc49d22 168 _terminal->printf("\r\n");
ashleymills 0:6c831cc49d22 169 }
ashleymills 0:6c831cc49d22 170
ashleymills 4:6971bded3ebd 171 void Console::updateLineBased() {
ashleymills 4:6971bded3ebd 172 //_terminal->printf("line based\r\n");
ashleymills 4:6971bded3ebd 173 // save until a line is read and then dump to the modem
ashleymills 4:6971bded3ebd 174 while(_terminal->readable()) {
ashleymills 4:6971bded3ebd 175 int c = _terminal->getc();
ashleymills 4:6971bded3ebd 176 if(_linePos<_lineLength) {
ashleymills 4:6971bded3ebd 177
ashleymills 4:6971bded3ebd 178 _lineBuffer[_linePos++] = c;
ashleymills 4:6971bded3ebd 179 _terminal->printf("%c",c);
ashleymills 4:6971bded3ebd 180 // activate process command when
ashleymills 4:6971bded3ebd 181 if(c==0x0a) {
ashleymills 4:6971bded3ebd 182 processCommand();
ashleymills 4:6971bded3ebd 183 clearBuffer();
ashleymills 4:6971bded3ebd 184 return;
ashleymills 4:6971bded3ebd 185 }
ashleymills 4:6971bded3ebd 186 } else {
ashleymills 4:6971bded3ebd 187 _terminal->printf("WARNING, max line length exceeded!!!");
ashleymills 4:6971bded3ebd 188 }
ashleymills 4:6971bded3ebd 189
ashleymills 4:6971bded3ebd 190 }
ashleymills 4:6971bded3ebd 191 }
ashleymills 4:6971bded3ebd 192
ashleymills 4:6971bded3ebd 193 void Console::updateCharacterBased() {
ashleymills 4:6971bded3ebd 194 // process console input
ashleymills 0:6c831cc49d22 195 while(_terminal->readable()) {
ashleymills 0:6c831cc49d22 196 int c = _terminal->getc();
ashleymills 0:6c831cc49d22 197 switch(c) {
ashleymills 0:6c831cc49d22 198 // backspace
ashleymills 0:6c831cc49d22 199 case 0x08:
ashleymills 0:6c831cc49d22 200 if(_linePos>0) {
ashleymills 0:6c831cc49d22 201 // case where pointer is at end of line
ashleymills 0:6c831cc49d22 202 if(_lineBuffer[_linePos]==0x00) {
ashleymills 0:6c831cc49d22 203 _lineBuffer[--_linePos] = 0x00;
ashleymills 0:6c831cc49d22 204 } else {
ashleymills 0:6c831cc49d22 205 // case where pointer is somewhere in the middle of the line
ashleymills 0:6c831cc49d22 206 int copyPointer = --_linePos;
ashleymills 0:6c831cc49d22 207 while(_lineBuffer[copyPointer]!=0x00) {
ashleymills 0:6c831cc49d22 208 _lineBuffer[copyPointer] = _lineBuffer[copyPointer+1];
ashleymills 0:6c831cc49d22 209 copyPointer++;
ashleymills 0:6c831cc49d22 210 }
ashleymills 0:6c831cc49d22 211 }
ashleymills 4:6971bded3ebd 212
ashleymills 0:6c831cc49d22 213 reprintBuffer();
ashleymills 0:6c831cc49d22 214 }
ashleymills 0:6c831cc49d22 215 break;
ashleymills 0:6c831cc49d22 216
ashleymills 0:6c831cc49d22 217 // escape sequence 0x1b 0x5b
ashleymills 0:6c831cc49d22 218 case 0x1b:
ashleymills 0:6c831cc49d22 219 // check that escape sequence exists
ashleymills 0:6c831cc49d22 220 if(waitForInput()&&_terminal->getc()==0x5b) {
ashleymills 0:6c831cc49d22 221
ashleymills 0:6c831cc49d22 222 // process escape characters
ashleymills 0:6c831cc49d22 223 if(waitForInput()) {
ashleymills 0:6c831cc49d22 224 c = _terminal->getc();
ashleymills 0:6c831cc49d22 225 switch(c) {
ashleymills 0:6c831cc49d22 226 // up
ashleymills 0:6c831cc49d22 227 case 0x41:
ashleymills 0:6c831cc49d22 228 loadPreviousBuffer();
ashleymills 0:6c831cc49d22 229 reprintBuffer();
ashleymills 0:6c831cc49d22 230 break;
ashleymills 0:6c831cc49d22 231
ashleymills 0:6c831cc49d22 232 // down
ashleymills 0:6c831cc49d22 233 case 0x42:
ashleymills 0:6c831cc49d22 234 loadNextBuffer();
ashleymills 0:6c831cc49d22 235 reprintBuffer();
ashleymills 0:6c831cc49d22 236 break;
ashleymills 0:6c831cc49d22 237
ashleymills 0:6c831cc49d22 238 // left
ashleymills 0:6c831cc49d22 239 case 0x44:
ashleymills 0:6c831cc49d22 240 if(_linePos>0) {
ashleymills 0:6c831cc49d22 241 _linePos--;
ashleymills 0:6c831cc49d22 242 _terminal->putc('\b');
ashleymills 0:6c831cc49d22 243 }
ashleymills 0:6c831cc49d22 244 break;
ashleymills 0:6c831cc49d22 245
ashleymills 0:6c831cc49d22 246 // right
ashleymills 0:6c831cc49d22 247 case 0x43:
ashleymills 0:6c831cc49d22 248 // only move right within a string upto its end
ashleymills 0:6c831cc49d22 249 if(_lineBuffer[_linePos]!=0x00) {
ashleymills 0:6c831cc49d22 250 _linePos++;
ashleymills 0:6c831cc49d22 251 _terminal->putc(0x1b);
ashleymills 0:6c831cc49d22 252 _terminal->putc('[');
ashleymills 0:6c831cc49d22 253 _terminal->putc('C');
ashleymills 0:6c831cc49d22 254 }
ashleymills 0:6c831cc49d22 255 break;
ashleymills 0:6c831cc49d22 256 }
ashleymills 0:6c831cc49d22 257 }
ashleymills 0:6c831cc49d22 258 }
ashleymills 0:6c831cc49d22 259 break;
ashleymills 0:6c831cc49d22 260
ashleymills 0:6c831cc49d22 261 // carriage return
ashleymills 0:6c831cc49d22 262 case 0x0d:
ashleymills 0:6c831cc49d22 263 storeBuffer();
ashleymills 0:6c831cc49d22 264 processCommand();
ashleymills 0:6c831cc49d22 265 clearBuffer();
ashleymills 0:6c831cc49d22 266 break;
ashleymills 0:6c831cc49d22 267
ashleymills 0:6c831cc49d22 268 default:
ashleymills 0:6c831cc49d22 269 if(_linePos<_lineLength) {
ashleymills 0:6c831cc49d22 270 // INS mode
ashleymills 0:6c831cc49d22 271 if(false) {
ashleymills 0:6c831cc49d22 272 _lineBuffer[_linePos++] = c;
ashleymills 0:6c831cc49d22 273 _terminal->printf("%c",c);
ashleymills 0:6c831cc49d22 274 } else {
ashleymills 0:6c831cc49d22 275 if(_lineBuffer[_linePos]==0x00) {
ashleymills 0:6c831cc49d22 276 _lineBuffer[_linePos++] = c;
ashleymills 0:6c831cc49d22 277 } else {
ashleymills 0:6c831cc49d22 278 // move everything to the right
ashleymills 0:6c831cc49d22 279 // so long as string end isn't at end of buffer
ashleymills 0:6c831cc49d22 280 int strEnd = _linePos;
ashleymills 0:6c831cc49d22 281 while(_lineBuffer[++strEnd]!=0x00);
ashleymills 0:6c831cc49d22 282 if(strEnd!=_lineLength) {
ashleymills 0:6c831cc49d22 283 int copyPointer = _lineLength;
ashleymills 0:6c831cc49d22 284 while(--copyPointer!=_linePos) {
ashleymills 0:6c831cc49d22 285 _lineBuffer[copyPointer] = _lineBuffer[copyPointer-1];
ashleymills 0:6c831cc49d22 286 }
ashleymills 0:6c831cc49d22 287
ashleymills 0:6c831cc49d22 288 // insert character
ashleymills 0:6c831cc49d22 289 _lineBuffer[_linePos++] = c;
ashleymills 0:6c831cc49d22 290 }
ashleymills 0:6c831cc49d22 291 }
ashleymills 0:6c831cc49d22 292 reprintBuffer();
ashleymills 0:6c831cc49d22 293 }
ashleymills 0:6c831cc49d22 294
ashleymills 0:6c831cc49d22 295 }
ashleymills 0:6c831cc49d22 296
ashleymills 0:6c831cc49d22 297 break;
ashleymills 0:6c831cc49d22 298 }
ashleymills 0:6c831cc49d22 299
ashleymills 0:6c831cc49d22 300 #ifdef DEBUG
ashleymills 0:6c831cc49d22 301 printLineBuffer();
ashleymills 0:6c831cc49d22 302 #endif
ashleymills 0:6c831cc49d22 303 }
ashleymills 4:6971bded3ebd 304 }
ashleymills 4:6971bded3ebd 305
ashleymills 4:6971bded3ebd 306 // process the console
ashleymills 4:6971bded3ebd 307 void Console::update() {
ashleymills 4:6971bded3ebd 308 if(_characterBased) {
ashleymills 4:6971bded3ebd 309 updateCharacterBased();
ashleymills 4:6971bded3ebd 310 } else {
ashleymills 4:6971bded3ebd 311 updateLineBased();
ashleymills 4:6971bded3ebd 312 }
ashleymills 0:6c831cc49d22 313 }