Webserver only w/o any other functions, single thread. Running on STM32F013+W5500

Dependencies:   NTPClient W5500Interface Watchdog device_configuration eeprom_flash mbed-rpc-nucleo mbed-rtos mbed

Fork of F103-Serial-to-Ethernet by Chau Vo

Files at this revision

API Documentation at this revision

Comitter:
olympux
Date:
Mon Dec 29 21:40:55 2014 +0000
Parent:
26:09e0dd020900
Child:
28:00c0c20d03c1
Commit message:
Added and tested Rpc with TCP/UDP

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rpc.lib Show annotated file Show diff for this revision Revisions of this file
my_eeprom_funcs.lib Show annotated file Show diff for this revision Revisions of this file
protocol_rpc.txt Show annotated file Show diff for this revision Revisions of this file
protocol_v2.0.txt Show annotated file Show diff for this revision Revisions of this file
readme.txt Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Wed Dec 24 13:23:33 2014 +0000
+++ b/main.cpp	Mon Dec 29 21:40:55 2014 +0000
@@ -3,10 +3,13 @@
 *  Alarm and Monitoring application
 */
 #include "mbed.h"
+#include "rtos.h"
+#include "mbed_rpc.h"
+#include "Arguments.h"
+
 #include "eeprom.h"
 #include "EthernetInterface.h"
 #include "NTPClient.h"
-#include "rtos.h"
 
 #include "my_eeprom_funcs.h"
 #include "Watchdog.h"
@@ -40,10 +43,16 @@
 EthernetInterface eth(&spi, PA_4, PC_9); // spi, cs, reset
 #endif
 
-// Serial
-Serial uart(USBTX,USBRX);
-
-// Digital inputs
+//Use the RPC enabled wrapped class  - see RpcClasses.h for more info
+// DigitalIn
+RpcDigitalIn di0(PB_14, "din0");
+RpcDigitalIn di1(PB_12, "din1");
+RpcDigitalIn di2(PB_10, "din2");
+RpcDigitalIn di3(PB_1, "din3");
+RpcDigitalIn di4(PB_15, "din4");
+RpcDigitalIn di5(PB_13, "din5");
+RpcDigitalIn di6(PB_11, "din6");
+RpcDigitalIn di7(PB_2, "din7");
 DigitalIn din0(PB_14);
 DigitalIn din1(PB_12);
 DigitalIn din2(PB_10);
@@ -52,7 +61,15 @@
 DigitalIn din5(PB_13);
 DigitalIn din6(PB_11);
 DigitalIn din7(PB_2);
-// Digital outputs
+// DigitalOut
+RpcDigitalOut do0(PB_3, "dout0");
+RpcDigitalOut do1(PB_5, "dout1");
+RpcDigitalOut do2(PB_7, "dout2");
+RpcDigitalOut do3(PB_9, "dout3");
+RpcDigitalOut do4(PD_2, "dout4");
+RpcDigitalOut do5(PB_4, "dout5");
+RpcDigitalOut do6(PB_6, "dout6");
+RpcDigitalOut do7(PB_8, "dout7");
 DigitalOut dout0(PB_3);
 DigitalOut dout1(PB_5);
 DigitalOut dout2(PB_7);
@@ -61,18 +78,23 @@
 DigitalOut dout5(PB_4);
 DigitalOut dout6(PB_6);
 DigitalOut dout7(PB_8);
-// Analog inputs
+// AnalogIn
+RpcAnalogIn adc10(PC_0, "ain0"); // adc10
+RpcAnalogIn adc11(PC_1, "ain1"); // adc11
 AnalogIn ain0(PC_0);
 AnalogIn ain1(PC_1);
-// Analog outputs
-//AnalogOut ano0(PA_8);
-//AnalogOut ano1(PA_15);
-
+// AnalogOut, PWM
+RpcPwmOut pwm11(PA_8, "pwm0"); // pwm11
+RpcPwmOut pwm21(PA_15, "pwm1"); // pwm21
+// Serial
+RpcSerial usart2(USBTX, USBRX, "uart"); // usart2
+Serial uart(USBTX,USBRX);
+// Timer
+RpcTimer timer1("timer1");
 // Watchdog
 Watchdog wdt;
 
 
-
 /*
 * EEPROM section
 */
@@ -153,7 +175,8 @@
 * Protocol
 */
 // Commands
-#define DEVICE_ID                           "NNIO"
+#define DEVICE_CONFIG_CODE                  "NNCF"
+#define DEVICE_CONTROL_CODE                 "NNIO"
 
 #define RECEIVING_PROTOCOL_LENGTH           58
 #define SENDING_PROTOCOL_LENGTH             39
@@ -161,14 +184,14 @@
 #define SET_NETWORK_CONFIG_CMD_LENGTH       19
 #define UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH   12
 
-#define QUERY_DISCOVERY_CMD                 "NNIODS"
-#define QUERY_IP_CMD                        "NNIOIP"
-#define QUERY_SUBNET_CMD                    "NNIOSN"
-#define QUERY_GATEWAY_CMD                   "NNIOGW"
-#define QUERY_MAC_CMD                       "NNIOMC"
-#define QUERY_UDP_PORT_CMD                  "NNIOUP"
-#define QUERY_TCP_PORT_CMD                  "NNIOTP"
-#define QUERY_UPDATE_TIME_CMD               "NNIOTM"
+#define QUERY_DISCOVERY_CMD                 "NNCFDS"
+#define QUERY_IP_CMD                        "NNCFIP"
+#define QUERY_SUBNET_CMD                    "NNCFSN"
+#define QUERY_GATEWAY_CMD                   "NNCFGW"
+#define QUERY_MAC_CMD                       "NNCFMC"
+#define QUERY_UDP_PORT_CMD                  "NNCFUP"
+#define QUERY_TCP_PORT_CMD                  "NNCFTP"
+#define QUERY_UPDATE_TIME_CMD               "NNCFTM"
 #define RECEIVING_PROTOCOL_ENABLE_OUTPUT    'O'
 #define QUERY_STATUS_COMMAND                'Q'
 #define DIGITAL_HIGH                        'H'
@@ -366,6 +389,7 @@
                     if (n <= 0) break;
                     
                     // got some data, test it
+                    tcp_receiving_buffer[n] = '\0'; // for debugging purpose
                     DBG("TCP server received: %s", tcp_receiving_buffer);
                     process_control_command(tcp_receiving_buffer, n);
                 } // end loop if no data received within timeout
@@ -375,38 +399,40 @@
 #endif
 
 #ifdef UDP_SERVER
-        bool config_mode_flag;
+        bool discovery_mode_flag, config_mode_flag;
         
         n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
         
         // check to see if it is a query command
         // if yes, is it a discovery command or an ip query to enter config mode
+        discovery_mode_flag = false;
         config_mode_flag = false;
         if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_DISCOVERY_CMD) != NULL)) {
+            discovery_mode_flag = true;
             DBG("Received discovery command");
             char str[50];
-            sprintf(str, "%s%s%s", DEVICE_ID, eth.getMACAddress(), eth.getIPAddress());
+            sprintf(str, "%s%s%s", DEVICE_CONFIG_CODE, eth.getMACAddress(), eth.getIPAddress());
             udp_server.sendTo(ep_udp_client, str, strlen(str));
-        } // NNIODS
+        } // NNCFDS
         else if ((n == QUERY_NETWORK_CONFIG_CMD_LENGTH) && (strstr(udp_receiving_buffer, QUERY_IP_CMD) != NULL)) {
             config_mode_flag = true;
-            DBG("Enabled configuration mode...");
+            DBG("Entered configuration mode...");
             DBG("!!! RESET when finished");
-        } // NNIOIP
+        } // NNCFIP
         
-        // if received NNIOIP, enter config mode
+        // if received NNCFIP, enter config mode
         if (config_mode_flag) {
             while (n > 0)
             {
                 // got some data, test it
-                DBG("UDP received (%s) from (%s) and port (%d)", udp_receiving_buffer, ep_udp_client.get_address(), ep_udp_client.get_port());
+                DBG("UDP received (%s) from (%s:%d)", udp_receiving_buffer, ep_udp_client.get_address(), ep_udp_client.get_port());
                 process_config_command(udp_receiving_buffer, n);
                 // wait to receive new config command
                 udp_server.set_blocking(true);
                 n = udp_server.receiveFrom(ep_udp_client, udp_receiving_buffer, sizeof(udp_receiving_buffer));
             } // while (n > 0), config loop
         } // if (config_mode_flag)
-        else if (n > 0) { // process control packages sent using UDP
+        else if ((n > 0) && (!discovery_mode_flag)) { // process control packages sent using UDP
             process_control_command(udp_receiving_buffer, n);
         }
 #endif
@@ -416,37 +442,40 @@
 
 void process_config_command(char* received_buffer, int len)
 {
+    DBG("Processing configuration command");
+    
     // process received data
     // a configuration command always starts with NN
-    if ((received_buffer[0] == 'N') && (received_buffer[1] == 'N')) {
+    if ((received_buffer[0] == 'N') && (received_buffer[1] == 'N') &&
+        (received_buffer[2] == 'C') && (received_buffer[3] == 'F')) {
         switch (len) {
             // length = 6, a QUERY command (discovery command, TCP port, or UDP port)
-            // Format: NNIODS, NNIOTP, NNIOUP, NNIOTM
+            // Format: NNCFDS, NNCFTP, NNCFUP, NNCFTM
             case QUERY_NETWORK_CONFIG_CMD_LENGTH:
                 if (strstr(received_buffer, QUERY_IP_CMD) != NULL) {
                     udp_server.sendTo(ep_udp_client, eth.getIPAddress(), strlen(eth.getIPAddress()));
-                } // NNIOIP
+                } // NNCFIP
                 else if (strstr(received_buffer, QUERY_SUBNET_CMD) != NULL) {
                     udp_server.sendTo(ep_udp_client, eth.getNetworkMask(), strlen(eth.getNetworkMask()));
-                } // NNIOSN
+                } // NNCFSN
                 else if (strstr(received_buffer, QUERY_GATEWAY_CMD) != NULL) {
                     udp_server.sendTo(ep_udp_client, eth.getGateway(), strlen(eth.getGateway()));
-                } // NNIOGW
+                } // NNCFGW
                 else if (strstr(received_buffer, QUERY_MAC_CMD) != NULL) {
                     udp_server.sendTo(ep_udp_client, eth.getMACAddress(), strlen(eth.getMACAddress()));
-                } // NNIOMC
+                } // NNCFMC
                 // ask for TCP server port
                 else if (strstr(received_buffer, QUERY_TCP_PORT_CMD) != NULL) {
                     char port[5];
                     sprintf(port, "%5d", tcp_server_local_port);
                     udp_server.sendTo(ep_udp_client, port, strlen(port));
-                } // NNIOTP
+                } // NNCFTP
                 // ask for UDP server port
                 else if (strstr(received_buffer, QUERY_UDP_PORT_CMD) != NULL) {
                     char port[5];
                     sprintf(port, "%5d", udp_server_local_port);
                     udp_server.sendTo(ep_udp_client, port, strlen(port));
-                } // NNIOUP
+                } // NNCFUP
                 else if (strstr(received_buffer, QUERY_UPDATE_TIME_CMD) != NULL) {
 #ifdef NTP
                     char str_time[50];
@@ -470,43 +499,43 @@
                     sprintf(str_time, "DIS");
                     udp_server.sendTo(ep_udp_client, str_time, strlen(str_time));
 #endif
-                } // NNIOTM
+                } // NNCFTM
 
                 break;
                 // length = 19, SET NETWORK CONFIGURATION
-                // Format: 4E 4E 49 4F      C0 A8 00 78        FF FF FF 00            C0 A8 00 01      00 00 01
-                //        (NNIO;            IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1)
+                // Format: 4E 4E 43 46      C0 A8 00 78        FF FF FF 00            C0 A8 00 01      00 00 01
+                //        (NNCF;            IP: 192.168.0.120; Subnet: 255.255.255.0; GW: 192.168.0.1; MAC: 0 0 1)
             case SET_NETWORK_CONFIG_CMD_LENGTH: {
                 // check device id
-                char* id = strstr(received_buffer, DEVICE_ID);
+                char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
                 if (id == NULL)
                     break;
                 else if ((id - received_buffer) > 0)
                     break;
 
                 DBG("Received user configuration");
-                write_eeprom_network(&received_buffer[strlen(DEVICE_ID)]); // parameters from 5th char, 15-bytes
+                write_eeprom_network(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char, 15-bytes
                 break;
             }
             // length = 12, SET TCP SERVER CONFIGURATION
             // auto update & its time period, TCP server configuration (IP & port)
-            // Format: 4E 4E 49 4F   'Y'     01   C0 A8 00 09   E0 2E (LSB MSB)
-            //         NNIO          Auto    1s   192.168.0.9   12000
+            // Format: 4E 4E 43 46   'Y'     01   C0 A8 00 09   E0 2E (LSB MSB)
+            //         NNCF          Auto    1s   192.168.0.9   12000
             case UPDATE_TCP_SERVER_INFO_COMMAND_LENGTH: {
-                char* id = strstr(received_buffer, DEVICE_ID);
+                char* id = strstr(received_buffer, DEVICE_CONFIG_CODE);
                 if (id == NULL)
                     break;
                 else if ((id - received_buffer) > 0)
                     break;
 
                 DBG("Received TCP server configuration");
-                write_eeprom_tcpserver(&received_buffer[strlen(DEVICE_ID)]); // parameters from 5th char
+                write_eeprom_tcpserver(&received_buffer[strlen(DEVICE_CONFIG_CODE)]); // parameters from 5th char
                 break;
             }
             default:
                 break;
         } // switch (n), check configuration command length
-    } // if starts with NN, a config command
+    } // if starts with NNCF, a config command
     else { // if not a command, check to see if it is a 6-byte data package
         // process 6-byte data package
     }
@@ -519,11 +548,32 @@
 {
     char* received_frame;
     int pos;
+    char inbuf[256], outbuf[256];
     
+    DBG("Processing control command");
+    
+    // check RPC protocol
+    strncpy(inbuf, received_buffer, len);
+    inbuf[len] = '\r'; // use inbuf for RPC protocol
+    inbuf[len+1] = '\n';
+    inbuf[len+2] = '\0'; // add CR-LF
+    DBG("inbuf = %s", inbuf);
+    if ((len > 0) && (inbuf[0] == '/')) {
+        bool result;
+        result = RPC::call(inbuf, outbuf);
+        if (result) {
+            DBG("I: %s O: %s\n", inbuf, outbuf);
+        }
+        else {
+            ERR("Failed: %s", inbuf);
+        }
+    }
+    
+    // NNIO protocol
     while (len >= RECEIVING_PROTOCOL_LENGTH) {
         // find device ID
         DBG("Checking device ID...");
-        char* id = strstr(received_buffer, DEVICE_ID);
+        char* id = strstr(received_buffer, DEVICE_CONTROL_CODE);
         if (id == NULL) {
             DBG("No device ID found");
             break;
@@ -575,8 +625,7 @@
             DBG("Sent");
         }
     }
-    
-    DBG("Successful");
+    DBG("Successfully processed.");
 }
 
 
@@ -586,12 +635,12 @@
 int ethernet_init(void) {
     int dhcp_ret, ret;
     
-    DBG("Start initialising ethernet");
+    DBG("Initialising ethernet...");
     
     // if not configured, try dhcp
     dhcp_ret = -1;
     if (configured_ip != DEFAULT_ENABLE_FLAG_VALUE) {
-        DBG("Connecting DHCP server...");
+        DBG("Connecting to DHCP server...");
         dhcp_ret = eth.init(u8mac);
         if (dhcp_ret == 0)
             dhcp_ret = eth.connect();
@@ -646,7 +695,7 @@
 * Prepare a frame for sending protocol, which includes status of I/Os
 */
 void update_sending_frame(char* buf) {
-    memcpy(&buf[SENDING_PROTOCOL_ID_POS], DEVICE_ID, 4); // device id
+    memcpy(&buf[SENDING_PROTOCOL_ID_POS], DEVICE_CONTROL_CODE, 4); // device id
     memcpy(&buf[SENDING_PROTOCOL_MAC_POS], &u8mac, 6);
     memcpy(&buf[SENDING_PROTOCOL_IP_POS], &u8ip_addr, 4);
     
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rpc.lib	Mon Dec 29 21:40:55 2014 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/olympux/code/mbed-rpc/#5e3dc699ab25
--- a/my_eeprom_funcs.lib	Wed Dec 24 13:23:33 2014 +0000
+++ b/my_eeprom_funcs.lib	Mon Dec 29 21:40:55 2014 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/olympux/code/my_eeprom_funcs/#4fc4b1b5509b
+http://mbed.org/users/olympux/code/my_eeprom_funcs/#b5fbb35bbc02
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/protocol_rpc.txt	Mon Dec 29 21:40:55 2014 +0000
@@ -0,0 +1,50 @@
+NNIO module can be controlled through TCP/UDP using RPC commands.
+
+
+1. Connections
+  + UDP port: 11000
+  + TCP port: 10000 (NNIO module is TCP server)
+
+2. Digital inputs
+  + Digital inputs: din0 - din7
+  + Commands: /din0/read x
+    
+3. Digital outputs
+  + Digital outputs: dout0 - dout7
+  + Commands:
+    /dout0/read x
+    /dout0/write 1
+
+3. Analog inputs
+  + Analog inputs: ain0 - ain1
+  + Commands:
+    /ain0/read x: returns a value between 0 to 1
+    /ain0/read_u16 x: returns a value between 0 to 0xFFFF
+
+4. PWM outputs:
+  + PWM outputs: pwm0 - pwm1
+  + Commands:
+    /pwm/period 0.5: Set the PWM period, specified in seconds (float), keeping the duty cycle the same.
+    /pwm/period_ms 500: Set the PWM period, specified in milli-seconds (int), keeping the duty cycle the same.
+    /pwm/pulsewidth 1: Set the PWM pulsewidth, specified in seconds (float), keeping the period the same.
+    /pwm/pulsewidth_ms 1000: Set the PWM pulsewidth, specified in milli-seconds (int), keeping the period the same.
+    /pwm/read x: Return the current output duty-cycle setting, measured as a percentage (float).
+    /pwm/write 0.6: Set the ouput duty-cycle, specified as a percentage (float).
+
+5. Timers:
+  + Timer: timer1
+  + Commands:
+    /timer1/start x
+    /timer1/stop x
+    /timer1/reset x
+    /timer1/read x: returns float, between 0 to 1.
+    /timer1/read_ms
+    /timer1/read_us
+
+6. UARTs:
+  + Uart: uart
+  + Commands:
+    /uart/baud 9600
+    /uart/putc 60: send ASCII code, '<'
+    /uart/getc x: return ASCII code
+    /uart/puts helloworld: print helloworld to serial port
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/protocol_v2.0.txt	Mon Dec 29 21:40:55 2014 +0000
@@ -0,0 +1,93 @@
+CONFIGURATION SECTION (UDP)
+A configuration command always starts with "NNCF"
+1. DISCOVERY Command
+    + UDP broadcast: 192.168.0.255 to port 11000
+    + Send: NNCFDS
+    + Receive: NNCF (4-bytes) MAC-address (6-bytes) IP-address
+1a. Query Command: IP, subnet, gateway, mac
+    + Send: NNCFIP (enter configuration mode), NNCFSN, NNCFGW, NNCFMC
+
+2. TCP SERVER PORT Command
+    + Send: NNCFTP
+    + Receive: 10000
+
+3. UDP SERVER PORT Command
+    + Send: NNCFUP
+    + Receive: 11000
+
+4. Set time using NTP Command    
+    + Send NNCFTM
+    + Receive:
+      DIS: if NTP is disabled
+      ERR: if cannot update time
+      Successful: Fri Sep 26 20:28:01 2014 {0A}
+      
+5. Set new network configuration
+    + Send: 19 bytes in total, NNCF + 15-byte
+      NNCF         4-byte IP address    4-byte subnet    4-byte gateway   3-byte MAC
+      4E 4E 43 46    C0 A8 00 78         FF FF FF 00       C0 A8 00 01     00 00 01
+
+6. Set TCP server info (only when the device is as a TCP client)
+    + Send: 12 bytes in total, NNIO + 8 bytes
+      NNCF         1-byte auto flag        1-byte time period (s)      4-byte IP       2-byte port (LSB MSB)
+      4E 4E 43 46  'Y' or others            05 (5s)                   C0 A8 00 09       E0 2E (0x2EE0 = 12000)
+
+NOTE:
+1. Both TCP client and server are working. Can be enabled/disabled using u16enable_tcp_client/server flags in eeprom (not in use now).
+2. UDP server is always working.
+
+
+INTERFACING SECTION (TCP)
+4. Receiving Protocol: 58-bytes in total
+Ex in hex
+ID: 4E 4E 49 4F
+OP: 4F 4F 4F 4F 51
+IP: C0 A8 00 78
+DO: 48 48 48 48 48 48 48 48
+AO: 80 00 80 00 (no DAC)
+UART: 32-byte
+CR: 0D
+    
+    + Field ID (4-bytes) = NNIO
+    + Field OP (5-bytes): output control enable flag
+      Byte 1: Digital output
+      Byte 2: Analog output 0
+      Byte 3: Analog output 1
+      Byte 4: UART output
+      Byte 5: Command (Q: query status)
+      'O': enable controlling output
+      Others: disable controlling output
+      If Command is 'Q', device will update its outputs if needed and send its status including new outputs
+    + Field IP (4-bytes): device IP address
+    + Field DO[n] (8-bytes): digital output values
+      'H': output set to high
+      'L': output set to low
+    + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
+      no DAC
+    + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
+      no DAC
+    + UART output (32-bytes): max 32 bytes, stop string by NULL
+    + End char: CR
+    
+5. Sending Protocol: 39-bytes in total
+    + Field ID (4-bytes) = NNIO
+    + Field MAC (6-bytes)
+    + Field IP (4-bytes)
+    + Field DI[n]: 8-bit digital input values
+      'H' if input is HIGH
+      'L' if input is LOW
+    + Field DO[n]: 8-bit digital output values
+      'H' if output is HIGH
+      'L' if output is LOW
+    + Field AI_0 (2-bytes): analog 16-bit input value, normalised, channel 0
+      1st byte = LSB, 2nd byte = MSB
+    + Field AI_1 (2-bytes): analog 16-bit input value, normalised, channel 1
+      1st byte = LSB, 2nd byte = MSB
+    + Field AO_0 (2-bytes): 16-bit analog output value, channel 0
+      no DAC, fixed
+    + Field AO_1 (2-bytes): 16-bit analog output value, channel 1
+      no DAC, fixed
+    + End char: CR
+    
+6 Commands:
+    + QUERY STATUS ('Q')
\ No newline at end of file
--- a/readme.txt	Wed Dec 24 13:23:33 2014 +0000
+++ b/readme.txt	Mon Dec 29 21:40:55 2014 +0000
@@ -1,16 +1,3 @@
-#NNIO Command and Configuration Processors
-
-This version is forked from F103_NNIO git rev25:48dd18cc147c, which is used for running demos.
-It intends to separate command processor and method to receive commands.
-
-v2.0 24/12/2014
-    + Use official mbed-rtos.
-
-
-
-
-
-
 Features
 0. Wait for 2s after resetting for ethernet to work.
 1. When auto update enabled and no TCP server is running, module will try to connect to server which results in a timeout every 15s.
@@ -34,5 +21,12 @@
     + Added: Discovery command now returns NNIO MAC IP
     + Added: receive and process receiving protocol using UDP
 
-v1.2.1 01/12/2014
-    + Modified: enter config mode with query ip command, not discovery command
\ No newline at end of file
+v1.2.1 01/12/2014 (demo version: git rev25)
+    + Modified: enter config mode with query ip command, not discovery command
+
+v2.0 24/12/2014
+    + Use official mbed-rtos
+    + Updated: configuration comands now use prefix NNCF, control commands use prefix NNIO.
+    + Run with demo software v2.0
+    + Added RPC through TCP/UDP: tested after fixed (Rpc)DigitalIn/Out names.
+      RPC control commands can be sent to TCP/UDP server on NNIO module. However, no reply yet, only debug with uart.
\ No newline at end of file