uTerminal is a simple AT-command style terminal processor, simplifying the work to send and parse COMMAND=value pairs to a microcontroller.

Dependencies:   USBDevice

Dependents:   uTerminal_Example

Committer:
fbcosentino
Date:
Thu Feb 21 14:51:43 2019 +0000
Revision:
3:39fb12e8a2a3
Parent:
2:8029cce18e1a
bug fixes

Who changed what in which revision?

UserRevisionLine numberNew contents of line
fbcosentino 0:1655adb3a46e 1 #include "uTerminal.h"
fbcosentino 0:1655adb3a46e 2
fbcosentino 1:4e304b58f597 3 uTerminal::uTerminal(PinName PinTX, PinName PinRX) {
fbcosentino 1:4e304b58f597 4 is_usb = 0;
fbcosentino 1:4e304b58f597 5 _serial = new Serial(PinTX, PinRX);
fbcosentino 1:4e304b58f597 6 _serial->attach(this, &uTerminal::_rx_irq, Serial::RxIrq);
fbcosentino 1:4e304b58f597 7 init();
fbcosentino 1:4e304b58f597 8 }
fbcosentino 1:4e304b58f597 9
fbcosentino 1:4e304b58f597 10 uTerminal::uTerminal(Serial * serial_object) {
fbcosentino 1:4e304b58f597 11 is_usb = 0;
fbcosentino 1:4e304b58f597 12 _serial = serial_object;
fbcosentino 1:4e304b58f597 13 _serial->attach(this, &uTerminal::_rx_irq, Serial::RxIrq);
fbcosentino 1:4e304b58f597 14 init();
fbcosentino 1:4e304b58f597 15 }
fbcosentino 1:4e304b58f597 16
fbcosentino 1:4e304b58f597 17 uTerminal::uTerminal(USBSerial * usbserial_object) {
fbcosentino 1:4e304b58f597 18 is_usb = 1;
fbcosentino 1:4e304b58f597 19 _usbserial = usbserial_object;
fbcosentino 1:4e304b58f597 20 _usbserial->attach(this, &uTerminal::_rx_irq);
fbcosentino 1:4e304b58f597 21 init();
fbcosentino 1:4e304b58f597 22 }
fbcosentino 1:4e304b58f597 23
fbcosentino 1:4e304b58f597 24 void uTerminal::init() {
fbcosentino 0:1655adb3a46e 25 _callback = 0;
fbcosentino 0:1655adb3a46e 26 cursor = 0;
fbcosentino 0:1655adb3a46e 27 param_cursor = 0;
fbcosentino 0:1655adb3a46e 28 buffer_len = 0;
fbcosentino 0:1655adb3a46e 29 params_len = 0;
fbcosentino 0:1655adb3a46e 30 has_command = 0;
fbcosentino 0:1655adb3a46e 31 NumParams = 0;
fbcosentino 0:1655adb3a46e 32 ParamLen = 0;
fbcosentino 0:1655adb3a46e 33 auto_mode = 0;
fbcosentino 0:1655adb3a46e 34 }
fbcosentino 0:1655adb3a46e 35
fbcosentino 1:4e304b58f597 36 bool uTerminal::readable() {
fbcosentino 1:4e304b58f597 37 if (is_usb) {
fbcosentino 1:4e304b58f597 38 if (_usbserial->connected()) return _usbserial->readable();
fbcosentino 1:4e304b58f597 39 else return 0;
fbcosentino 1:4e304b58f597 40 }
fbcosentino 1:4e304b58f597 41 else return _serial->readable();
fbcosentino 1:4e304b58f597 42 }
fbcosentino 1:4e304b58f597 43 unsigned char uTerminal::getc() {
fbcosentino 1:4e304b58f597 44 if (is_usb) {
fbcosentino 1:4e304b58f597 45 if (_usbserial->connected()) return _usbserial->getc();
fbcosentino 1:4e304b58f597 46 else return 0;
fbcosentino 1:4e304b58f597 47 }
fbcosentino 1:4e304b58f597 48 else return _serial->getc();
fbcosentino 1:4e304b58f597 49 }
fbcosentino 1:4e304b58f597 50
fbcosentino 0:1655adb3a46e 51 void uTerminal::ModeAuto() {
fbcosentino 0:1655adb3a46e 52 auto_mode = 1;
fbcosentino 0:1655adb3a46e 53 }
fbcosentino 0:1655adb3a46e 54
fbcosentino 0:1655adb3a46e 55 void uTerminal::ModeManual() {
fbcosentino 0:1655adb3a46e 56 auto_mode = 0;
fbcosentino 0:1655adb3a46e 57 }
fbcosentino 0:1655adb3a46e 58
fbcosentino 0:1655adb3a46e 59 void uTerminal::attach( void (*callback)() ) {
fbcosentino 0:1655adb3a46e 60 _callback = callback;
fbcosentino 0:1655adb3a46e 61 }
fbcosentino 0:1655adb3a46e 62
fbcosentino 0:1655adb3a46e 63 void uTerminal::_rx_irq() {
fbcosentino 0:1655adb3a46e 64 unsigned char val;
fbcosentino 1:4e304b58f597 65 if(readable()) {
fbcosentino 1:4e304b58f597 66 val = getc();
fbcosentino 0:1655adb3a46e 67 if ((val == 10) || (val == 13)) {
fbcosentino 0:1655adb3a46e 68 // Received a return character (Linux = 10, Windows = 13,10)
fbcosentino 0:1655adb3a46e 69 // When #13#10 is received, the #10 will trigger this "if" with empty command. Ignore it.
fbcosentino 0:1655adb3a46e 70 if (cursor > 0) {
fbcosentino 0:1655adb3a46e 71 // Ok, we indeed have a command.
fbcosentino 0:1655adb3a46e 72 has_command = 1; // 1-> Successful command (return). 2->Buffer full
fbcosentino 3:39fb12e8a2a3 73 _buffer[cursor++] = 0x00; // make a null-terminated safe string
fbcosentino 3:39fb12e8a2a3 74 buffer_len = cursor; // Includes terminating null
fbcosentino 0:1655adb3a46e 75 cursor = 0;
fbcosentino 0:1655adb3a46e 76 transfer_buffers(); // prepare the Command and Value buffers
fbcosentino 0:1655adb3a46e 77 }
fbcosentino 0:1655adb3a46e 78 }
fbcosentino 0:1655adb3a46e 79 else {
fbcosentino 0:1655adb3a46e 80 has_command = 0; // If had unread command in buffer, cancel it. Sorry, you lost it.
fbcosentino 3:39fb12e8a2a3 81 _buffer[cursor++] = val;
fbcosentino 0:1655adb3a46e 82 if (cursor >= UTERMINAL_BUF_SIZE) {
fbcosentino 0:1655adb3a46e 83 // Even if it's not a return, we must not continue since buffer is full
fbcosentino 0:1655adb3a46e 84 // Consider input done, but with result=2 instead of 1, to tell it's buffer size
fbcosentino 0:1655adb3a46e 85 has_command = 2;
fbcosentino 0:1655adb3a46e 86 buffer_len = UTERMINAL_BUF_SIZE; // all valid characters
fbcosentino 0:1655adb3a46e 87 _buffer[cursor] = 0x00; // make a null-terminated safe string
fbcosentino 0:1655adb3a46e 88 cursor = 0; // reset cursor to avoid overflow
fbcosentino 0:1655adb3a46e 89 transfer_buffers(); // prepare the Command and Value buffers
fbcosentino 0:1655adb3a46e 90 }
fbcosentino 0:1655adb3a46e 91 }
fbcosentino 0:1655adb3a46e 92 }
fbcosentino 0:1655adb3a46e 93 }
fbcosentino 0:1655adb3a46e 94
fbcosentino 0:1655adb3a46e 95 void uTerminal::transfer_buffers() {
fbcosentino 0:1655adb3a46e 96 int i;
fbcosentino 0:1655adb3a46e 97 int j;
fbcosentino 0:1655adb3a46e 98 char c;
fbcosentino 0:1655adb3a46e 99
fbcosentino 0:1655adb3a46e 100 // transfer cmd buffer
fbcosentino 0:1655adb3a46e 101 i = 0;
fbcosentino 0:1655adb3a46e 102 j = 0;
fbcosentino 0:1655adb3a46e 103 while (i < buffer_len) {
fbcosentino 0:1655adb3a46e 104 c = _buffer[i++];
fbcosentino 0:1655adb3a46e 105 if ((c == '=') || (c == 0)) {
fbcosentino 0:1655adb3a46e 106 Command[j] = 0; // null-terminated string
fbcosentino 0:1655adb3a46e 107 break;
fbcosentino 0:1655adb3a46e 108 }
fbcosentino 0:1655adb3a46e 109 else {
fbcosentino 0:1655adb3a46e 110 Command[j++] = c;
fbcosentino 0:1655adb3a46e 111 }
fbcosentino 0:1655adb3a46e 112 }
fbcosentino 3:39fb12e8a2a3 113 if (i >= buffer_len) Command[j] = 0; // null-terminated safe
fbcosentino 0:1655adb3a46e 114
fbcosentino 0:1655adb3a46e 115 // transfer param buffer
fbcosentino 0:1655adb3a46e 116 if (c == '=') { // if we have parameters
fbcosentino 0:1655adb3a46e 117 NumParams = 1;
fbcosentino 0:1655adb3a46e 118 j = 0;
fbcosentino 0:1655adb3a46e 119 while (i < buffer_len) {
fbcosentino 0:1655adb3a46e 120 c = _buffer[i++];
fbcosentino 0:1655adb3a46e 121 Value[j++] = c;
fbcosentino 0:1655adb3a46e 122 if (c == ',') NumParams++;
fbcosentino 0:1655adb3a46e 123 if (c == 0) break;
fbcosentino 0:1655adb3a46e 124 }
fbcosentino 3:39fb12e8a2a3 125 params_len = j; // length includes terminating null
fbcosentino 0:1655adb3a46e 126 }
fbcosentino 0:1655adb3a46e 127 else {
fbcosentino 0:1655adb3a46e 128 Value[0] = 0; // empty string
fbcosentino 0:1655adb3a46e 129 NumParams = 0;
fbcosentino 0:1655adb3a46e 130 params_len = 0;
fbcosentino 0:1655adb3a46e 131 }
fbcosentino 0:1655adb3a46e 132
fbcosentino 0:1655adb3a46e 133 Param[0] = 0; // Param always begins as empty string
fbcosentino 0:1655adb3a46e 134 ParamLen = 0;
fbcosentino 0:1655adb3a46e 135
fbcosentino 0:1655adb3a46e 136 param_cursor = 0;
fbcosentino 0:1655adb3a46e 137
fbcosentino 0:1655adb3a46e 138 // If in auto-mode, invoke the callback
fbcosentino 0:1655adb3a46e 139 if (auto_mode) Process();
fbcosentino 0:1655adb3a46e 140 }
fbcosentino 0:1655adb3a46e 141
fbcosentino 0:1655adb3a46e 142 char* uTerminal::GetParam() {
fbcosentino 0:1655adb3a46e 143 int i;
fbcosentino 0:1655adb3a46e 144 char c;
fbcosentino 0:1655adb3a46e 145
fbcosentino 0:1655adb3a46e 146 i = 0;
fbcosentino 0:1655adb3a46e 147 while (param_cursor < params_len) {
fbcosentino 0:1655adb3a46e 148 c = Value[param_cursor];
fbcosentino 0:1655adb3a46e 149 if (c == ',') {
fbcosentino 0:1655adb3a46e 150 Param[i] = 0;
fbcosentino 0:1655adb3a46e 151 param_cursor++;
fbcosentino 0:1655adb3a46e 152 break;
fbcosentino 0:1655adb3a46e 153 }
fbcosentino 0:1655adb3a46e 154 if (c == 0) {
fbcosentino 0:1655adb3a46e 155 Param[i] = 0;
fbcosentino 0:1655adb3a46e 156 break;
fbcosentino 0:1655adb3a46e 157 }
fbcosentino 0:1655adb3a46e 158 else {
fbcosentino 0:1655adb3a46e 159 Param[i++] = c;
fbcosentino 0:1655adb3a46e 160 param_cursor++;
fbcosentino 0:1655adb3a46e 161 }
fbcosentino 0:1655adb3a46e 162 }
fbcosentino 0:1655adb3a46e 163 if (param_cursor >= params_len) Param[i] = 0; // null-terminated safe
fbcosentino 0:1655adb3a46e 164
fbcosentino 0:1655adb3a46e 165 ParamLen = i; // does not include terminating null
fbcosentino 0:1655adb3a46e 166
fbcosentino 0:1655adb3a46e 167 return Param;
fbcosentino 0:1655adb3a46e 168 }
fbcosentino 0:1655adb3a46e 169
fbcosentino 0:1655adb3a46e 170
fbcosentino 0:1655adb3a46e 171 int uTerminal::Process() {
fbcosentino 0:1655adb3a46e 172 // Be ready for next message in the background
fbcosentino 0:1655adb3a46e 173 int _has_cmd = has_command;
fbcosentino 0:1655adb3a46e 174 has_command = 0;
fbcosentino 0:1655adb3a46e 175
fbcosentino 0:1655adb3a46e 176 // invoke the callback
fbcosentino 0:1655adb3a46e 177 if ((_has_cmd > 0) && (_callback != 0)) _callback();
fbcosentino 0:1655adb3a46e 178
fbcosentino 0:1655adb3a46e 179 // Return status
fbcosentino 0:1655adb3a46e 180 return _has_cmd;
fbcosentino 0:1655adb3a46e 181 }
fbcosentino 0:1655adb3a46e 182
fbcosentino 0:1655adb3a46e 183 void uTerminal::print(char* str) {
fbcosentino 1:4e304b58f597 184 if (is_usb) {
fbcosentino 1:4e304b58f597 185 while (!_usbserial->connected()); // block until connected
fbcosentino 1:4e304b58f597 186 _usbserial->printf(str);
fbcosentino 1:4e304b58f597 187 }
fbcosentino 1:4e304b58f597 188 else _serial->printf(str);
fbcosentino 0:1655adb3a46e 189 }
fbcosentino 0:1655adb3a46e 190
fbcosentino 0:1655adb3a46e 191 void uTerminal::print(const char* str) {
fbcosentino 1:4e304b58f597 192 print((char*)str);
fbcosentino 0:1655adb3a46e 193 }
fbcosentino 0:1655adb3a46e 194