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

Committer:
kamilion
Date:
Thu Nov 06 01:57:54 2014 +0000
Revision:
1:29f6c660d174
Parent:
0:5d5265391846
trying to make telnetserver repo public

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kamilion 0:5d5265391846 1 // Telnet UART MUX server
kamilion 0:5d5265391846 2 // This application will buffer and send lines from up to
kamilion 0:5d5265391846 3 // three serial devices and USB host when connected to via TCP.
kamilion 0:5d5265391846 4 // Written, 02/10/2011-2/14/2011 by Graham Cantin and
kamilion 0:5d5265391846 5 // Special Guest Appearance from Sasha Jevtic (Patron Diety of Queues)
kamilion 0:5d5265391846 6
kamilion 0:5d5265391846 7 /*
kamilion 0:5d5265391846 8 "Have you looked on the underside of the mBed?"
kamilion 0:5d5265391846 9 There's a chip marked "mBed Interface" which is an 8-bit
kamilion 0:5d5265391846 10 microcontroller in it's own right and an AT45DB161 16Mbit flash device.
kamilion 0:5d5265391846 11 It's the "backend" of the mBed system you are seeing,
kamilion 0:5d5265391846 12 not the target LPC1768 device on the top side of the mBed.
kamilion 0:5d5265391846 13 This interface exposes the flash device as a FAT partition over USB,
kamilion 0:5d5265391846 14 and also handles resetting the LPC1768 when a serial break occurs.
kamilion 0:5d5265391846 15 */
kamilion 0:5d5265391846 16
kamilion 0:5d5265391846 17 // 02/14/2011: Added a hard fault handler. Please improve if you've got a bit of time.
kamilion 0:5d5265391846 18
kamilion 0:5d5265391846 19 // ------ Defines ------
kamilion 0:5d5265391846 20
kamilion 0:5d5265391846 21 // DEBUG LOGGING
kamilion 0:5d5265391846 22 #define DEBUG
kamilion 0:5d5265391846 23
kamilion 0:5d5265391846 24 // DHCP OR STATIC IP?
kamilion 0:5d5265391846 25 #define DHCP
kamilion 0:5d5265391846 26
kamilion 0:5d5265391846 27 // What port do we listen on?
kamilion 0:5d5265391846 28 #define TCP_LISTENING_PORT 3001
kamilion 0:5d5265391846 29
kamilion 0:5d5265391846 30 // 9600, 14400, 19200, 38400, 57600, 115200, 230400, 460800 (too fast), 921600 (way too fast)
kamilion 0:5d5265391846 31 #define HOST_BAUD 115200
kamilion 0:5d5265391846 32 #define MODSERIAL_DEFAULT_RX_BUFFER_SIZE 2048
kamilion 0:5d5265391846 33 #define MODSERIAL_DEFAULT_TX_BUFFER_SIZE 384
kamilion 0:5d5265391846 34 #define MESSAGE_BUFFER_SIZE 256
kamilion 0:5d5265391846 35 #define TS_PAD 10
kamilion 0:5d5265391846 36 #define TX_CHUNK 30
kamilion 0:5d5265391846 37 #define MAX_LINES_PER_ITER 10
kamilion 0:5d5265391846 38 #define Q_ALERT_THRESH 70
kamilion 0:5d5265391846 39
kamilion 0:5d5265391846 40 // ------ Includes ------
kamilion 0:5d5265391846 41
kamilion 0:5d5265391846 42 #include "mbed.h"
kamilion 0:5d5265391846 43 #include "line_util.h"
kamilion 0:5d5265391846 44 #include "EthernetNetIf.h"
kamilion 0:5d5265391846 45 #include "TCPSocket.h"
kamilion 0:5d5265391846 46 #include "NTPClient.h"
kamilion 0:5d5265391846 47 #include "MODDMA.h"
kamilion 0:5d5265391846 48 #include "MODSERIAL.h"
kamilion 0:5d5265391846 49 #include "GPS.h"
kamilion 0:5d5265391846 50
kamilion 0:5d5265391846 51 // ------ Constants ------
kamilion 0:5d5265391846 52
kamilion 0:5d5265391846 53 const char BannerText[] = "**** Software Build Date : "__DATE__" "__TIME__" ****\r\n";
kamilion 0:5d5265391846 54 const char REC_SEP[] = "\r\n";
kamilion 0:5d5265391846 55
kamilion 0:5d5265391846 56 // ------ Reset & Crash ------
kamilion 0:5d5265391846 57
kamilion 0:5d5265391846 58 extern "C" void mbed_reset(); // Ask for soft-reset (like pressing the button)
kamilion 0:5d5265391846 59 extern "C" void NVIC_SystemReset(); // Force a hard reset by calling the low level raw function.
kamilion 0:5d5265391846 60
kamilion 0:5d5265391846 61 // Handles a hard fault with a reset. SEE: http://mbed.org/forum/mbed/post/2843/
kamilion 0:5d5265391846 62 extern "C" void HardFault_Handler() { printf("HARD FAULT!\r\n"); NVIC_SystemReset(); }
kamilion 0:5d5265391846 63 // SEE: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0337g/Babcefea.html
kamilion 0:5d5265391846 64 // Could be handled better.
kamilion 0:5d5265391846 65 // MBED WATCHDOGS: http://mbed.org/forum/mbed/post/3276/
kamilion 0:5d5265391846 66
kamilion 0:5d5265391846 67
kamilion 0:5d5265391846 68 // ------ Timers -----
kamilion 0:5d5265391846 69 // Note that timers are based on 32-bit int microsecond (us) counters,
kamilion 0:5d5265391846 70 // so can only time up to a maximum of 2^31-1 microseconds i.e. 30 minutes.
kamilion 0:5d5265391846 71 Timer highres; // for reading
kamilion 0:5d5265391846 72
kamilion 0:5d5265391846 73 // ------ LEDS -----
kamilion 0:5d5265391846 74
kamilion 0:5d5265391846 75 PwmOut led1(LED1, "led1");
kamilion 0:5d5265391846 76 PwmOut led2(LED2, "led2");
kamilion 0:5d5265391846 77 PwmOut led3(LED3, "led3");
kamilion 0:5d5265391846 78 PwmOut led4(LED4, "led4");
kamilion 0:5d5265391846 79
kamilion 0:5d5265391846 80 // ------ Buttons -----
kamilion 0:5d5265391846 81
kamilion 0:5d5265391846 82 // Define some interrupts for buttons.
kamilion 0:5d5265391846 83 InterruptIn P21(p21);
kamilion 0:5d5265391846 84 InterruptIn P22(p22);
kamilion 0:5d5265391846 85 InterruptIn P23(p23);
kamilion 0:5d5265391846 86 InterruptIn P24(p24);
kamilion 0:5d5265391846 87
kamilion 0:5d5265391846 88 #define BUTTON_MESSAGE_SEND(x,y) \
kamilion 0:5d5265391846 89 printf("$MBEDE,%d,BUTTON,%02d,%d*FF\r\n",time(NULL),x,y);
kamilion 0:5d5265391846 90
kamilion 0:5d5265391846 91 void pin21Rise(void) { BUTTON_MESSAGE_SEND(21, 1); }
kamilion 0:5d5265391846 92 void pin21Fall(void) { BUTTON_MESSAGE_SEND(21, 0); }
kamilion 0:5d5265391846 93 void pin22Rise(void) { BUTTON_MESSAGE_SEND(22, 1); }
kamilion 0:5d5265391846 94 void pin22Fall(void) { BUTTON_MESSAGE_SEND(22, 0); }
kamilion 0:5d5265391846 95 void pin23Rise(void) { BUTTON_MESSAGE_SEND(23, 1); }
kamilion 0:5d5265391846 96 void pin23Fall(void) { BUTTON_MESSAGE_SEND(23, 0); }
kamilion 0:5d5265391846 97 void pin24Rise(void) { BUTTON_MESSAGE_SEND(24, 1); }
kamilion 0:5d5265391846 98 void pin24Fall(void) { BUTTON_MESSAGE_SEND(24, 0); }
kamilion 0:5d5265391846 99
kamilion 0:5d5265391846 100
kamilion 0:5d5265391846 101 void buttonSetup() {
kamilion 0:5d5265391846 102 // Enable pullup resistors on pins.
kamilion 0:5d5265391846 103 P21.mode(PullUp); P22.mode(PullUp); P23.mode(PullUp); P24.mode(PullUp);
kamilion 0:5d5265391846 104
kamilion 0:5d5265391846 105 // Fix Mbed library bug, see http://mbed.org/forum/bugs-suggestions/topic/1498
kamilion 0:5d5265391846 106 // Prevents pullup interrupts from firing once on below attachment during startup.
kamilion 0:5d5265391846 107 LPC_GPIOINT->IO2IntClr = (1UL << 5) | (1UL << 4) | (1UL << 3) | (1UL << 2);
kamilion 0:5d5265391846 108
kamilion 0:5d5265391846 109 // Attach InterruptIn pin callbacks.
kamilion 0:5d5265391846 110 P21.rise(&pin21Rise); P21.fall(&pin21Fall);
kamilion 0:5d5265391846 111 P22.rise(&pin22Rise); P22.fall(&pin22Fall);
kamilion 0:5d5265391846 112 P23.rise(&pin23Rise); P23.fall(&pin23Fall);
kamilion 0:5d5265391846 113 P24.rise(&pin24Rise); P24.fall(&pin24Fall);
kamilion 0:5d5265391846 114 }
kamilion 0:5d5265391846 115
kamilion 0:5d5265391846 116 // ------ Ethernet -----
kamilion 0:5d5265391846 117
kamilion 0:5d5265391846 118 #ifdef DHCP
kamilion 0:5d5265391846 119 EthernetNetIf eth; // Use DHCP from router
kamilion 0:5d5265391846 120 #else
kamilion 0:5d5265391846 121 EthernetNetIf eth(
kamilion 0:5d5265391846 122 IpAddr(10,4,0,212), //IP Address
kamilion 0:5d5265391846 123 IpAddr(255,255,255,0), //Network Mask
kamilion 0:5d5265391846 124 IpAddr(10,4,0,1), //Gateway
kamilion 0:5d5265391846 125 IpAddr(10,0,0,7) //DNS
kamilion 0:5d5265391846 126 ); // Define a static IP to run with for early crossover cable debugging.
kamilion 0:5d5265391846 127 #endif
kamilion 0:5d5265391846 128
kamilion 0:5d5265391846 129 NTPClient ntp; // Object for the ntpclient
kamilion 0:5d5265391846 130
kamilion 0:5d5265391846 131 void rtcSetup() {
kamilion 0:5d5265391846 132 Host server(IpAddr(), 123, "0.us.pool.ntp.org");
kamilion 0:5d5265391846 133 ntp.setTime(server);
kamilion 0:5d5265391846 134 time_t ctTime;
kamilion 0:5d5265391846 135 ctTime = time(NULL);
kamilion 0:5d5265391846 136 printf("$MBEDE,%d,TIME_SET_NTP,%s",time(NULL), ctime(&ctTime));
kamilion 0:5d5265391846 137 }
kamilion 0:5d5265391846 138
kamilion 0:5d5265391846 139 Host client; // a Host (IP address) object named client; the one connecting to us.
kamilion 0:5d5265391846 140 TCPSocket ListeningSock; // Actual listening socket
kamilion 0:5d5265391846 141 TCPSocket* pConnectedSock; // pointer for ConnectedSock
kamilion 0:5d5265391846 142 TCPSocketErr err; // Error slot for TCP Socket
kamilion 0:5d5265391846 143
kamilion 0:5d5265391846 144 bool clientExists = 0;
kamilion 0:5d5265391846 145
kamilion 0:5d5265391846 146 void onConnectedTCPSocketEvent(TCPSocketEvent e) {
kamilion 0:5d5265391846 147 switch(e) {
kamilion 0:5d5265391846 148 case TCPSOCKET_WRITEABLE:
kamilion 0:5d5265391846 149 // printf("$MBEDE,%d,IP,CONNECTED,TCP_SOCKET_SENDING_DATA*FF\r\n",time(NULL));
kamilion 0:5d5265391846 150 led1 = 1.0; // Blink an xmit
kamilion 0:5d5265391846 151 led1 = 0.10;
kamilion 0:5d5265391846 152 break;
kamilion 0:5d5265391846 153 case TCPSOCKET_READABLE:
kamilion 0:5d5265391846 154 printf("$MBEDE,%d,IP,CONNECTED,TCP_SOCKET_READABLE*FF\r\n",time(NULL));
kamilion 0:5d5265391846 155 led2 = 1.0; // Blink a recv
kamilion 0:5d5265391846 156 led2 = 0.10;
kamilion 0:5d5265391846 157 break;
kamilion 0:5d5265391846 158 // The following cases generally should not happen often, but are explicitly covered anyway
kamilion 0:5d5265391846 159 case TCPSOCKET_CONTIMEOUT:
kamilion 0:5d5265391846 160 case TCPSOCKET_CONRST:
kamilion 0:5d5265391846 161 case TCPSOCKET_CONABRT:
kamilion 0:5d5265391846 162 case TCPSOCKET_ERROR:
kamilion 0:5d5265391846 163 case TCPSOCKET_DISCONNECTED:
kamilion 0:5d5265391846 164 printf("$MBEDE,%d,IP,CONNECTED,TCP_SOCKET_DISCONNECTED*FF\r\n",time(NULL));
kamilion 0:5d5265391846 165 pConnectedSock->close();
kamilion 0:5d5265391846 166 clientExists = 0;
kamilion 0:5d5265391846 167 SLine_put_control(false);
kamilion 0:5d5265391846 168 SLine_clear();
kamilion 0:5d5265391846 169 led4 = 0.0; // Shut off LED4 (Connected)
kamilion 0:5d5265391846 170 led1 = 0.0; // Shut off LED1 (Xmit)
kamilion 0:5d5265391846 171 break;
kamilion 0:5d5265391846 172 default:
kamilion 0:5d5265391846 173 break;
kamilion 0:5d5265391846 174 }
kamilion 0:5d5265391846 175 }
kamilion 0:5d5265391846 176
kamilion 0:5d5265391846 177
kamilion 0:5d5265391846 178 void onListeningTCPSocketEvent(TCPSocketEvent e) {
kamilion 0:5d5265391846 179 switch(e) {
kamilion 0:5d5265391846 180 case TCPSOCKET_ACCEPT:
kamilion 0:5d5265391846 181 printf("$MBEDE,%d,IP,LISTENING,TCP_SOCKET_ACCEPTED*FF\r\n",time(NULL));
kamilion 0:5d5265391846 182 // Accepts connection from client and gets connected socket.
kamilion 0:5d5265391846 183 err=ListeningSock.accept(&client, &pConnectedSock);
kamilion 0:5d5265391846 184 if (err) {
kamilion 0:5d5265391846 185 printf("$MBEDE,%d,IP,onListeningTcpSocketEvent,Could not accept connection*FF\r\n",time(NULL));
kamilion 0:5d5265391846 186 return; //Error in accept, discard connection (nmap/netcat -z portscanning us?)
kamilion 0:5d5265391846 187 }
kamilion 0:5d5265391846 188 // Setup the new socket events
kamilion 0:5d5265391846 189 pConnectedSock->setOnEvent(&onConnectedTCPSocketEvent);
kamilion 0:5d5265391846 190 // We can find out where the connection is coming by looking at the
kamilion 0:5d5265391846 191 // Host parameter of the accept() method
kamilion 0:5d5265391846 192 IpAddr clientIp = client.getIp();
kamilion 0:5d5265391846 193 printf("$MBEDE,%d,IP,LISTENING,TCP_CONNECT_FROM,%d.%d.%d.%d*FF\r\n",time(NULL),
kamilion 0:5d5265391846 194 clientIp[0], clientIp[1], clientIp[2], clientIp[3]);
kamilion 0:5d5265391846 195 clientExists = 1; // Mark ourselves connected.
kamilion 0:5d5265391846 196 SLine_clear();
kamilion 0:5d5265391846 197 SLine_put_control(true);
kamilion 0:5d5265391846 198 led4 = 0.10; // Turn on LED4 (Connected)
kamilion 0:5d5265391846 199 break;
kamilion 0:5d5265391846 200 // The following cases generally should not happen often, but are explicitly covered anyway
kamilion 0:5d5265391846 201 case TCPSOCKET_CONRST:
kamilion 0:5d5265391846 202 case TCPSOCKET_CONTIMEOUT:
kamilion 0:5d5265391846 203 case TCPSOCKET_CONABRT:
kamilion 0:5d5265391846 204 case TCPSOCKET_ERROR:
kamilion 0:5d5265391846 205 case TCPSOCKET_DISCONNECTED:
kamilion 0:5d5265391846 206 // Close the socket (nmap/netcat -z portscanning us?)
kamilion 0:5d5265391846 207 printf("$MBEDE,%d,IP,LISTENING,TCP_SOCKET_DISCONNECTED*FF\r\n",time(NULL));
kamilion 0:5d5265391846 208 ListeningSock.close();
kamilion 0:5d5265391846 209 clientExists = 0;
kamilion 0:5d5265391846 210 SLine_put_control(false);
kamilion 0:5d5265391846 211 SLine_clear();
kamilion 0:5d5265391846 212 led4 = 0.0; // Shut off LED4 (Connected)
kamilion 0:5d5265391846 213 break;
kamilion 0:5d5265391846 214 default:
kamilion 0:5d5265391846 215 break;
kamilion 0:5d5265391846 216 };
kamilion 0:5d5265391846 217 }
kamilion 0:5d5265391846 218
kamilion 0:5d5265391846 219 // ------ Serial -----
kamilion 0:5d5265391846 220
kamilion 0:5d5265391846 221 // Set up the UARTs with MODSERIAL buffering
kamilion 0:5d5265391846 222 MODSERIAL hostPort(USBTX, USBRX);
kamilion 0:5d5265391846 223 MODSERIAL gpsPort(p13, p14);
kamilion 0:5d5265391846 224 MODSERIAL imuPort(p9, p10);
kamilion 0:5d5265391846 225 MODSERIAL wheelPort(p28, p27);
kamilion 0:5d5265391846 226
kamilion 0:5d5265391846 227 void captureSerial(MODSERIAL* serial, LINE_T* line, LINE_SRC_T src) {
kamilion 0:5d5265391846 228 memset(line->line, 0, LINE_MAX_LEN + 1); // Empty out buffer first
kamilion 0:5d5265391846 229 line->source = src; // Enumerate source from line_util.h
kamilion 0:5d5265391846 230 line->usec = highres.read_us(); // Read highres timer
kamilion 0:5d5265391846 231 serial->move(line->line, LINE_MAX_LEN); // Move the buffer into the struct member
kamilion 0:5d5265391846 232 line->len = strip_crlf(line->line); // Strip the line of endings of the struct member
kamilion 0:5d5265391846 233 line->timestamp = time(NULL); // Read RTC time
kamilion 0:5d5265391846 234 }
kamilion 0:5d5265391846 235
kamilion 0:5d5265391846 236 void generateOutput(TCPSocket* socket, LINE_T* line) {
kamilion 0:5d5265391846 237 char tx_buf[MESSAGE_BUFFER_SIZE];
kamilion 0:5d5265391846 238 unsigned int tx_length; // total bytes to be sent.
kamilion 0:5d5265391846 239 int bytes_sent; // total bytes sent so far in function.
kamilion 0:5d5265391846 240 int send_rc; // result of last send operation.
kamilion 0:5d5265391846 241 unsigned int send_chunk; // amount attempted for tx operation.
kamilion 0:5d5265391846 242 unsigned int consec_zeros; // consecutive socket send ops returning 0.
kamilion 0:5d5265391846 243
kamilion 0:5d5265391846 244 if (line->len > 0) {
kamilion 0:5d5265391846 245
kamilion 0:5d5265391846 246 // Though not strictly necessary, life is just easier if we preformat
kamilion 0:5d5265391846 247 // the data we want to send by socket.
kamilion 0:5d5265391846 248
kamilion 0:5d5265391846 249 tx_length = snprintf(tx_buf, MESSAGE_BUFFER_SIZE,
kamilion 0:5d5265391846 250 "%s,%010u,%010u,%s%s",
kamilion 0:5d5265391846 251 LINE_SRC_NAMES[line->source],
kamilion 0:5d5265391846 252 line->timestamp,
kamilion 0:5d5265391846 253 line->usec,
kamilion 0:5d5265391846 254 line->line,
kamilion 0:5d5265391846 255 REC_SEP);
kamilion 0:5d5265391846 256 bytes_sent = 0;
kamilion 0:5d5265391846 257 send_rc = 0;
kamilion 0:5d5265391846 258 consec_zeros = 0;
kamilion 0:5d5265391846 259 printf(tx_buf);
kamilion 0:5d5265391846 260
kamilion 0:5d5265391846 261 // Traditional socket transmission APIs don't guarantee that
kamilion 0:5d5265391846 262 // everything we ask to send will get sent. Details on the mbed
kamilion 0:5d5265391846 263 // implementation are light, but it is wise to take this likelihood
kamilion 0:5d5265391846 264 // into consideration. Socket buffer capacity is certainly not
kamilion 0:5d5265391846 265 // infinite, and can fill for a variety of reasons.
kamilion 0:5d5265391846 266
kamilion 0:5d5265391846 267 while ((send_rc >= 0) && ((tx_length - bytes_sent) > 0)) {
kamilion 0:5d5265391846 268
kamilion 0:5d5265391846 269 // We'll go at it until we're out of stuff to send or we get an
kamilion 0:5d5265391846 270 // error when we send (traditional socket transmission APIs
kamilion 0:5d5265391846 271 // return -1 when encountering an error.
kamilion 0:5d5265391846 272
kamilion 0:5d5265391846 273 send_chunk = ((tx_length - bytes_sent) > TX_CHUNK ?
kamilion 0:5d5265391846 274 TX_CHUNK : tx_length - bytes_sent);
kamilion 0:5d5265391846 275
kamilion 0:5d5265391846 276 // We use this notion of chunking to go easy on the network
kamilion 0:5d5265391846 277 // stack, never trying to transmit a large amount of data
kamilion 0:5d5265391846 278 // in a single call.
kamilion 0:5d5265391846 279
kamilion 0:5d5265391846 280 send_rc = pConnectedSock->send(&(tx_buf[bytes_sent]),
kamilion 0:5d5265391846 281 send_chunk);
kamilion 0:5d5265391846 282 bytes_sent += (send_rc > 0 ? send_rc : 0);
kamilion 0:5d5265391846 283
kamilion 0:5d5265391846 284 // If we try to send too much and not poll often enough, the
kamilion 0:5d5265391846 285 // network stack will stop being able to accept data. So, we'll
kamilion 0:5d5265391846 286 // poll here since this is a really intense area of transmission.
kamilion 0:5d5265391846 287
kamilion 0:5d5265391846 288 Net::poll();
kamilion 0:5d5265391846 289
kamilion 0:5d5265391846 290 if (consec_zeros && (send_rc > 0)) {
kamilion 0:5d5265391846 291 printf("### Recovery: First non-zero send after %06u tries "
kamilion 0:5d5265391846 292 "(%04d/%04u). ###\r\n",
kamilion 0:5d5265391846 293 consec_zeros, send_rc, send_chunk);
kamilion 0:5d5265391846 294 printf("Serial data line queue utilization: %u/%u.\r\n",
kamilion 0:5d5265391846 295 SLines_get_fill(), SLines_get_capacity());
kamilion 0:5d5265391846 296 consec_zeros = 0;
kamilion 0:5d5265391846 297 }
kamilion 0:5d5265391846 298
kamilion 0:5d5265391846 299 if (send_rc < send_chunk) {
kamilion 0:5d5265391846 300
kamilion 0:5d5265391846 301 if (!consec_zeros) {
kamilion 0:5d5265391846 302 printf("### Send result: %04d/%04u. ###\r\n",
kamilion 0:5d5265391846 303 send_rc, send_chunk);
kamilion 0:5d5265391846 304 printf("Serial data line queue utilization: %u/%u.\r\n",
kamilion 0:5d5265391846 305 SLines_get_fill(), SLines_get_capacity());
kamilion 0:5d5265391846 306 }
kamilion 0:5d5265391846 307
kamilion 0:5d5265391846 308 if (send_rc <= 0) {
kamilion 0:5d5265391846 309 consec_zeros++;
kamilion 0:5d5265391846 310 }
kamilion 0:5d5265391846 311
kamilion 0:5d5265391846 312 }
kamilion 0:5d5265391846 313
kamilion 0:5d5265391846 314 }
kamilion 0:5d5265391846 315
kamilion 0:5d5265391846 316 }
kamilion 0:5d5265391846 317
kamilion 0:5d5265391846 318 }
kamilion 0:5d5265391846 319
kamilion 0:5d5265391846 320 // ------ Serial ISRs -----
kamilion 0:5d5265391846 321
kamilion 0:5d5265391846 322 void gpsMessageReceive(void) {
kamilion 0:5d5265391846 323 LINE_T new_line;
kamilion 0:5d5265391846 324
kamilion 0:5d5265391846 325 captureSerial(&gpsPort, &new_line, LINE_SRC_GPS);
kamilion 0:5d5265391846 326 SLine_put(&new_line);
kamilion 0:5d5265391846 327 }
kamilion 0:5d5265391846 328
kamilion 0:5d5265391846 329 void imuMessageReceive(void) {
kamilion 0:5d5265391846 330 LINE_T new_line;
kamilion 0:5d5265391846 331
kamilion 0:5d5265391846 332 captureSerial(&imuPort, &new_line, LINE_SRC_IMU);
kamilion 0:5d5265391846 333 SLine_put(&new_line);
kamilion 0:5d5265391846 334 }
kamilion 0:5d5265391846 335
kamilion 0:5d5265391846 336 void wheelMessageReceive(void) {
kamilion 0:5d5265391846 337 LINE_T new_line;
kamilion 0:5d5265391846 338
kamilion 0:5d5265391846 339 captureSerial(&wheelPort, &new_line, LINE_SRC_WHEEL);
kamilion 0:5d5265391846 340 SLine_put(&new_line);
kamilion 0:5d5265391846 341 }
kamilion 0:5d5265391846 342
kamilion 0:5d5265391846 343 void hostMessageReceive(void) {
kamilion 0:5d5265391846 344 LINE_T new_line;
kamilion 0:5d5265391846 345
kamilion 0:5d5265391846 346 captureSerial(&hostPort, &new_line, LINE_SRC_HOST);
kamilion 0:5d5265391846 347 SLine_put(&new_line);
kamilion 0:5d5265391846 348 }
kamilion 0:5d5265391846 349
kamilion 0:5d5265391846 350 void processSerialQueues() {
kamilion 0:5d5265391846 351 unsigned int cur_fill;
kamilion 0:5d5265391846 352 unsigned int lines_handled;
kamilion 0:5d5265391846 353
kamilion 0:5d5265391846 354 cur_fill = SLines_get_fill();
kamilion 0:5d5265391846 355 lines_handled = 0;
kamilion 0:5d5265391846 356
kamilion 0:5d5265391846 357 while ((cur_fill > 0) && (lines_handled < MAX_LINES_PER_ITER)) {
kamilion 0:5d5265391846 358
kamilion 0:5d5265391846 359 // It's tempting to just process every line we have while we're in
kamilion 0:5d5265391846 360 // here. However, since we're in a super-looped environment, network
kamilion 0:5d5265391846 361 // I/O is completed via polling, and it seems prudent to not jam too
kamilion 0:5d5265391846 362 // much down the stack between polling operations.
kamilion 0:5d5265391846 363
kamilion 0:5d5265391846 364 if (((cur_fill * 100) / SLines_get_capacity()) >= Q_ALERT_THRESH) {
kamilion 0:5d5265391846 365 printf("Serial data line queue utilization: %u/%u.\r\n",
kamilion 0:5d5265391846 366 cur_fill, SLines_get_capacity());
kamilion 0:5d5265391846 367 }
kamilion 0:5d5265391846 368
kamilion 0:5d5265391846 369 if (clientExists) {
kamilion 0:5d5265391846 370 generateOutput(pConnectedSock, SLine_get());
kamilion 0:5d5265391846 371 }
kamilion 0:5d5265391846 372
kamilion 0:5d5265391846 373 SLine_remove();
kamilion 0:5d5265391846 374 cur_fill = SLines_get_fill();
kamilion 0:5d5265391846 375 lines_handled++;
kamilion 0:5d5265391846 376 }
kamilion 0:5d5265391846 377
kamilion 0:5d5265391846 378 }
kamilion 0:5d5265391846 379
kamilion 0:5d5265391846 380 void serialSetup() {
kamilion 0:5d5265391846 381 // Set up the USB UART for host debugging
kamilion 0:5d5265391846 382 hostPort.baud(HOST_BAUD); // Need a baud rate. We can go faster, but this is good.
kamilion 0:5d5265391846 383 hostPort.attach(&hostMessageReceive, MODSERIAL::RxAutoDetect); // Attach a handler on receive.
kamilion 0:5d5265391846 384 hostPort.autoDetectChar('\r'); // Tell the handler to keep an eye for carrage returns.
kamilion 0:5d5265391846 385
kamilion 0:5d5265391846 386 // Set up the GPS UART for incoming sentences
kamilion 0:5d5265391846 387 gpsPort.baud(38400); // Need a baud rate. We can go faster, but this is good.
kamilion 0:5d5265391846 388 gpsPort.attach(&gpsMessageReceive, MODSERIAL::RxAutoDetect); // Attach a handler on receive.
kamilion 0:5d5265391846 389 gpsPort.autoDetectChar('\n'); // Tell the handler to keep an eye for newlines.
kamilion 0:5d5265391846 390
kamilion 0:5d5265391846 391 // Set up the IMU UART for incoming sentences
kamilion 0:5d5265391846 392 imuPort.baud(57600); // Need a baud rate. We can go faster, but this is good.
kamilion 0:5d5265391846 393 imuPort.attach(&imuMessageReceive, MODSERIAL::RxAutoDetect); // Attach a handler on receive.
kamilion 0:5d5265391846 394 imuPort.autoDetectChar('\n'); // Tell the handler to keep an eye for newlines.
kamilion 0:5d5265391846 395
kamilion 0:5d5265391846 396 // Set up the Wheel UART for incoming sentences
kamilion 0:5d5265391846 397 wheelPort.baud(57600); // Need a baud rate. We can go faster, but this is good.
kamilion 0:5d5265391846 398 wheelPort.attach(&wheelMessageReceive, MODSERIAL::RxAutoDetect); // Attach a handler on receive.
kamilion 0:5d5265391846 399 wheelPort.autoDetectChar('\r'); // Tell the handler to keep an eye for carrage returns.
kamilion 0:5d5265391846 400 }
kamilion 0:5d5265391846 401
kamilion 0:5d5265391846 402 int ethernetSetup() { // Setup ethernet hardware
kamilion 0:5d5265391846 403 printf("\r\n$MBEDE,%d,IP,ETHERNET_DHCP_SLEEP_20*FF\r\n",time(NULL)); // Send some status
kamilion 0:5d5265391846 404 wait(20);
kamilion 0:5d5265391846 405 printf("\r\n$MBEDE,%d,IP,ETHERNET_DHCP*FF\r\n",time(NULL)); // Send some status
kamilion 0:5d5265391846 406 EthernetErr ethErr = eth.setup(60000); // Initiate ethernet setup (DHCP or Static IP)
kamilion 0:5d5265391846 407 if(ethErr) {
kamilion 0:5d5265391846 408 printf("$MBEDE,%d,IP,ETHERNET_ERROR,%d*FF\r\n",time(NULL), ethErr);
kamilion 0:5d5265391846 409 return -1;
kamilion 0:5d5265391846 410 }
kamilion 0:5d5265391846 411 IpAddr ip = eth.getIp(); // Say our IP address
kamilion 0:5d5265391846 412 printf("$MBEDE,%d,IP,ADDRESS,%d.%d.%d.%d*FF\r\n",time(NULL), ip[0], ip[1], ip[2], ip[3]);
kamilion 0:5d5265391846 413 led3 = 0.10; // Turn on LED3 (DHCP Success)
kamilion 0:5d5265391846 414 led1 = 0.00; // Turn off LED1 (Xmit)
kamilion 0:5d5265391846 415 led2 = 0.00; // Turn off LED2 (Recv)
kamilion 0:5d5265391846 416 return 0;
kamilion 0:5d5265391846 417 }
kamilion 0:5d5265391846 418
kamilion 0:5d5265391846 419 void portSetup() { // Set the callbacks for Listening
kamilion 0:5d5265391846 420 ListeningSock.setOnEvent(&onListeningTCPSocketEvent); // bind and listen on TCP
kamilion 0:5d5265391846 421 err=ListeningSock.bind(Host(IpAddr(), TCP_LISTENING_PORT)); // Bind the port
kamilion 0:5d5265391846 422 printf("$MBEDE,%d,IP,BINDING_PORT,%i*FF\r\n",time(NULL), TCP_LISTENING_PORT);
kamilion 0:5d5265391846 423 if(err) printf("$MBEDE,%d,IP,BINDING_ERROR,%i*FF\r\n",time(NULL), TCP_LISTENING_PORT);
kamilion 0:5d5265391846 424 err=ListeningSock.listen(); // Starts listening
kamilion 0:5d5265391846 425 printf("$MBEDE,%d,IP,LISTENING_PORT,%i*FF\r\n",time(NULL), TCP_LISTENING_PORT);
kamilion 0:5d5265391846 426 if(err) printf("$MBEDE,%d,IP,LISTENING_ERROR,%i*FF\r\n",time(NULL), TCP_LISTENING_PORT);
kamilion 0:5d5265391846 427 }
kamilion 0:5d5265391846 428
kamilion 0:5d5265391846 429 // ------ MAINLOOP -----
kamilion 0:5d5265391846 430
kamilion 0:5d5265391846 431 int main() {
kamilion 0:5d5265391846 432 led1 = 1.0;
kamilion 0:5d5265391846 433 highres.start(); // Initiate highres timer ticking.
kamilion 0:5d5265391846 434 led1 = 0.75;
kamilion 0:5d5265391846 435 buttonSetup(); // Activate button ISRs
kamilion 0:5d5265391846 436 led1 = 0.50;
kamilion 0:5d5265391846 437 serialSetup(); // Activate Serial ISRs
kamilion 0:5d5265391846 438 led1 = 0.10;
kamilion 0:5d5265391846 439 printf(BannerText);
kamilion 0:5d5265391846 440 led2 = 1.0;
kamilion 0:5d5265391846 441 if(ethernetSetup()==-1) return -1; // 'quit' if we cannot setup ethernet. (return to bootloader/'reboot')
kamilion 0:5d5265391846 442 led2 = 0.75;
kamilion 0:5d5265391846 443 rtcSetup(); // Get time from network
kamilion 0:5d5265391846 444 led2 = 0.50;
kamilion 0:5d5265391846 445 portSetup(); // Open listens
kamilion 0:5d5265391846 446 led2 = 0.10;
kamilion 0:5d5265391846 447
kamilion 0:5d5265391846 448 while(true) { // infinite network poll loop
kamilion 0:5d5265391846 449 Net::poll(); // Poll the network stack.
kamilion 0:5d5265391846 450 processSerialQueues(); // Process queued messages (Seems fastest here)
kamilion 0:5d5265391846 451 }
kamilion 0:5d5265391846 452 }