test code for our MBED board

Dependencies:   mbed lwip

Files at this revision

API Documentation at this revision

Comitter:
lolpcc
Date:
Wed May 04 08:30:52 2011 +0000
Parent:
0:9edfcca7cd25
Commit message:

Changed in this revision

DstZones.h Show annotated file Show diff for this revision Revisions of this file
FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.h Show annotated file Show diff for this revision Revisions of this file
SNTPClient.cpp Show annotated file Show diff for this revision Revisions of this file
SNTPClient.h Show annotated file Show diff for this revision Revisions of this file
analog.c Show annotated file Show diff for this revision Revisions of this file
analog.h Show annotated file Show diff for this revision Revisions of this file
breakup.c Show annotated file Show diff for this revision Revisions of this file
breakup.h Show annotated file Show diff for this revision Revisions of this file
can.c Show annotated file Show diff for this revision Revisions of this file
can.h Show annotated file Show diff for this revision Revisions of this file
can_layer.h Show annotated file Show diff for this revision Revisions of this file
cmd.c Show annotated file Show diff for this revision Revisions of this file
cmd.h Show annotated file Show diff for this revision Revisions of this file
diags.h Show diff for this revision Revisions of this file
digital.c Show annotated file Show diff for this revision Revisions of this file
digital.h Show annotated file Show diff for this revision Revisions of this file
help_data.h Show annotated file Show diff for this revision Revisions of this file
i2c.c Show annotated file Show diff for this revision Revisions of this file
i2c.h Show annotated file Show diff for this revision Revisions of this file
led.c Show annotated file Show diff for this revision Revisions of this file
led.h Show annotated file Show diff for this revision Revisions of this file
led_diag.c Show diff for this revision Revisions of this file
local_defines.h Show annotated file Show diff for this revision Revisions of this file
main.c Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
main.h Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
network.c Show annotated file Show diff for this revision Revisions of this file
network.h Show annotated file Show diff for this revision Revisions of this file
pca9685_reg.h Show annotated file Show diff for this revision Revisions of this file
precomp.lib Show annotated file Show diff for this revision Revisions of this file
scripting.c Show annotated file Show diff for this revision Revisions of this file
scripting.h Show annotated file Show diff for this revision Revisions of this file
serial.c Show annotated file Show diff for this revision Revisions of this file
serial.h Show annotated file Show diff for this revision Revisions of this file
sntp.c Show annotated file Show diff for this revision Revisions of this file
sntp.h Show annotated file Show diff for this revision Revisions of this file
sound.c Show annotated file Show diff for this revision Revisions of this file
sound.h Show annotated file Show diff for this revision Revisions of this file
ticker.c Show annotated file Show diff for this revision Revisions of this file
ticker.h Show annotated file Show diff for this revision Revisions of this file
useful.c Show annotated file Show diff for this revision Revisions of this file
useful.h Show annotated file Show diff for this revision Revisions of this file
diff -r 9edfcca7cd25 -r 6877bb99aa17 DstZones.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DstZones.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,30 @@
+// DstZone.h
+// Written by iva2k
+//
+// Data-driven implementation of DST zones.
+// This file is included into many places.
+// _() macro is defined for each specific use.
+
+// zone is DST symbol
+// pFnc is NULL or custom function of pFncDstCalc type
+// gmt 0..1
+// dst - shift in seconds (typically 3600)
+// hr 0..23
+// wk 0=last, 1=first, 2=second, etc.
+// wday 0=Sunday
+// mon 0..11
+// _( z, fnc, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2 )
+// zone,       pFnc, gmt,dst, 1:hr,wk,wday,mon, 2:hr,wk,wday,mon
+//------------------------------------------------------------------------------
+_( DST_NONE,   NULL, 0,    0,    0, 0, 0, 0,    0, 0, 0,  0 )
+    // USA: 3600; 2, Second SUN, March; 2, First SUN, November
+_( DST_USA,    NULL, 0, 3600,    2, 2, 0, 2,    2, 1, 0, 10 )
+    // USA: 3600; 2, First SUN, April; 2, Last SUN, October (Pre-2007)
+_( DST_USA_06, NULL, 0, 3600,    2, 1, 0, 3,    2, 0, 0,  9 )
+    // EU: 3600; 1GMT, Last SUN, March; 1GMT, Last SUN, October
+_( DST_EU_GMT, NULL, 1, 3600,    1, 0, 0, 2,    1, 0, 0,  9 )
+//    // Just for test
+//_( DST_TEST,   NULL, 0, 3600,   18, 1, 2, 0,   12, 1, 4,  0 )
+
+#undef _
+//END
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 FATFileSystem.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 SDFileSystem.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.cpp	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,294 @@
+/* mbed Microcontroller Library - SDFileSystem
+ * Copyright (c) 2008-2009, sford
+ *
+ * Introduction
+ * ------------
+ * SD and MMC cards support a number of interfaces, but common to them all
+ * is one based on SPI. This is the one I'm implmenting because it means
+ * it is much more portable even though not so performant, and we already 
+ * have the mbed SPI Interface!
+ *
+ * The main reference I'm using is Chapter 7, "SPI Mode" of: 
+ *  http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
+ *
+ * SPI Startup
+ * -----------
+ * The SD card powers up in SD mode. The SPI interface mode is selected by
+ * asserting CS low and sending the reset command (CMD0). The card will 
+ * respond with a (R1) response.
+ *
+ * CMD8 is optionally sent to determine the voltage range supported, and 
+ * indirectly determine whether it is a version 1.x SD/non-SD card or 
+ * version 2.x. I'll just ignore this for now.
+ *
+ * ACMD41 is repeatedly issued to initialise the card, until "in idle"
+ * (bit 0) of the R1 response goes to '0', indicating it is initialised.
+ *
+ * You should also indicate whether the host supports High Capicity cards,
+ * and check whether the card is high capacity - i'll also ignore this
+ *
+ * SPI Protocol
+ * ------------
+ * The SD SPI protocol is based on transactions made up of 8-bit words, with
+ * the host starting every bus transaction by asserting the CS signal low. The
+ * card always responds to commands, data blocks and errors.
+ * 
+ * The protocol supports a CRC, but by default it is off (except for the 
+ * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
+ * I'll leave the CRC off I think! 
+ * 
+ * Standard capacity cards have variable data block sizes, whereas High 
+ * Capacity cards fix the size of data block to 512 bytes. I'll therefore
+ * just always use the Standard Capacity cards with a block size of 512 bytes.
+ * This is set with CMD16.
+ *
+ * You can read and write single blocks (CMD17, CMD25) or multiple blocks 
+ * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
+ * the card gets a read command, it responds with a response token, and then 
+ * a data token or an error.
+ * 
+ * SPI Command Format
+ * ------------------
+ * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
+ *
+ * +---------------+------------+------------+-----------+----------+--------------+
+ * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
+ * +---------------+------------+------------+-----------+----------+--------------+
+ *
+ * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
+ *
+ * All Application Specific commands shall be preceded with APP_CMD (CMD55).
+ *
+ * SPI Response Format
+ * -------------------
+ * The main response format (R1) is a status byte (normally zero). Key flags:
+ *  idle - 1 if the card is in an idle state/initialising 
+ *  cmd  - 1 if an illegal command code was detected
+ *
+ *    +-------------------------------------------------+
+ * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
+ *    +-------------------------------------------------+
+ *
+ * R1b is the same, except it is followed by a busy signal (zeros) until
+ * the first non-zero byte when it is ready again.
+ *
+ * Data Response Token
+ * -------------------
+ * Every data block written to the card is acknowledged by a byte 
+ * response token
+ *
+ * +----------------------+
+ * | xxx | 0 | status | 1 |
+ * +----------------------+
+ *              010 - OK!
+ *              101 - CRC Error
+ *              110 - Write Error
+ *
+ * Single Block Read and Write
+ * ---------------------------
+ *
+ * Block transfers have a byte header, followed by the data, followed
+ * by a 16-bit CRC. In our case, the data will always be 512 bytes.
+ *  
+ * +------+---------+---------+- -  - -+---------+-----------+----------+
+ * | 0xFE | data[0] | data[1] |        | data[n] | crc[15:8] | crc[7:0] | 
+ * +------+---------+---------+- -  - -+---------+-----------+----------+
+ */
+ 
+#include "SDFileSystem.h"
+
+#define SD_COMMAND_TIMEOUT 5000
+
+SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
+  FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
+  	_cs = 1; 
+}
+
+int SDFileSystem::disk_initialize() {
+
+	_spi.frequency(100000); // Set to 100kHz for initialisation
+	
+	// Initialise the card by clocking it a bit (cs = 1)
+	for(int i=0; i<16; i++) {   
+		_spi.write(0xFF);
+	}
+
+	// send CMD0, should return with all zeros except IDLE STATE set (bit 0)
+	if(_cmd(0, 0) != 0x01) { 
+		fprintf(stderr, "Not in idle state\n");
+		return 1;
+	}
+	
+	// ACMD41 to give host capacity support (repeat until not busy)
+	// ACMD41 is application specific command, so we send APP_CMD (CMD55) beforehand
+	for(int i=0;; i++) {
+		_cmd(55, 0); 
+		int response = _cmd(41, 0);
+		if(response == 0) { 
+			break;
+		} else if(i > SD_COMMAND_TIMEOUT) {
+			fprintf(stderr, "Timeout waiting for card\n");
+			return 1;
+		}	
+	}
+
+	_sectors = _sd_sectors();
+
+	// Set block length to 512 (CMD16)
+	if(_cmd(16, 512) != 0) {
+		fprintf(stderr, "Set block timeout\n");
+		return 1;
+	}
+		
+	_spi.frequency(1000000); // Set to 1MHz for data transfer
+	return 0;
+}
+
+int SDFileSystem::disk_write(const char *buffer, int block_number) {
+	// set write address for single block (CMD24)
+	if(_cmd(24, block_number * 512) != 0) {
+		return 1;
+	}
+
+	// send the data block
+	_write(buffer, 512);	
+	return 0;	
+}
+
+int SDFileSystem::disk_read(char *buffer, int block_number) {		
+	// set read address for single block (CMD17)
+	if(_cmd(17, block_number * 512) != 0) {
+		return 1;
+	}
+	
+	// receive the data
+	_read(buffer, 512);
+	return 0;
+}
+
+int SDFileSystem::disk_status() { return 0; }
+int SDFileSystem::disk_sync() { return 0; }
+int SDFileSystem::disk_sectors() { return _sectors; }
+
+// PRIVATE FUNCTIONS
+
+int SDFileSystem::_cmd(int cmd, int arg) {
+	_cs = 0; 
+
+	// send a command
+	_spi.write(0x40 | cmd);
+	_spi.write(arg >> 24);
+	_spi.write(arg >> 16);
+	_spi.write(arg >> 8);
+	_spi.write(arg >> 0);
+	_spi.write(0x95);
+
+	// wait for the repsonse (response[7] == 0)
+	for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
+		int response = _spi.write(0xFF);
+		if(!(response & 0x80)) {
+			_cs = 1;
+			return response;
+		}
+	}
+	_cs = 1;
+	return -1; // timeout
+}
+
+int SDFileSystem::_read(char *buffer, int length) {
+	_cs = 0;
+
+	// read until start byte (0xFF)
+	while(_spi.write(0xFF) != 0xFE);
+
+	// read data
+	for(int i=0; i<length; i++) {
+		buffer[i] = _spi.write(0xFF);
+	}
+	_spi.write(0xFF); // checksum
+	_spi.write(0xFF);
+
+	_cs = 1;	
+	return 0;
+}
+
+int SDFileSystem::_write(const char *buffer, int length) {
+	_cs = 0;
+	
+	// indicate start of block
+	_spi.write(0xFE);
+	
+	// write the data
+	for(int i=0; i<length; i++) {
+		_spi.write(buffer[i]);
+	}
+	
+	// write the checksum
+	_spi.write(0xFF); 
+	_spi.write(0xFF);
+
+	// check the repsonse token
+	if((_spi.write(0xFF) & 0x1F) != 0x05) {
+		_cs = 1; 
+		return 1;
+	}
+
+	// wait for write to finish
+	while(_spi.write(0xFF) == 0);
+
+	_cs = 1; 
+	return 0;
+}
+
+static int ext_bits(char *data, int msb, int lsb) {
+	int bits = 0;
+	int size = 1 + msb - lsb; 
+	for(int i=0; i<size; i++) {
+		int position = lsb + i;
+		int byte = 15 - (position >> 3);
+		int bit = position & 0x7;
+		int value = (data[byte] >> bit) & 1;
+		bits |= value << i;
+	}
+	return bits;
+}
+
+int SDFileSystem::_sd_sectors() {
+
+	// CMD9, Response R2 (R1 byte + 16-byte block read)
+	if(_cmd(9, 0) != 0) {
+		fprintf(stderr, "Didn't get a response from the disk\n");
+		return 0;
+	}
+	
+	char csd[16];	
+	if(_read(csd, 16) != 0) {
+		fprintf(stderr, "Couldn't read csd response from disk\n");
+		return 0;
+	}
+
+	// csd_structure : csd[127:126]
+	// c_size        : csd[73:62]
+	// c_size_mult   : csd[49:47]
+	// read_bl_len   : csd[83:80] 
+
+	int csd_structure = ext_bits(csd, 127, 126);
+	int c_size = ext_bits(csd, 73, 62);
+	int c_size_mult = ext_bits(csd, 49, 47);
+	int read_bl_len = ext_bits(csd, 83, 80);
+	
+	if(csd_structure != 0) {
+		fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures");
+		return 0;
+	}
+			                
+	int blocks = (c_size + 1) * (1 << (c_size_mult + 2));
+	int block_size = 1 << read_bl_len;
+
+	if(block_size != 512) {
+		fprintf(stderr, "This disk tastes funny! I only like 512-byte blocks");
+		return 0;
+	}
+	
+	return blocks;
+}
diff -r 9edfcca7cd25 -r 6877bb99aa17 SDFileSystem.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDFileSystem.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,56 @@
+/* mbed Microcontroller Library - SDFileSystem
+ * Copyright (c) 2008-2009, sford
+ */
+
+#ifndef SDFILESYSTEM_H
+#define SDFILESYSTEM_H
+
+#include "mbed.h"
+#include "FATFileSystem.h"
+
+/* Class: SDFileSystem
+ *  Access the filesystem on an SD Card using SPI
+ *
+ * Example:
+ * > SDFileSystem sd(p5, p6, p7, p12, "sd");
+ * > 
+ * > int main() {
+ * >     FILE *fp = fopen("/sd/myfile.txt", "w");
+ * >     fprintf(fp, "Hello World!\n");
+ * >     fclose(fp);
+ * > }
+ */
+class SDFileSystem : public FATFileSystem {
+public:
+
+	/* Constructor: SDFileSystem
+	 *  Create the File System for accessing an SD Card using SPI
+	 *
+	 * Variables:
+	 *  mosi - SPI mosi pin connected to SD Card
+	 *  miso - SPI miso pin conencted to SD Card
+	 *  sclk - SPI sclk pin connected to SD Card
+	 *  cs   - DigitalOut pin used as SD Card chip select
+   *  name - The name used to access the filesystem
+	 */
+	SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name);
+	virtual int disk_initialize();
+	virtual int disk_write(const char *buffer, int block_number);
+	virtual int disk_read(char *buffer, int block_number);	
+	virtual int disk_status();
+	virtual int disk_sync();
+	virtual int disk_sectors();
+
+protected:
+
+	int _cmd(int cmd, int arg);
+	int _read(char *buffer, int length);
+	int _write(const char *buffer, int length);
+	int _sd_sectors();
+	int _sectors;
+	
+	SPI _spi;
+	DigitalOut _cs;	 
+};
+
+#endif
diff -r 9edfcca7cd25 -r 6877bb99aa17 SNTPClient.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SNTPClient.cpp	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,802 @@
+/*
+ * SNTPClient.cpp
+ * SNTP (Simple NTP) client
+ * Written by iva2k
+ *
+ * Wrapper around LWIP/sntp for MBED, with DST rules.
+ * This implementation relies on:
+ *  1. LWIP (http://www.sics.se/~adam/lwip/) adopted for MBED
+ *     http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk
+ *  2. LWIP's contributed SNTP client (sntp.c and sntp.h) from
+ *     http://cvs.savannah.gnu.org/viewvc/contrib/apps/sntp/?root=lwip
+ *     (used version 1.8)
+ *
+ * Changes needed in LWIP/sntp:
+ *  -  pointer typecast (line 594) - fixes mbed compiler problem
+ *  -  #include "sntp.h" moved after lwip/opt.h et.al - for re-defines.
+ *  -  pbuf_free(p) in sntp_send_request() (line 602) - fixes memory leak BUG.
+ *  -  changing sntp_dns_found() to delayed sntp_try_next_server() - to unblock if network is disconnected.
+ *
+ * Changes in MBED's LWIP:
+ *  -  modified lwipopts.h (this file is automatically included into sntp.c)
+ *
+ * Requirements:
+ *  + direct RTC update from receiving the NTP time packet
+ *  + optionally support more than one NTP server
+ *  + the IP address of the NTP server(s) stored in a local file
+ *  + timeout error recovery should the NTP server(s) not be available.  No RTC update should the NTP access fail
+ *  + allow for a UTC offset, also stored in the local file
+ *  + DST correction
+ *  + use DNS for NTP servers IP address resolution
+ *  + periodic updates at specified time intervals
+ *
+ * TODO:
+ *  . DST correction
+ *  - record metrics (count of updates, failed tries?, correction more than epsilon, etc.?)
+ */
+
+#include "mbed.h"
+#include "lwip/opt.h"
+#include "SNTPClient.h"
+#include "useful.h"
+
+#define SNTP_EPSILON        10                // time difference noticed as big update (in seconds).
+
+//#define SNTP_DST_TESTS      // Define this to run DST algorithms tests
+
+typedef struct DST_ZONE_DESCR {
+    tDST_ZONE zone;
+    const char *name;
+    int gmt;
+    int dst;
+    int hr1;
+    int wk1;
+    int wday1;
+    int mon1;
+    int hr2;
+    int wk2;
+    int wday2;
+    int mon2;
+    pFncDstCalc fnc;
+} tDST_ZONE_DESR;
+
+static tDST_ZONE_DESR gSntpDstZones[] = {
+#define _(z, fnc, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2) \
+  { z, #z, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2, fnc },
+#include "DstZones.h"
+};
+#define DST_ZONE_DESCR_CNT    (sizeof(gSntpDstZones)/sizeof(gSntpDstZones[0]))
+
+const char *SNTPDstZoneName(tDST_ZONE zone) {
+    if (zone >= DST_ZONE_DESCR_CNT)
+        return "";
+    return gSntpDstZones[zone].name;
+}
+#ifdef __cplusplus
+extern "C" {
+#endif
+tDST_ZONE    gSntpDstZone = DST_NONE;       // DST zone - rule selector
+unsigned int gSntpRecvTimeout_s = 3;        // 3 sec; SNTP_RECV_TIMEOUT
+unsigned int gSntpUpdateDelay_s = 3600;     // 1 hour; SNTP_UPDATE_DELAY
+signed int   gSntpTimezone =  0*3600;       // seconds from UTC to local time
+signed int   gSntpDST      =  0*3600;       // seconds from UTC to local time
+bool         gSntpRtcUtc   = false;         // true to keep RTC in UTC, false to keep in local time
+unsigned int gSntpUpdates  = 0;             // Track number of all clock NTP updates
+unsigned int gSntpUpdatesBig = 0;           // Track number of significant clock NTP updates
+bool         gSntpRunning = false;          // true if SNTP service is running
+Timeout      gSntpDelay;                    // For async calls.
+Ticker       gSntpTicker;                   // There is no RTC interrupt on MBED (yet). Use (more wastefull) timer.
+time_t       gSntpRtcTCR = 0;               // Timer Capture Register equivalent (in RTC time - either local or UTC depending on gSntpRtcUtc)
+signed int   gSntpRtcTCRDST = 0;            // New DST value for when RTC crosses gSntpRtcTCR
+
+static void SNTPSetDSTEx(unsigned int dst, bool adjust_clock) {
+    if (adjust_clock && !gSntpRtcUtc && gSntpDST != dst) {
+        time_t seconds = time(NULL);
+        seconds -= gSntpDST;                // Convert from old local time
+        seconds += dst;                     // Convert to   new local time
+        set_time(seconds);
+        if (gSntpRtcTCR) {
+            // Adjust our alarm clock
+            gSntpRtcTCR -= gSntpDST;
+            gSntpRtcTCR += dst;
+        }
+    }
+    gSntpDST = dst;
+}
+
+#if 0
+// Custom DST zone function example
+// USA (since 2007)
+// Calculate start or stop DST point for given year based on rules
+// tz    - Timezone
+// year  - current year. DST changes well away from year end, so does not matter what timezone.
+// start - DST_START for start, DST_STOP for stop
+// Returns DST point (in local time). DST_STOP time is in DST
+static tDstPoint _sntp_dst_calc_custom(int tz, int year, tDST_START start) {
+    tDstPoint ret;
+    struct tm t;
+
+    // USA: 3600; 2, Second SUN, March; 2, First SUN, November
+    int dst = 3600;     // DST shift (seconds)
+    int hour;           // Hour of the change
+    int N;              // Week in the month
+    int wday;           // Day of the week
+    int month;
+    if (start == DST_START) {
+        hour  = 2;      // (0-23) Hour of the change
+        N     = 2-1;    // 2nd in the month
+        wday  = 0;      // Sunday
+        month = 2;      // March
+    } else {  // DST_STOP
+        hour  = 2;      // (0-23) Hour of the change
+        N     = 1-1;    // 1st in the month
+        wday  = 0;      // Sunday
+        month = 10;     // November
+    }
+
+    t.tm_sec  = 0;              // 0-59
+    t.tm_min  = 0;              // 0-59
+    t.tm_hour = hour;           // 0-23
+    t.tm_year = year - 1900;    // 
+    t.tm_mon  = month;          // 0-11
+    t.tm_mday = 1+N*7;          // 1-31, first possible date for Nth given weekday
+    mktime(&t);                 // Calculate tm_wday
+    t.tm_mday += (wday-t.tm_wday+14)%7;   // Shift to wday
+    ret.t = mktime(&t);
+    ret.dst = (start == DST_START) ? dst : 0;
+    ret.dstshift = dst;
+    return ret;
+}
+#endif
+
+// Calculate start or stop DST point for given year based on rules for the DST zone
+// tz    - Timezone
+// zone  - DST zone
+// year  - current year. DST changes well away from year end, so does not matter timezone.
+// start - DST_START for start, DST_STOP for stop
+// Returns DST point (in standard local time). DST_STOP time is in NOT IN DST
+static tDstPoint _sntp_dst_calc(int tz, tDST_ZONE zone, int year, tDST_START start) {
+    tDstPoint ret;
+
+    ret.t = 0;
+    ret.dst = 0;
+    ret.dstshift = 0;
+    if (zone == DST_NONE || zone >= DST_ZONE_DESCR_CNT)
+        return ret;
+
+    tDST_ZONE_DESR *descr = &gSntpDstZones[zone];
+    if (descr->fnc) {
+        // Use custom function
+        ret = descr->fnc(tz, year, start);
+    } else {
+        // Use rules
+        struct tm t;
+        t.tm_sec  = 0;              // 0-59
+        t.tm_min  = 0;              // 0-59
+        t.tm_hour = (start == DST_START) ? descr->hr1  : descr->hr2;
+        t.tm_year = year - 1900;    // 
+        t.tm_mon  = (start == DST_START) ? descr->mon1 : descr->mon2;          // 0-11
+        int wk    =((start == DST_START) ? descr->wk1  : descr->wk2) -1;
+        int wday  = (start == DST_START) ? descr->wday1: descr->wday2;
+        if (wk < 0) {
+            // For "Last in the month" - we go to next month, then move back by one week
+            t.tm_mon  += 1;         // 0-11
+            if (t.tm_mon > 11) {
+                t.tm_mon  -= 12;
+                t.tm_year += 1;
+            }
+            t.tm_mday = 1+0*7;      // 1-31, first possible date for Nth given weekday
+        } else {
+            t.tm_mday = 1+wk*7;      // 1-31, first possible date for Nth given weekday
+        }
+        mktime(&t);                 // Calculate tm_wday
+        t.tm_mday += (wday-t.tm_wday+14)%7;   // Shift to wday
+        ret.t = mktime(&t);
+        if (wk < 0) {
+            ret.t -= 7 * 24 * 3600;
+        }
+        if (descr->gmt) {
+            ret.t += tz;
+        }
+        ret.dst = (start == DST_START) ? descr->dst : 0;
+        ret.dstshift = descr->dst;
+    }
+    if (start == DST_STOP) {
+        ret.t -= ret.dstshift;
+        // this correction is due to the fact that rules are given in local time with DST,
+        // but calculations are made in standard local time (without DST adjustment)
+    }
+    return ret;
+}
+
+// Calculate desired DST point relative to now based on rules for the DST zone
+// tz    - timezone
+// zone  - DST zone
+// now   - current time (standard local time = excluding DST).
+// index - 0 for immediate next, +1 for second next, -1 for immediate previous
+// Returns DST point (in standard local time)
+static tDstPoint _sntp_dst_point(int tz, tDST_ZONE zone, time_t now, int index) {
+    tDstPoint ret;
+    int year;
+    tDST_START type;
+    struct tm *pt = localtime(&now);
+    ret.t = 0;
+    ret.dst = 0;
+    ret.dstshift = 0;
+    if (zone == DST_NONE || zone >= DST_ZONE_DESCR_CNT)
+        return ret;
+
+// Algorithm
+// 1. Determine where now is in respect to current year DST points (find for index=0) 
+// 2. Use index to shift year and type 
+// 3. return the point
+// This algorithm relies on DST start date being before DST stop date in the year.
+    year = pt->tm_year + 1900;
+    type = DST_START;
+    ret = _sntp_dst_calc(tz, zone, year, type);
+    if (now > ret.t) {
+        type = DST_STOP;
+        ret = _sntp_dst_calc(tz, zone, year, type);
+        if (now > ret.t) {
+            // It is next year's start point
+            type = DST_START;
+            year += 1;
+        }
+    }
+    // Now year and type are right for index=0
+
+    // Calculate where index points to - shift year and type    
+    int norm = (index > 0) ? (int)(index/2) : (int)((index-1)/2);
+    year  += norm;
+    index -= norm*2;    // Now index is (0,1)
+    if (index) {
+        // Flip the type
+        type = (type == DST_START) ? DST_STOP : DST_START;
+    }
+
+    ret = _sntp_dst_calc(tz, zone, year, type);
+    return ret;
+//    struct tm t;
+//    t.tm_sec  = 0;     // 0-59
+//    t.tm_min  = 0;     // 0-59
+//    t.tm_hour = 0;     // 0-23
+//    t.tm_mday = 0;     // 1-31
+//    t.tm_mon  = 0;     // 0-11
+//    t.tm_year = 2005-1900;     // year since 1900
+//    t.tm_wday = 0;     // 0-6 Day of week (Sunday = 0)
+//    t.tm_yday = 0;     // Day of year (0 - 365)
+//    t.tm_isdst = -1;   // Nonzero = Daylight saving time
+}
+
+#if defined(LWIP_DEBUG)
+// Print DST dates report
+static void _sntp_dst_dates(int tz, tDST_ZONE zone, int year) {
+    char _buffer[64];
+    tDstPoint r;
+    printf("\r\nDST DATES for zone %d/%s:\r\n", (int)zone, SNTPDstZoneName(zone));
+    r = _sntp_dst_calc(tz, zone, year, DST_START);
+    strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+    printf("    %d DST BEGINS (+%04d sec) %s\r\n", year, r.dst, _buffer);
+
+    r = _sntp_dst_calc(tz, zone, year, DST_STOP);
+    strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+    printf("    %d DST ENDS   (+%04d sec) %s\r\n", year, r.dst, _buffer);
+}
+#endif
+#ifdef SNTP_DST_TESTS
+static void test_sntp_dst_calc(int tz, tDST_ZONE zone) {
+    char _buffer[64];
+    tDstPoint r;
+    int year;
+
+    printf("\r\nTEST: _sntp_dst_calc(tz=%d, zone=%d/%s)\r\n", tz, (int)zone, SNTPDstZoneName(zone));
+
+    for (year = 1999; year < 2016; year++) {
+        r = _sntp_dst_calc(tz, zone, year, DST_START);
+        strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+        printf("    (0,%d,start) %s %d\r\n", year, _buffer, r.dst);
+        r = _sntp_dst_calc(tz, zone, year, DST_STOP);
+        strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+        printf("    (0,%d,stop ) %s %d\r\n", year, _buffer, r.dst);
+    }
+}
+static void test_sntp_dst_point(int index) {
+    char _buffer[64];
+    struct tm t;
+    tDstPoint r;
+    int tz=gSntpTimezone;
+    tDST_ZONE zone=gSntpDstZone;
+    int year = 2009, day, month;
+
+    int norm = (index > 0) ? (int)(index/2) : (int)((index-1)/2);
+    printf("\r\nTEST: _sntp_dst_point(%d) norm=%d\r\n", index, norm);
+    t.tm_sec  = 0;              // 0-59
+    t.tm_min  = 0;              // 0-59
+    t.tm_hour = 9;              // 0-23
+    t.tm_year = year-1900;
+    day = 1;
+    for (month = 0; month < 2; month++) {
+      t.tm_mon = month;
+      t.tm_mday = day;
+      t.tm_year = year-1900;
+      r = _sntp_dst_point(tz, zone, mktime(&t), index);
+      strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+      printf("    (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst);
+    }
+    for (day = 1; day < 32; day++) {
+      t.tm_mon = month;
+      t.tm_mday = day;
+      t.tm_year = year-1900;
+      r = _sntp_dst_point(tz, zone, mktime(&t), index);
+      strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+      printf("    (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst);
+    }
+    day = 30;
+    for (; month < 10; month++) {
+      t.tm_mon = month;
+      t.tm_mday = day;
+      t.tm_year = year-1900;
+      r = _sntp_dst_point(tz, zone, mktime(&t), index);
+      strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+      printf("    (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst);
+    }
+
+    for (day = 1; day < 32; day++) {
+      t.tm_mon = month;
+      t.tm_mday = day;
+      t.tm_year = year-1900;
+      r = _sntp_dst_point(tz, zone, mktime(&t), index);
+      strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t));
+      printf("    (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst);
+    }
+}
+#endif  // SNTP_DST_TESTS
+// Set current DST
+static void _sntp_dst_now(void) {
+    time_t now = time(NULL);
+    // Convert to standart local time (no DST)
+    now = gSntpRtcUtc ? (now + gSntpTimezone) : (now - gSntpDST);
+
+    // Check DST setting for now
+    tDstPoint dst = _sntp_dst_point(gSntpTimezone, gSntpDstZone, now, -1);
+#ifdef LWIP_DEBUG
+    char _buffer[64];
+    strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&dst.t));
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, (
+        "DEBUG: _sntp_dst_now(%d) based on last DST change on (%d) %s to (+%04d sec)\r\n",
+         now, dst.t, _buffer, dst.dst));
+#endif
+    // Change RTC
+    SNTPSetDSTEx(dst.dst, true);
+}
+
+// Plan for next DST change
+static void _sntp_dst_schedule(void) {
+    time_t now = time(NULL);
+    // Convert to standart local time (no DST)
+    now = gSntpRtcUtc ? (now + gSntpTimezone) : (now - gSntpDST);
+    // Check next DST change point
+    tDstPoint dst = _sntp_dst_point(gSntpTimezone, gSntpDstZone, now, 0);
+    if (dst.t) {
+#ifdef LWIP_DEBUG
+        char _buffer[64];
+        strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&dst.t));
+#endif
+
+        // Set our alarm clock
+        // Convert from standard local to UTC time or local time
+        dst.t = gSntpRtcUtc ? (dst.t - gSntpTimezone) : (dst.t + gSntpDST);
+
+#ifdef LWIP_DEBUG
+        if (time(NULL) > dst.t) {
+            LWIP_DEBUGF(SNTP_DEBUG_STATE, (
+            "DEBUG: _sntp_dst_schedule() ASSERTION FAILED !(%d<%d) trying to schedule for the past: %s (+%04d sec)\r\n",
+             time(NULL), dst.t, _buffer, dst.dst));
+        } else {
+            LWIP_DEBUGF(SNTP_DEBUG_STATE, (
+            "DEBUG: _sntp_dst_schedule() scheduled in %d seconds, set for %s (+%04d sec)\r\n",
+             dst.t-time(NULL), _buffer, dst.dst));
+        }
+#endif
+    }
+    gSntpRtcTCR = dst.t;
+    gSntpRtcTCRDST = dst.dst;
+}
+
+// RTC ISR - called upon each RTC tick
+static void _sntp_isr(void) {
+    time_t seconds = time(NULL);
+    if (gSntpRtcTCR && seconds > gSntpRtcTCR ) {
+        // DST change has arrived
+        gSntpRtcTCR = 0;
+        // Disable ISR and avoid extra calcs in SNTPSetDSTEx()
+//if (gSntpRtcTCRDST != gSntpDST) {
+        // Change to/from DST
+        SNTPSetDSTEx(gSntpRtcTCRDST, true);
+        gSntpRtcTCRDST = 0;
+        // Schedule callback to plan for next DST change (take it out of ISR context)
+        gSntpDelay.attach(_sntp_dst_schedule, 1.0);
+#ifdef LWIP_DEBUG
+        char _buffer[64];
+        if (gSntpRtcUtc) {
+            seconds += gSntpTimezone + gSntpDST;     // Convert to local time
+        }
+        strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&seconds));
+        LWIP_DEBUGF(SNTP_DEBUG_STATE, (
+        "DEBUG: _sntp_isr() changed DST. datetime=%s\r\n", _buffer));
+#endif
+//}
+    }
+}
+
+// NTP Callback - timestamp from NTP server arrives here
+void SntpClientSet(time_t seconds) {
+    time_t old_seconds = time(NULL);
+    if (!gSntpRtcUtc) {
+        seconds += gSntpTimezone + gSntpDST;     // Convert to local time
+    }
+    set_time(seconds);
+
+    // Special tasks for the very first NTP updates
+    if (!gSntpUpdates) {
+#if defined(LWIP_DEBUG)
+        // Report DST dates for the zone
+        struct tm *pt = localtime(&seconds);
+        _sntp_dst_dates(gSntpTimezone, gSntpDstZone, pt->tm_year+1900);
+#endif
+
+        // DST scheduler
+        _sntp_dst_now();
+        _sntp_dst_schedule();
+
+        // Enable RTC ISR
+        gSntpTicker.attach(_sntp_isr, 1.0);
+    }
+    if (gSntpUpdates && abs((int)(old_seconds - seconds)) > SNTP_EPSILON) {
+        printf("SNTP settime() corrected big difference: (%d) seconds, more than %d. Big updates count=%d.\r\n",
+            old_seconds-seconds, SNTP_EPSILON, gSntpUpdatesBig);
+        gSntpUpdatesBig ++;
+    }
+
+    gSntpUpdates++;
+
+    if (1) {
+        char _buffer[64];
+        if (gSntpRtcUtc) {
+            seconds += gSntpTimezone + gSntpDST;     // Convert to local time
+        }
+        strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&seconds));
+        printf("SNTP settime() #%d seconds=%d TZ=%0.1f datetime=%s\r\n",
+          gSntpUpdates, seconds, gSntpTimezone/3600.0, _buffer);
+    }
+}
+#ifdef __cplusplus
+};
+#endif
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "lwip/def.h"
+#include "lwip/pbuf.h"
+#include "lwip/sys.h"
+#include "lwip/stats.h"
+#include "netif/etharp.h"
+#include "string.h"
+#ifdef __cplusplus
+};
+#endif
+// Accomodating sntp timeout functions
+#if NO_SYS
+#include "sntp.h"
+extern void sntp_request(void *arg);    // this is dirty hack around "static" function. Some linkers may revolt!
+extern void sntp_try_next_server(void *arg);
+extern char* sntp_server_addresses[];
+extern u8_t sntp_current_server;
+extern u8_t sntp_num_servers;
+static void (*sntp_addresses_free)(void*) = NULL;
+static Timeout _sntp_timer1;
+static Timeout _sntp_timer2;
+void sntp_sys_timeout(u32_t timeout_s, void (*func)(void *arg), void *arg) {
+// all we really need to track is only 2 functions: sntp_request, sntp_try_next_server
+    Timeout *t = NULL;
+    if (func == &sntp_request) {
+        t = &_sntp_timer1;
+        LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_timeout(), func=sntp_request\r\n"));
+    } else if (func == &sntp_try_next_server) {
+        t = &_sntp_timer2;
+        LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_timeout(), func=sntp_try_next_server\r\n"));
+    }
+    if (t) {
+        t->detach();
+        t->attach((void(*)(void))func, 1.0*timeout_s);
+        // Another shortcut - we have no arg to pass, so just typecast the func.
+    }
+}
+void sntp_sys_untimeout(void (*func)(void *arg), void *arg) {
+
+    Timeout *t = NULL;
+    if (func == &sntp_request) {
+        t = &_sntp_timer1;
+        LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_untimeout(), func=sntp_request\r\n"));
+    } else if (func == &sntp_try_next_server) {
+        t = &_sntp_timer2;
+        LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_untimeout(), func=sntp_try_next_server\r\n"));
+    }
+    if (t) {
+        t->detach();
+    }
+}
+
+#else  // NO_SYS
+#error "I don't know how to compile LWIP/SNTP with NO_SYS=0"
+#endif // NO_SYS
+
+// Can be called when already running
+void SNTPSetDstZone(tDST_ZONE zone) {
+    if (zone >= DST_ZONE_DESCR_CNT)
+        return;   // ERR_INVALID_ARG
+    gSntpDstZone = zone;
+
+    if (gSntpRunning) {
+        // DST scheduler
+        _sntp_dst_now();
+        _sntp_dst_schedule();
+    }
+}
+
+
+void SNTPSetRecvTimeout(unsigned int val_s) { gSntpRecvTimeout_s = val_s; }
+void SNTPSetUpdateDelay(unsigned int val_s) { gSntpUpdateDelay_s = val_s; }
+void SNTPSetTimezone(float hours_from_utc, bool adjust_clock) {
+    if (adjust_clock && !gSntpRtcUtc) {
+        time_t seconds = time(NULL);
+        seconds -= gSntpTimezone;           // Convert from old local time
+        seconds += hours_from_utc * 3600;   // Convert to   new local time
+        set_time(seconds);
+        if (gSntpRtcTCR) {
+            // Adjust our alarm clock
+            gSntpRtcTCR -= gSntpTimezone;
+            gSntpRtcTCR += hours_from_utc * 3600;
+        }
+    }
+    gSntpTimezone = hours_from_utc * 3600;
+}
+
+void SNTPSetDST(float hours_from_utc, bool adjust_clock) {
+    SNTPSetDSTEx(hours_from_utc * 3600, adjust_clock);
+}
+
+static int sntp_num_servers_alloc = 0;
+
+static void _SNTPClrAddresses(void) {
+    if (!sntp_num_servers_alloc) sntp_num_servers_alloc = sntp_num_servers;
+    // Here we save the original size of the sntp_server_addresses[] array.
+
+    if (sntp_addresses_free) {
+        for (int i=0; i<sntp_num_servers; i++) {
+            sntp_addresses_free(sntp_server_addresses[i]);
+        }
+    }
+    sntp_current_server = 0;
+    sntp_num_servers = 0;
+    sntp_addresses_free = NULL;
+}
+
+static int _SNTPAddAddress(const char* server_address) {
+    if (sntp_num_servers+1 > sntp_num_servers_alloc)
+        return -1;
+    sntp_server_addresses[sntp_num_servers] = (char*)malloc(strlen(server_address)+1);
+    if (sntp_server_addresses[sntp_num_servers] == NULL) return -1;    // Out of memory
+    strcpy(sntp_server_addresses[sntp_num_servers], server_address);
+    sntp_num_servers++;
+    return 0;
+}
+
+// Override default servers list.
+// For no-copy, pass pointer to free() in p_free.
+// Returns: actual number of servers set (limited by allocated buffer size)
+// WARNING! There is no interlock to ensure that SNTP service does not read its data while we are updating it.
+// This function is intended to be called only before SNTPClientInit().
+
+int SNTPSetAddresses(const char* server_addresses[], int count, void (*p_free)(void*)) {
+    // In order to use sntp.c as-is, we hack into its static variables.
+    // Not all compilers/linkers will support that.
+
+    _SNTPClrAddresses();
+    if (count > sntp_num_servers_alloc)
+        count = sntp_num_servers_alloc;
+    for (int i=0; i<count; i++) {
+        if (p_free) {
+            sntp_server_addresses[i] = (char *)server_addresses[i];
+        } else {
+            _SNTPAddAddress(server_addresses[i]);
+        }
+    }
+    sntp_num_servers = count;
+    sntp_current_server = 0;
+    sntp_addresses_free = p_free ? p_free : &free;
+    return count;
+}
+
+
+// Trim whitespace/CRLFs from both ends of a given string
+char * str_cleanup(char *in) {
+    char * out = in;
+    // Trim leading spaces and CR/LF
+    while (*out == ' ' || *out == '\t' || *out == '\r' || *out == '\n')
+        out ++;
+    // Trim trailing spaces and CR/LF
+    int len = strlen(out)-1;
+    while (out[len] == ' ' || out[len] == '\t' || out[len] == '\r' || out[len] == '\n') {
+        out[len] = '\0';
+        len--;
+    }
+    return out;
+}
+
+
+
+#ifndef CRLF
+#define CRLF "\r\n"
+#endif
+
+void SNTPWriteIniFile(FILE * f) {
+
+    fprintf(f, "# SNTP Configuration file" CRLF);
+    fprintf(f, CRLF "[Servers]" CRLF);
+    for (int i=0; i<sntp_num_servers; i++) {
+        fprintf(f, "%s" CRLF, sntp_server_addresses[i]);
+    }
+    fprintf(f, CRLF "[Global]" CRLF);
+    fprintf(f, "RtcUtc=%d" CRLF, (int)gSntpRtcUtc);
+    fprintf(f, "Timezone=%0.1f" CRLF, gSntpTimezone / 3600.0);
+    fprintf(f, "DstZone=%d" CRLF, gSntpDstZone);
+    fprintf(f, "# %s" CRLF, SNTPDstZoneName(gSntpDstZone));
+    fprintf(f, "UpdateDelay=%d" CRLF, gSntpUpdateDelay_s);
+    fprintf(f, "RecvTimeout=%d" CRLF, gSntpRecvTimeout_s);
+    fprintf(f, CRLF "##END" CRLF);
+}
+
+// Simple ini file parser for SNTP configuration (Case-sensitive!)
+// This function is intended to be called only before SNTPClientInit().
+// Returns: 0 if OK, errno otherwise
+enum {
+  SECT_NONE,
+  SECT_SERVERS,
+  SECT_GLOBAL,
+};
+
+int SNTPReadIniFile(const char* filename) {
+    FILE *f;
+    char buf[512];
+    bool addresses_cleared = false;
+
+    f = fopen(filename, "r");
+    if (!f)
+        return -1;    // errno not used?
+
+    char *buf1, *buf2;
+    int section=SECT_NONE;
+    int line = 0;
+    while (fgets(buf, sizeof(buf)/sizeof(buf[0]), f)) {
+        line++;
+        buf1 = str_cleanup(buf);
+        if (*buf1 == '#' || *buf1 == '\0')
+            continue;    // Comment line or empty line - skip
+        if (*buf1 == '[') {
+            // New section
+            if (0 == strncmp(buf1,"[Servers]", sizeof("[Servers]")-1)) {
+                section=SECT_SERVERS;
+                if (!addresses_cleared) {
+                    // Clear addresses only once.
+                    _SNTPClrAddresses();
+                    addresses_cleared = true;
+                }
+            } else if (0 == strncmp(buf1,"[Global]", sizeof("[Global]")-1)) {
+                section=SECT_GLOBAL;
+            } else {
+                section=SECT_NONE;
+                fprintf(stderr, "File \"%s\", line %d - section \"%s\" is not understood.\r\n", filename, line, buf1);
+            }
+        } else {
+            // Section values
+            switch (section) {
+            case SECT_SERVERS:
+                if (_SNTPAddAddress(buf1)) {
+                    fprintf(stderr, "File \"%s\", line %d - cannot add server \"%s\" - exceeded allocated slots.\r\n", filename, line, buf1);
+                }
+                break;
+            case SECT_GLOBAL:
+                buf2 = strchr(buf1, '=');
+                if (buf2) {
+                    *buf2++ = '\0';     // Now buf1 has variable name, buf2 has value
+                    buf2 = str_cleanup(buf2);
+                    if (0 == strncmp(buf1, "Timezone", sizeof("Timezone")-1)) {
+                        gSntpTimezone = strtod(buf2, &buf2) * 3600;
+                    } else if (0 == strncmp(buf1, "UpdateDelay", sizeof("UpdateDelay")-1)) {
+                        gSntpUpdateDelay_s = strtoul(buf2, &buf2, 10);
+                    } else if (0 == strncmp(buf1, "RecvTimeout", sizeof("RecvTimeout")-1)) {
+                        gSntpRecvTimeout_s = strtoul(buf2, &buf2, 10);
+                    } else if (0 == strncmp(buf1, "RtcUtc", sizeof("RtcUtc")-1)) {
+                        gSntpRtcUtc = (bool)strtol(buf2, &buf2, 10);
+                    } else if (0 == strncmp(buf1, "DstZone", sizeof("DstZone")-1)) {
+                        // FIXME: It would be nice to allow human-readable string here.
+                        gSntpDstZone = (tDST_ZONE)strtol(buf2, &buf2, 10);
+                    } else {
+                        fprintf(stderr, "File \"%s\", line %d - unrecognized variable \"%s\" in section [Global]\r\n", filename, line, buf1);
+                    }
+                } else {
+                    fprintf(stderr, "File \"%s\", line %d - unrecognized statement in section [Global]: %s\r\n", filename, line, buf1);
+                }
+                break;
+            default:
+                fprintf(stderr, "File \"%s\", line %d - unrecognized statement / no section: %s\r\n", filename, line, buf1);
+            }
+        }
+    }
+    fclose(f);
+    lprintf("SNTP configuration read from file \"%s\", %d lines.\r\n", filename, line);
+    return 0;
+}
+// Start the SNTP client
+void SNTPClientInit(void) {
+#ifdef SNTP_DST_TESTS
+    // Test our DST algorithms
+    test_sntp_dst_calc(gSntpTimezone, gSntpDstZone);
+    test_sntp_dst_point(-2);
+    test_sntp_dst_point(-1);
+    test_sntp_dst_point(0);
+    test_sntp_dst_point(1);
+    test_sntp_dst_point(2);
+#endif
+    // SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds
+    if (gSntpUpdateDelay_s < 15) {
+        gSntpUpdateDelay_s = 15;
+    }
+    gSntpRunning = true;
+
+    // Just call this to start SNTP client:
+    sntp_init();
+//    // Enable RTC ISR
+//    gSntpTicker.attach(_sntp_isr, 1);
+// We do it from first NTP response
+}
+
+// Use instead of system time()
+// Returns local time
+time_t SNTPTime(void) {
+    time_t seconds = time(NULL);
+    if (gSntpRtcUtc) {
+        seconds += gSntpTimezone + gSntpDST;     // Convert to local time
+    }
+    return seconds;
+}
+
+// Use instead of system set_time()
+// seconds - local time
+void SNTPSetTime(time_t seconds) {
+    if (gSntpRtcUtc) {
+        seconds -= gSntpTimezone + gSntpDST;     // Convert from local time
+    }
+    set_time(seconds);
+}
+
+// Use instead of system time()
+// Returns UTC time
+time_t SNTPTimeUTC(void) {
+    time_t seconds = time(NULL);
+    if (!gSntpRtcUtc) {
+        seconds -= gSntpTimezone + gSntpDST;     // Convert from local time
+    }
+    return seconds;
+}
+// Use instead of system set_time()
+// seconds - UTC time
+void SNTPSetTimeUTC(time_t seconds) 
+{
+    if (!gSntpRtcUtc) {
+        seconds += gSntpTimezone + gSntpDST;     // Convert to local time
+    }
+    set_time(seconds);
+}
+//END
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 SNTPClient.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SNTPClient.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,35 @@
+#ifndef SNTPCLIENT_H
+#define SNTPCLIENT_H
+
+typedef enum {DST_START, DST_STOP} tDST_START;
+
+typedef struct DST_POINT {
+    time_t     t;               // Point in time when DST switch happens (in localtime)
+    signed int dst;             // Active DST value (for gSntpDST)
+    signed int dstshift;        // DST shift value (regardless if it is active or not)
+} tDstPoint;
+
+typedef tDstPoint (*pFncDstCalc)(int tz, int year, tDST_START start);
+typedef enum {
+#define _(z, fnc, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2) z,
+#include "DstZones.h"
+    DST_LAST    // LAST ITEM IN ENUM
+} tDST_ZONE;
+
+
+void SNTPSetDstZone(tDST_ZONE zone, bool adjust_clock=false);
+const char *SNTPDstZoneName(tDST_ZONE zone);
+void SNTPSetRecvTimeout(unsigned int val_s);
+void SNTPSetUpdateDelay(unsigned int val_s);
+void SNTPSetTimezone(float hours_from_utc, bool adjust_clock=false);
+void SNTPSetDST(float hours_from_utc, bool adjust_clock=false);
+int  SNTPSetAddresses(const char* server_addresses[], int count, void (*p_free)(void*));
+int  SNTPReadIniFile(const char* filename);
+void SNTPWriteIniFile(FILE * f);
+void   SNTPClientInit(void);
+time_t SNTPTime(void);
+void   SNTPSetTime(time_t seconds);
+time_t SNTPTimeUTC(void);
+void   SNTPSetTimeUTC(time_t seconds);
+#endif  // SNTPCLIENT_H
+//END
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 analog.c
--- a/analog.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/analog.c	Wed May 04 08:30:52 2011 +0000
@@ -1,51 +1,14 @@
 #include "mbed.h"
-#include "diags.h"
-
-/* This is the two 3.5mm Jack sockets */
-AnalogOut signal(p18);    /* Audio-out */
-AnalogIn ain(p19);        /* Audio-in  */
-
-void Analog_out(void);
-void Analog_in(void);
+#include "main.h"
+#include "useful.h"
 
-/******************************************/
-/*                                        */
-/*  Analog I/O tests                      */
-/*                                        */
-/*                                        */
-/*                                        */
-/*                                        */
-/******************************************/
-void test_analog(void)
+AnalogIn ain1(p15);
+AnalogIn ain2(p16);
+AnalogIn ain3(p17);
+AnalogIn ain4(p20);
+
+void show_a2d(void)
 {
-    char    buf[0x60];
-    sprintf(buf,"Testing the analog output\n\r");
-    serial_output_string(buf);
-    Analog_out();
-    sprintf(buf,"Testing the analog input\n\r");
-    serial_output_string(buf);
-    Analog_in();
-}
-
-
-
-void Analog_out(void) 
-{
-    int    cnt;
-    cnt=0;
-    
-    while(cnt!=100) {
-        for(float i=0.0; i<1.0; i+=0.1) {
-            signal = i;
-            wait(0.0001);
-        }
-        for(float i=1.0; i>0.0; i-=0.1) {
-            signal = i;
-            wait(0.0001);
-        }
-        cnt++;
-    }
-}
-void Analog_in(void)
-{
-}
+    lprintf("Analog Levels are %d, %d, %d, %d\n\r",
+        ain1.read_u16(), ain2.read_u16(), ain3.read_u16(), ain4.read_u16());
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 analog.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/analog.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+void show_a2d(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 breakup.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakup.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,114 @@
+#include "mbed.h"
+
+/*
+int breakup(char *, char *[], char);
+void breakup_sub(char *, char *,char,char);
+*/
+
+void breakup_sub(char *line,char *entery_point,char c,char d)
+{
+    char *point,*pt2;
+     
+    point = entery_point;
+    
+    point++;
+    pt2 = point;
+    point --;
+    while (*pt2!='\0') {
+        *point = *pt2;
+        point ++;
+        pt2 ++;
+    }
+    *point = *pt2;
+}
+
+int breakup(char *string,char *p[],char c)
+{
+    char *pt,*pt1;
+    char cc,ccc;
+    int cnt = 0;
+    int number = 0;
+    int flag = 0;
+    int last = 0;
+    int just = 0;
+    int length = strlen(string);
+
+    pt = string;
+    p[number] = pt;
+    number++;
+
+    while (cnt != length + 1) {
+        cc = *pt;
+        if (cc == '\0')
+            return(number);
+        /* this section of code will need sorting, so we don't have to use a space
+           char, we should move the ramainder of the buffer down one charactor
+        */
+        if (cc=='\\') {
+            pt1 = pt;    /* save the current pointer */
+            pt++;
+            ccc = *pt;
+            if (ccc=='"') {
+                pt--;
+                breakup_sub(string,pt,cc,ccc);
+                pt = pt1;
+            } else {
+                pt--;
+                pt = pt1;    /* restore the current pointer */
+            }
+        }
+        if (flag == 0) {
+            switch (cc) {
+                case '"' :
+                    flag = 1;
+                case '\n' :
+                case '\t' :
+                case ' ' :
+                    if (just==1) {
+                        /* move the current pointer along */
+                        pt = pt + 1;
+                        p[number] = pt;
+                        pt = pt - 1;
+                    } else {
+                        /* add the current point to the array  */
+                        just = 1;
+                        *pt = '\0';
+                        pt++;
+                        p[number] = pt;
+                        pt--;
+                    }
+                    if (flag == 1) {
+                        number ++;
+                        just = 0;
+                    }
+                    break;
+                default :
+                    if (just == 1) {
+                        just = 0;
+                        number ++;
+                    }
+                    break;
+            }
+            if (cc == c) {  /* test for the user defined char  */
+                just = 1;
+                *pt = '\0';
+                pt++;
+                p[number] = pt;
+                pt--;
+            }
+        } else {
+            if ((last == 0) & (cc =='"')) {     /* close of quoate */
+                flag = 0;
+                just = 1;
+                *pt = '\0';
+                pt++;
+                p[number] = pt;
+                pt--;
+            } else if ((flag == 1) & (last == 1) & (cc!='\\'))
+                last = 0;
+        }
+        pt++;
+        cnt++;
+    }
+    return(-1);
+}
diff -r 9edfcca7cd25 -r 6877bb99aa17 breakup.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/breakup.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+int breakup(char *string,char *p[],char c);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 can.c
--- a/can.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/can.c	Wed May 04 08:30:52 2011 +0000
@@ -1,8 +1,9 @@
 #include "mbed.h"
-#include "diags.h"
-#include "CAN.h"
-
-Ticker ticker;
+#include "useful.h"
+#include "led.h"
+#include "cmd.h"        /* used to get at the command code */
+#include "can_layer.h"
+#include "can.h"
 
 // CAN_RS pin at Philips PCA82C250 can bus controller.
 // activate transceiver by pulling this pin to GND.
@@ -15,42 +16,447 @@
 CAN can(p30, p29);
 
 int    can_cnt=0;
+extern char station_id;
+char    *can_str;
 
 /******************************************/
 /*                                        */
-/*    Can Bus Tests                       */
+/*    Can Bus Send a string to remote add */
+/*                                        */
+/******************************************/
+void can_send_string(char remote, char *str)
+{
+    unsigned char    buf[0x8];
+    int     len = strlen(str);
+    int     id;
+    int     cnt = 0;
+    int     sub;
+    int     pt = 0;
+     
+    if(len > 128){
+        lprintf("Max string lenght of 128 bytes, current string %d bytes long, not sending\n",len);
+        return;
+    }
+    
+    /* Set up the TX buffer for start packet */
+    can_clear_data(buf);
+    buf[0] = station_id;  /* who we are */
+    buf[1] = len;         /* number of bytes been sent, overall */
+    buf[2] = (len/8)+1;   /* guess at how many packets it should be */
+      
+    id = can_build_id(station_id,remote,CAN_SPRT);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet (%03x),",cancmd[CAN_SPRT],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+    /* About to send the data */
+    sub = 1;
+    pt = 0;
+    while(sub > 0){
+        can_clear_data(buf);
+        sub = can_build_data(len,pt,(unsigned char*)str,buf);
+        id = can_build_id(station_id,remote,CAN_PRT);
+        if(!can.write(CANMessage(id | cnt, (char *)buf, 8))) {
+            lprintf("Error sending %s packet PRT (%03x),",cancmd[CAN_PRT],id);
+            can_dump_buffer(buf);
+            lprintf("\n");
+      } else {
+            pt = sub;
+       }
+       wait(0.1);
+       cnt++;
+    }
+    
+    /* Set up the TX buffer for end packet */
+    can_clear_data(buf);
+    buf[0] = station_id;    /* Who we are */
+    buf[1] = len;           /* number of bytes sent */
+    buf[2] = cnt;           /* atual packet count */
+    id = can_build_id(station_id,remote,CAN_EPRT);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet EPRT (%03x),",cancmd[CAN_EPRT],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
+/*                                        */
+/*    Can Bus Send raw data to remote add */
+/*                                        */
+/******************************************/
+void can_send_raw(char remote, char *str)
+{
+    lprintf("In Can Send String with '%02x%02x%02x%02x%02x%02x%02x%02x' going to %d\n",
+    str[0],str[1],str[2],str[3],str[4],str[5],str[6],str[7], remote);
+}
+/******************************************/
+/*                                        */
+/*    Can Bus Send BUS Reset              */
+/*                                        */
+/******************************************/
+void can_send_sync(void)
+{
+    unsigned char    buf[0x8];
+    int     id;
+    
+    can_clear_data(buf);
+    id = can_build_id(0,0,CAN_SYNC);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet SYNC (%03x),",cancmd[CAN_SYNC],id);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
 /*                                        */
+/*    Can Bus Send Intger to remote add   */
+/*    mode = 0, Int, mode = 1, Time       */
 /*                                        */
+/******************************************/
+void can_send_int(int remote,int value,char mode)
+{
+    unsigned char    buf[0x8];
+    int     id;
+    
+    can_clear_data(buf);
+    if(mode==0)
+        id = can_build_id(station_id,remote,CAN_INT);
+    else if(mode == 1)
+        id = can_build_id(station_id,remote,CAN_TIME);
+    else {
+        lprintf("can_send_int: unknown mode with %d\n",mode);
+        return;
+    }
+    buf[0]=value & 0x000000ff;
+    buf[1]=(value >> 8)  & 0x000000ff;
+    buf[2]=(value >> 16) & 0x000000ff;
+    buf[3]=(value >> 24) & 0x000000ff;
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet INT (%03x),",cancmd[CAN_INT],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
 /*                                        */
+/*    Can Bus Send Who is Out there mes   */
+/*                                        */
+/******************************************/
+void can_send_who(void)
+{
+    unsigned char    buf[0x8];
+    int     id;
+    
+    can_clear_data(buf);
+    buf[0]=station_id;
+    id = can_build_id(station_id,0,CAN_WHOIS);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet WhoIs (%03x),",cancmd[CAN_WHOIS],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
+/*                                        */
+/*    Can Bus Send I Am Out there mes   */
+/*                                        */
+/******************************************/
+void can_send_iam(int from)
+{
+    unsigned char    buf[0x8];
+    int     id;
+    
+    can_clear_data(buf);
+    buf[0]=station_id;
+    buf[1]=from;
+    id = can_build_id(station_id,from,CAN_IAM);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet I'm Here (%03x),",cancmd[CAN_IAM],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
+/*                                        */
+/*    CAN Bus Send a ticker message       */
+/*                                        */
+/******************************************/
+void can_ticker_tx(int v)
+{
+    unsigned char    buf[0x8];
+    int     id;
+    
+    can_clear_data(buf);
+    buf[0]=station_id;
+    buf[4]=v;
+    id = can_build_id(station_id,0,CAN_IAM);
+    if(!can.write(CANMessage(id, (char *)buf, 8))) {
+        lprintf("Error sending %s packet CAN Ticker (%03x),",cancmd[CAN_IAM],id);
+        can_dump_buffer(buf);
+        lprintf("\n");
+        return;
+    }
+}
+/******************************************/
+/*                                        */
+/*    CAN Bus receiver, show the messages */
 /*                                        */
 /******************************************/
-void send() {
-    static char counter = 0;
-    if (can.write(CANMessage(0x200, &counter, 1))) {
-        printf("CanTx--> id: 0x200  dlc: 1  data: %x\n\r", counter);
-        counter++;
-    } else {
-        printf("CanTx--> id: 0x200  dlc: 1  data: %x ERROR\n\r", counter);
-        can.reset();
+void can_receive(void)
+{
+    CANMessage  msg;
+    int pt;
+    time_t seconds;
+        
+    if(can.read(msg)) {
+        switch(can_decode_id(msg.id,CAN_GET_CMD)){
+            case CAN_SYNC    :
+                lprintf("CAN SYNC MESSAGE< what do we do :-)\n");
+                break;
+            case CAN_RAW     :
+                break;
+            case CAN_SPRT    :
+                if(can_str != NULL){
+                    lprintf("trying to start a string packet, when the buffer is in use\n");
+                } else {
+                    can_str = can_buffer_create(msg.data[1]+2);
+                }                    
+                break;
+            case CAN_EPRT    :
+                find_cmd(can_str);
+                free(can_str);
+                can_str = NULL;
+                break;
+            case CAN_INT     :
+                lprintf("Recieved an int 0x%08x\n", msg.data[0] | msg.data[1]<<8 | msg.data[2]<<16 | msg.data[3]<<24);
+                break;
+            case CAN_TIME    :
+                seconds = msg.data[0] | msg.data[1]<<8 | msg.data[2]<<16 | msg.data[3]<<24;
+                set_time(seconds);
+                break;
+            case CAN_WHOIS   :
+                wait(station_id/10);
+                can_send_iam(msg.data[0]);
+                break;
+            case CAN_IAM     :
+                lprintf("Can_I_AM responce station id %02x, you where %02x\n",
+                    msg.data[0],msg.data[1]);
+                break;
+            case CAN_PRT     :
+                pt = can_decode_id(msg.id,CAN_GET_CNT);
+                can_str[(pt*8)+0] = msg.data[0];
+                can_str[(pt*8)+1] = msg.data[1];
+                can_str[(pt*8)+2] = msg.data[2];
+                can_str[(pt*8)+3] = msg.data[3];
+                can_str[(pt*8)+4] = msg.data[4];
+                can_str[(pt*8)+5] = msg.data[5];
+                can_str[(pt*8)+6] = msg.data[6];
+                can_str[(pt*8)+7] = msg.data[7];
+                break;
+            default     :
+                lprintf("CAN receive, unknown message %d\n",can_decode_id(msg.id,CAN_GET_CMD));
+        }
     }
-    if(can_cnt==0){
-        led_on(3);
-        can_cnt=1;
-    } else {
-        led_off(3);
-        can_cnt=0;
-    }
-    // toggle led1 after every transmission
 }
-void test_can(int loop)
+
+/******************************************/
+/*                                        */
+/*    Setup the CAN bus for use           */
+/*                                        */
+/******************************************/
+void can_init(void)
 {
     // 500kbit/s
-    can.frequency(500000);
+    // can.frequency(500000);
+    // 10kbits/s, for testing
+    can.frequency(10000);
     // activate external can transceiver
     can_Pca82c250SlopePin = 0;
-    can_cnt=loop;
-    // every 500ms
-    ticker.attach(&send, 0.5);
+    can_str = NULL;             /* Mark the input buffer as free */
+}
+/******************************************/
+/*                                        */
+/*    Setup the CAN message ID            */
+/*                                        */
+/******************************************/
+int can_build_id(char station, char dest, int cmd)
+{
+    int add, dst,c = 0,id = 0;
+    add = station << 8;
+    dst = dest << 4;
     
-    printf("CAN message ticker started\n\r");
-}
\ No newline at end of file
+    switch(cmd) {
+        case CAN_SYNC    :
+            c = 0;
+            add = 0;
+            dst = 0;
+            break;
+        case CAN_RAW     :
+            c = 1;
+            break;
+        case CAN_SPRT    :
+            c = 2;
+            break;
+        case CAN_EPRT    :
+            c = 3;
+            break;
+        case CAN_INT     :
+            c = 4;
+            break;
+        case CAN_TIME    :
+            c = 5;
+            break;
+        case CAN_S2      :
+            c = 6;
+            break;
+        case CAN_S3      :
+            c = 7;
+            break;
+        case CAN_S4      :
+            c = 8;
+            break;
+        case CAN_S5      :
+            c = 9;
+            break;
+        case CAN_S6      :
+            c = 0xa;
+            break;
+        case CAN_S7      :
+            c = 0xb;
+            break;
+        case CAN_S8      :
+            c = 0xc;
+            break;
+        case CAN_S9      :
+            c = 0xd;
+            break;
+        case CAN_WHOIS   :
+            c = 0xe;
+            break;
+        case CAN_IAM     :
+            c = 0xf;
+            break;
+        case CAN_PRT     :
+            c = 0x80;
+            break;
+        default     :
+            lprintf("CAN Message Selector switch, unknown message %d\n",cmd);
+            return(-1);
+    }
+    /* Build the message ID */
+    id = c | add | dst;
+    return(id);
+}
+/******************************************/
+/*                                        */
+/*   Get the data from the can message ID */
+/*                                        */
+/******************************************/
+int can_decode_id(int id, int what)
+{
+    switch(what){
+        case    CAN_SENDER_ID   :       /* Who sent the message */
+            return((id & 0xf00)>>8);
+        case    CAN_OUR_ID      :       /* who is it for */
+            return((id &0x070)>>4);
+        case    CAN_IS_PRT      :       /* is it a string packet */
+            return((id &0x080));
+        case    CAN_GET_CNT     :       /* Get the packet count value */
+            return((id & 0x00f));
+        case    CAN_GET_CMD     :       /* count and cmd live on the first 4 bits */
+            if(can_decode_id(id,CAN_IS_PRT))
+                return(CAN_PRT);
+            return((id & 0x00f));
+        default                 :
+            lprintf("Unknown CAN Id decode request %02x\n",what);
+            return(0);
+    }
+}
+/******************************************/
+/*                                        */
+/* Build a buffer for transmit, from a    */
+/* source buffer, of variable length      */
+/* this code is re-entrant, state held    */
+/* in the parent routine                  */
+/* Safe for raw, and string data          */
+/*                                        */
+/******************************************/
+int can_build_data(int len, int pt, unsigned char *data, unsigned char *buffer)
+{
+    int a = 0;
+    int px;
+        
+    px = pt;
+        
+    while(a!=MAX_CAN_BUF){
+        if(px<=len){
+            buffer[a] = data[px];
+            px++;
+        } else {
+            buffer[a] = 0x00;
+        }       
+        a++;
+    }
+    if(px <= len)
+        return(px);
+    else
+        return(0);
+}
+/******************************************/
+/*                                        */
+/* Clear the TX buffer to Zero's          */
+/* Safe for raw, and string data          */
+/*                                        */
+/******************************************/
+void can_clear_data(unsigned char *buffer)
+{
+    int a = 0;
+    while(a != MAX_CAN_BUF){
+        buffer[a] = 0x00;
+        a++;
+    }
+}
+/******************************************/
+/*                                        */
+/* Dump the TX buffer to the user         */
+/* Safe for raw, and string data          */
+/*                                        */
+/******************************************/
+void can_dump_buffer(unsigned char *buffer)
+{
+    int a = 0;
+    lprintf("   ");
+    while(a != MAX_CAN_BUF){
+        lprintf("%02x",buffer[a]);
+        if(buffer[a] > 0x20 & buffer[a] < 0x7f)
+            lprintf("(%c),",buffer[a]);
+        else
+            lprintf(",   ");
+        a++;
+    }
+}
+/******************************************/
+/*                                        */
+/* Create a new string buffer for can RX  */
+/*                                        */
+/******************************************/
+char *can_buffer_create(int size)
+{
+    char *str;
+    int   pt;
+    
+    str = (char *)malloc(sizeof(char)*size);
+    pt = 0;
+    while(pt!=size){
+        str[pt]='\0';
+        pt++;
+    }
+    return(str);
+}
+
diff -r 9edfcca7cd25 -r 6877bb99aa17 can.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/can.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,15 @@
+void can_send_string(char remote, char *str);
+void can_send_raw(char remote, char *str);
+void can_send_sync(void);
+void can_send_int(int remote,int value, char mode);
+void can_send_who(void);
+void can_send_iam(int from);
+void can_ticker_tx(int v);
+void can_receive(void);
+void can_init(void);
+int can_build_id(char station, char dest, int cmd);
+int can_decode_id(int id, int what);
+int can_build_data(int len,int pt, unsigned char *data, unsigned char *buffer);
+void can_clear_data(unsigned char *buffer);
+void can_dump_buffer(unsigned char *buffer);
+char *can_buffer_create(int size);
diff -r 9edfcca7cd25 -r 6877bb99aa17 can_layer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/can_layer.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,30 @@
+#define CAN_SYNC    0x00000
+#define CAN_RAW     0x00001
+#define CAN_SPRT    0x00002
+#define CAN_EPRT    0x00003
+#define CAN_INT     0x00004
+#define CAN_TIME    0x00005
+#define CAN_S2      0x00006
+#define CAN_S3      0x00007
+#define CAN_S4      0x00008
+#define CAN_S5      0x00009
+#define CAN_S6      0x0000a
+#define CAN_S7      0x0000b
+#define CAN_S8      0x0000c
+#define CAN_S9      0x0000d
+#define CAN_WHOIS   0x0000e
+#define CAN_IAM     0x0000f
+#define CAN_PRT     0x00010
+
+#define CAN_SENDER_ID   0x0001
+#define CAN_OUR_ID      0x0002
+#define CAN_IS_PRT      0x0004
+#define CAN_GET_CNT     0x0008
+#define CAN_GET_CMD     0x0010
+
+#define MAX_CAN_BUF 0x08
+
+char *cancmd[0x12] = {"SYNC","Raw Data","Start Print",\
+    "End Print","Interger","Spare 1","Spare 2","Spare 3",\
+    "Spare 4","Spare 5","Spare 6","Spare 7","Spare 8",\
+    "Spare 9", "Who is on line ?", "I am here","Print Packet"};
diff -r 9edfcca7cd25 -r 6877bb99aa17 cmd.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,633 @@
+#include "mbed.h"
+#include "useful.h"
+
+#include "led.h"        /* Basic On-Board LED driver functions */
+#include "digital.h"    /* Test the basic digital I/O of the MBED board */
+#include "analog.h"     /* code to do things to the a2d sub system */
+#include "i2c.h"        /* basic I2C Functions */
+#include "can.h"        /* Basic CAN bus test functions */
+#include "ticker.h"     /* Ticker look, flash a led et. al. */
+#include "serial.h"     /* Talk to the RS232 line */
+#include "network.h"    /* Test code for the TCP/IP network */
+#include "main.h"       /* routines in this file */
+#include "breakup.h"    /* breakup a string to its bits */
+#include "local_defines.h"
+#include "pca9685_reg.h"    /* Needed for the led driver init */
+#include "scripting.h"  /* Lets see if we can get a simple scripting system going */
+#include "SNTPClient.h" /* Time handling code */
+#include "SDFileSystem.h"   /* Look at the SD card */
+#include "sound.h"      /* Test code for the sound I/I system */
+
+#include "help_data.h"    /* a text file for the command help data */
+
+#include "cmd.h"
+
+
+SDFileSystem sd(p5, p6, p7, p27, "sd");
+
+LocalFileSystem local("local");
+
+FILE    *exec_fp;
+
+extern char station_id;
+extern char pwd[0x20];
+extern int set_baud_rate;
+extern int sys_state;
+extern int var[MAX_VAR];
+extern int jmp[MAX_JMP];
+
+
+/******************************************/
+/*                                        */
+/* Exec commands, for the Diags Code      */
+/*                                        */
+/******************************************/
+
+struct    cmd_callback {
+    char    *label;            /* command */
+    int         cmd;            /* switch value */
+    int         args;            /* Number of args for this command, 0 let sub-routine handle */
+    void    (*cmd_routine)(int,char **);    /* call */
+};
+struct cmd_callback cmd_cb[] ={
+    /* General commands for the command interpriter */
+    {   "exec",     0,      0,    exec_file},           /* Run a script file from the local file store */
+    {   "cat",      0,      2,    cat_file},            /* Cat a file on the file system to the current output device */
+    {   "cp",       0,      3,    cp_file},             /* copy file from to */
+    {   "dir",      0,      1,    dir_file},            /* Get a directory listing from the local file store */
+    {   "cd",       0,      0,    cd_file},             /* Change directory */
+    {   "pwd",      0,      0,    pwd_file},            /* show the user the current directory */
+    {   "wait",     0,      2,    wait_control},        /* wait for X tenths of a second */
+    {   "baud",     0,      2,    baud_rate},           /* Set the baudrate of the serial I/O */
+    {   "print",    0,      0,    print_string},        /* Print a string to current output device */
+    {   "help",     0,      1,    help_display},        /* Show the user some help data */
+    {   "state",    0,      0,    show_state},          /* Show the current setup state of the SBC */
+    {   "date",     0,      1,    date_cmd},            /* tell the user the data from the RTC */
+    {   "dateset",  0,      2,    date_set},            /*Set the RTC to a new time */
+    {   "station",  0,      2,    station_set},         /* Set the CAN bus station ID */
+    {   "netinit",  0,      1,    netinit},             /* DHCP the network */
+    {   "set",      0,      0,    set_var},             /* Set the variable to a value */
+    {   "sum",      0,      0,    sum_var},             /* Add some basic maths */
+    {   "point",    0,      0,    point_var},           /* Set out loop point */
+    {   "tst",      0,      0,    tst_var},             /* test the value of a var */
+    {   "clr",      0,      0,    clr_var},             /* Clear the var's to zero */
+    /* Commands for the Diags */
+    {   "list",     0,      1,    list},                /* List I2C Devices to user */
+    {   "i2cw",     0,      3,    i2cw},                /* Write a value to the I2C bus */
+    {   "i2cr",     0,      2,    i2cr},                /* Read a value from the I2C bus */
+    {   "led",      0,      0,    led_test},            /* Simple test of the MBED LED's */
+    {   "sseg",     0,      0,    sseg_test},           /* Simple test of the  Seven Seg displays*/
+    {   "rs232",    0,      2,    rs232_test_code},     /* Some test code for the RS232 interface */
+    {   "a2d",      0,      2,    a2d_test},            /* Simple test of the  A2D system */
+    {   "snd",      0,      1,    snd_test},            /* Sound test code */
+    {   "digital",  0,      2,    dig_test},            /* Simple test of the Digital I/O */
+    {   "lcd",      0,      2,    lcd_test},            /* Test the attached LCD display */
+    {   "lcdprt",   0,      0,    lcd_print},           /* print a string on the Batron LCD */
+    {   "lcdclr",   0,      0,    lcd_clear},           /* Clear the Batron screen */
+    {   "kbd",      0,      2,    kbd_test},            /* Test the attached keyboard */
+    {   "canrx",    0,      1,    canrx},               /* Make this box a CAN Reciever */
+    {   "cantx",    0,      0,    cantx},               /* Transmit a CAN message */
+    {   "cancmd",   0,      3,    can_cmd},             /* send a command out on the can bus */
+    {   "ticker",   0,      1,    ticker_test},         /* Test the ticker calls */
+    /* End of command table marker */
+    {   "test",      0,      2,    cmd_test},            /* We need somewhere to test commands first :-) */
+    {   "END",      -1,    -1,    error_handler}
+};
+
+
+/* Scan down tags, to find the match, else return -1 */
+int find_cmd(char *tag)
+{
+    int     cnt=0,c;
+    int  length=strlen(tag);
+    char *elements[0x10];
+
+    if(tag[0]=='#') /* See is we have a command or a comment */
+        return(0);
+
+    c = breakup(tag,elements,' ');
+    while(1){
+        if((strcmp(cmd_cb[cnt].label,"END"))==0){
+                  if(length>1)
+            cmd_cb[cnt].cmd_routine(c,elements);  /* this will call the error routine */
+            return(cmd_cb[cnt].cmd);
+        } else if((strcmp(cmd_cb[cnt].label,tag))==0){
+            if((cmd_cb[cnt].args==c) || (cmd_cb[cnt].args==0)){    /* if arg count set to zero, can be anything */
+                cmd_cb[cnt].cmd_routine(c,elements);        /* Call the function with args */
+                return(cnt);
+            } else {
+                lprintf("\n\rWrong number of args passed to %s\n\r",cmd_cb[cnt].label);
+                return(-1);
+            }
+        }
+        cnt++;
+    }
+}
+
+
+void error_handler(int c, char **a)
+{
+    int cnt=0;
+    lprintf("\n\rCommands available are ");
+    while(1){
+        if((strcmp(cmd_cb[cnt].label,"END"))==0){
+            lprintf("\n\r");
+            return;
+        } else
+            lprintf("%s, ",cmd_cb[cnt].label);
+        cnt++;
+    }
+}
+
+/******************************************/
+/*                                        */
+/* Command stubs are here                 */
+/*                                        */
+/******************************************/
+
+void exec_file(int c, char **a)
+{
+    /* File on a[1] */
+    
+    char     buf[0x60];
+    char     cmd[0x60];
+    int      cnt=0;
+    
+    sprintf(buf,"%s%s",pwd,a[1]);
+   
+    if((exec_fp = fopen(buf,"r"))==NULL){
+        lprintf("Unable to open %s\n\r",buf);
+        return;
+    }
+    sys_state = sys_state | EXEC_CALLED;
+    while(!feof(exec_fp)){
+        fgets(buf,sizeof(buf),exec_fp);
+        cnt++;
+        if(c==3)
+            lprintf("exec line (%d) is :%s\n",cnt,buf);
+        if(strlen(buf) > 2){
+            sprintf(cmd,"%s\n",buf);
+            find_cmd(cmd);
+        }
+        buf[0]='\0';
+        buf[1]='\0';
+    }
+    fclose(exec_fp);
+    sys_state = TO_USB;
+}
+void cat_file(int c, char **a)
+{
+    /* File on a[1] */
+    
+    FILE    *fp;
+    char     buf[0x60];
+    
+    sprintf(buf,"%s%s",pwd,a[1]);
+    
+    if((fp = fopen(buf,"r"))==NULL){
+        lprintf("Unable to open %s\n\r",buf);
+        return;
+    }
+    
+    while(!feof(fp)){
+        fgets(buf,sizeof(buf),fp);
+        if(strlen(buf) > 2){
+            lprintf(buf);
+        }
+        buf[0]='\0';
+        buf[1]='\0';
+    }
+    fclose(fp);
+}
+
+void cp_file(int c, char **a)
+{
+    /* from File on a[1] to file on a[2], full paths supplied */
+    
+    FILE    *fi,*fo;
+    char     buf[0x60];
+    
+    if((fi = fopen(a[1],"r"))==NULL){
+        lprintf("Unable to open %s to read\n",a[1]);
+        return;
+    }
+    if((fo = fopen(a[2],"w"))==NULL){
+        lprintf("Unable to open %s to write\n",a[2]);
+        fclose(fi);
+        return;
+    }
+    while(!feof(fi)){
+        fgets(buf,sizeof(buf),fi);
+        if(strlen(buf) > 2){
+            fprintf(fo,buf);
+        }
+        buf[0]='\0';
+        buf[1]='\0';
+    }
+    fclose(fi);
+    fclose(fo);
+}
+
+void dir_file(int c, char **a)
+{
+    DIR *d;
+    struct dirent *p;
+    char     buf[0x60];
+    
+    sprintf(buf,"%s%s",pwd,a[1]);
+    d = opendir(buf);
+    if(d != NULL) {
+        while((p = readdir(d)) != NULL) {
+            lprintf("- %s\n\r", p->d_name);
+        }
+    } else {
+        error("Could not open directory!");
+    }
+    closedir(d);
+}
+void cd_file(int c, char **a)
+{
+    int x;
+    char y;
+    
+    y = a[1][strlen(a[1])];
+    
+    if(a[1][0]=='/'){
+        if(y!='/')
+            sprintf(pwd,"%s/",a[1]);
+        else
+            sprintf(pwd,a[1]);
+    } else
+        lprintf("File Path like /local/\nCurrently you are in %s\n",pwd);
+    x = 0;
+    if((strcmp(pwd,"/sd/"))==0)
+        x = 1;
+    else  if((strcmp(pwd,"/local/"))==0)
+        x = 1;
+    if(!x){
+        lprintf("Only directories are /local/ or /sd/ (If the SD card is in slot, resetting to /local/\n");
+        sprintf(pwd,"/local/");
+    }
+}
+void pwd_file(int c, char **a)
+{
+    lprintf("%s\n",pwd);
+}
+void wait_control(int c, char **a)
+{
+    wait(htoi(a[1])/10);
+}
+
+void print_string(int c, char **a)
+{
+    int cnt = 1;
+    int len;
+    while(cnt <= c){
+        if(a[cnt][0]=='v' || a[cnt][0]=='V'){
+            len = strlen(a[cnt]);
+            if(len == 2){
+                lprintf(" %04x",htoi(a[cnt]));
+            } else {
+                lprintf("%s",a[cnt]);
+            }
+        } else
+            lprintf("%s",a[cnt]);
+        cnt++;
+    }
+    lprintf("\n");
+}
+
+void help_display(int c, char **a)
+{
+    lprintf("%s",HELP_STRING);
+    lprintf("%s",HELP_STRING2);
+    lprintf("%s",HELP_STRING3);
+    lprintf("%s",HELP_SCRIPT1);
+}
+
+/******************************************/
+/*                                        */
+/* Diag Command stubs are here            */
+/*                                        */
+/******************************************/
+
+void list(int c, char **a)
+{
+    i2c_probe();
+}
+
+void i2cw(int c, char **a)
+{
+    pio_write(htoi(a[1]),htoi(a[2]));
+}
+
+void i2cr(int c, char **a)
+{
+    pio_read(htoi(a[1]));
+}
+
+void led_test(int c, char **a)
+{
+    if(c==2){
+        test_leds(htoi(a[1]));
+    } else  if(c==3){
+        if((strcmp(a[1],"on"))==0){
+            if((strcmp(a[2],"all"))==0)
+                led_on(htoi(0));
+            else
+                led_on(htoi(a[2]));
+        } else if((strcmp(a[1],"off"))==0){
+             if((strcmp(a[2],"all"))==0)
+                led_off(htoi(0));
+            else
+                led_off(htoi(a[2]));
+        } else
+            lprintf("LED Control Error: led on/off <led>\n");
+            
+    } else {
+        lprintf("led <num>           - simple led test, go round loop num times\n");
+        lprintf("led <on/off> <num>  - Turn <led num> <on/off>\n");
+    }
+}
+
+void sseg_test(int c, char **a)
+{
+    if(c==2){
+        lprintf("Testing the Seven Segment Display, will go roung the test loop %d times\n",htoi(a[1]));
+        test_seven_seg(htoi(a[1]));
+    } else if (c==3 & (strcmp(a[1],"val"))==0){
+        sseg_four_digits(htoi(a[2]));
+    } else {
+        lprintf("sseg <num>     - basic test of sseg, loop num times\n");
+        lprintf("sseg val <num> - display number on the sseg display\n");
+    }
+}
+
+void a2d_test(int c, char **a)
+{
+    show_a2d();
+}
+
+void snd_test(int c, char **a)
+{
+    sound();
+}
+
+void dig_test(int c, char **a)
+{
+    lprintf("Testing the Digital I/O, will go roung the test loop %d times\n",htoi(a[1]));
+    digital_test(htoi(a[1]));
+}
+
+/******************************************/
+/*                                        */
+/* Test routines for the Keyboard and LCD */
+/* at the mo we need to know what type of */
+/* keyboard and LCD we have, carried on   */
+/* the supplied argument                  */
+/*                                        */
+/******************************************/
+void lcd_test(int c, char **a)
+{
+    switch(htoi(a[1])){
+        case    1      :    /* Robot Electronics I2C LCD interface */
+            init_lcd();     /* Setup the LCD */
+            clear_lcd();    /* Clear the screen */
+            write_lcd("Hello");    /* Send it some text */
+            break; 
+        case    2      :    /* Batron I2C LCD interface */
+            batron_lcd_init();
+            batron("Hello World");
+            break;
+        default        :
+            lprintf("Unknown LCD type %d\n",htoi(a[1]));
+    }
+}
+
+void lcd_print(int c, char **a)
+{
+    batron_lcd_init();
+    batron(a[1]);
+}
+void lcd_clear(int c, char **a)
+{
+    batron_clear();
+}
+
+void kbd_test(int c, char **a)
+{
+    char    r;
+    switch(htoi(a[1])){
+        case    3      :    /* Robot Electronics I2C LCD interface */
+            lprintf("Will take 4 key presses of the Robot Electronics key pad\n");
+            lprintf("Displaying the results to the user\n");
+            r = blocking_read_keyboard();
+            lprintf("Key 1 %d, or 0x%x, or %c\n",r,r,r);
+            r = blocking_read_keyboard();
+            lprintf("Key 2 %d, or 0x%x, or %c\n",r,r,r);
+            r = blocking_read_keyboard();
+            lprintf("Key 3 %d, or 0x%x, or %c\n",r,r,r);
+            r = blocking_read_keyboard();
+            lprintf("Key 4 %d, or 0x%x, or %c\n",r,r,r);
+            break;
+        case    4      :    /* Work around, with PCF8574 when with Batron I2C LCD */
+            lprintf("Will take 4 key presses of thePCF8574s key pad\n");
+            lprintf("Displaying the results to the user\n");
+            r = pcf8574_kbd(1);
+            lprintf("Key 1 %d, or 0x%x, or %c\n",r,r,r);
+            r = pcf8574_kbd(1);
+            lprintf("Key 2 %d, or 0x%x, or %c\n",r,r,r);
+            r = pcf8574_kbd(1);
+            lprintf("Key 3 %d, or 0x%x, or %c\n",r,r,r);
+            r = pcf8574_kbd(1);
+            lprintf("Key 4 %d, or 0x%x, or %c\n",r,r,r);
+            break;
+        default        :
+            lprintf("Unknown KBD type %d\n",htoi(a[1]));
+    }
+    
+}
+/******************************************/
+/*                                        */
+/* CAN Bus tests, run from here           */
+/*                                        */
+/******************************************/
+void canrx(int c, char **a)
+{
+    lprintf("Locking into the CAN message feed, till RESET is pressed\n");
+    while(1){
+        can_receive();
+    }
+}
+void cantx(int c, char **a)
+{
+    if(c== 2 | c==4){
+        if((strcmp(a[1],"prt"))==0){
+            can_send_string(htoi(a[2]),a[3]);
+        } else if((strcmp(a[1],"raw"))==0){
+            can_send_raw(htoi(a[2]),a[3]);
+        } else if((strcmp(a[1],"sync"))==0){
+            can_send_sync();
+        } else if((strcmp(a[1],"int"))==0){
+            can_send_int(htoi(a[2]),htoi(a[3]),0);
+        } else if((strcmp(a[1],"time"))==0){
+            can_send_int(htoi(a[2]),htoi(a[3]),1);
+        } else if((strcmp(a[1],"who"))==0){
+            can_send_who();
+        } else
+            lprintf("cantx commnads are, sync, int, raw, who, prt\n");
+    } else {
+        lprintf("cantx <prt/raw> <remote station> <message>\n");
+        lprintf("cantx int <remote station> <value>\n");
+        lprintf("cantx time <remote station> <value>\n");
+        lprintf("cantx sync\n");
+        lprintf("cantx who\n");
+    }
+}
+void can_cmd(int c, char **a)
+{
+    can_send_string(htoi(a[1]),a[2]);
+}
+/******************************************/
+/*                                        */
+/* TCP/IP Networking test tool box        */
+/*                                        */
+/******************************************/
+void netinit(int c, char **a)
+{
+     network_init();
+     lprintf("Starting SNTP\n");
+     SNTPReadIniFile("/local/sntp.ini");
+//     SNTPWriteIniFile(stdout);
+     SNTPClientInit();
+}
+
+/******************************************/
+/*                                        */
+/* Test the Ticker system                 */
+/*                                        */
+/******************************************/
+void ticker_test(int c, char **a)
+{
+     setup_ticker();
+}
+
+/******************************************/
+/*                                        */
+/* Set the station ID for the CAN bus     */
+/*                                        */
+/******************************************/
+void station_set(int c, char **a)
+{
+     station_id = htoi(a[1]);
+}
+
+/******************************************/
+/*                                        */
+/* Display the system time to the user    */
+/*                                        */
+/******************************************/
+void date_cmd(int c, char **a)
+{
+     time_t seconds = time(NULL);
+     lprintf("mbed RTC time(%d): %s\n",seconds,ctime(&seconds));
+}
+void date_set(int c, char **a)
+{
+    time_t seconds;
+    seconds = atoi(a[1]);     /* http://www.onlineconversion.com/unix_time.htm  */
+    set_time(seconds);
+}
+/******************************************/
+/*                                        */
+/* Display the system state to the user   */
+/*                                        */
+/******************************************/
+#define STATE_VAR   0x0001
+#define STATE_I2C   0x0002
+#define STATE_BRD   0x0004
+#define STATE_JMP   0x0008
+
+void show_state(int c, char **a)
+{
+     int    cnt = 0;
+     int    show=0;
+     
+     if(c!=1){
+        if((strcmp(a[1],"var"))==0)
+            show = STATE_VAR;
+        else if((strcmp(a[1],"i2c"))==0)
+            show = STATE_I2C;
+        else if((strcmp(a[1],"board"))==0)
+            show = STATE_BRD;
+        else if((strcmp(a[1],"jmp"))==0)
+            show = STATE_JMP;
+        else
+            lprintf("Unknown state %s, should be var, jmp, i2c, board\n",a[1]);
+    } else {
+        show = STATE_VAR | STATE_I2C | STATE_BRD | STATE_JMP;
+    }
+            
+    if(show & STATE_BRD){
+        time_t seconds = time(NULL);
+        lprintf("mbed RTC time(%d): %s",seconds,ctime(&seconds));
+        lprintf("Baudrate Setting is %d\n",set_baud_rate);
+        lprintf("Station CAN ID is %d\n",station_id);
+        lprintf("Sysem State is %08x\nVariables, ",sys_state);
+     }
+     if(show & STATE_VAR){
+        lprintf("System Variables\n");
+        while(cnt != MAX_VAR){
+            lprintf("%04x, ",var[cnt]);
+            cnt++;
+        }
+        lprintf("\n");
+     }
+     if(show & STATE_JMP){
+        lprintf("System Jump Table\n");
+        while(cnt != MAX_JMP){
+            lprintf("%04x, ",jmp[cnt]);
+            cnt++;
+        }
+        lprintf("\n");
+     }
+     if(show & STATE_I2C){
+        lprintf("Attached I2C devices \n");
+        i2c_probe();
+     }
+}
+
+/******************************************/
+/*                                        */
+/*  SD card file system test              */
+/*                                        */
+/******************************************/
+void sdcard_test(int c, char **a)
+{
+    sys_state = (sys_state & ~MEMSTICK) | SDCARD;
+    lprintf("Set the file system to the SD Card\n");
+}   
+/******************************************/
+/*                                        */
+/*  Mem Stick file system test            */
+/*                                        */
+/******************************************/
+void memstick_test(int c, char **a)
+{
+    sys_state = (sys_state & ~SDCARD) | MEMSTICK;
+    lprintf("Set the file system to the Memory Stick\n");
+}   
+/******************************************/
+/*                                        */
+/* General Test command for the source    */
+/*                                        */
+/******************************************/
+void cmd_test(int c, char **a)
+{
+    int b=0;
+    while(b!=htoi(a[1])){
+        sseg_four_digits(b);
+        wait(0.1);
+        b++;
+    }
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 cmd.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,36 @@
+int find_cmd(char *tag);
+void error_handler(int c, char **a);
+
+void exec_file(int c, char **a);
+void cat_file(int c, char **a);
+void cp_file(int c, char **a);
+void dir_file(int c, char **a);
+void cd_file(int c, char **a);
+void pwd_file(int c, char **a);
+void wait_control(int c, char **a);
+void print_string(int c, char **a);
+void help_display(int c, char **a);
+
+void list(int c, char **a);
+void i2cw(int c, char **a);
+void i2cr(int c, char **a);
+void led_test(int c, char **a);
+void sseg_test(int c, char **a);
+void a2d_test(int c, char **a);
+void snd_test(int c, char **a);
+void dig_test(int c, char **a);
+void lcd_test(int c, char **a);
+void lcd_print(int c, char **a);
+void lcd_clear(int c, char **a);
+void kbd_test(int c, char **a);
+void canrx(int c, char **a);
+void cantx(int c, char **a);
+void can_cmd(int c, char **a);
+void netinit(int c, char **a);
+void ticker_test(int c, char **a);
+void station_set(int c, char **a);
+void date_cmd(int c, char **a);
+void date_set(int c, char **a);
+void show_state(int c, char **a);
+
+void cmd_test(int c, char **a);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 diags.h
--- a/diags.h	Tue Jan 12 16:49:56 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/* Basic LED tests for the board */
-void test_leds(char t);
-void led_on(char led);
-void led_off(char led);
-
-/* RS232 tests for the board */
-void test_rs232(char t);
-void serial_output_string(char *buf);
-
-/* CAN interface tests */
-void test_can(int loop);
-
-/* Basic tests for the LCD interface */
-void test_lcd(char t);
-char init_lcd(void);
-char clear_lcd(void);
-char set_lcd(char line, char col);
-char write_lcd(char *str);
-void test_kbd(void);
-char read_keyboard(void);
-
-/* Test for the I2C PIO Chip */
-void test_pio(char t);
-/* Test for the digital I/O on the board */
-void test_real_pio(char t);
-void i2c_probe(void);
-
-/* Seven Seg test code */
-void test_seven_seg(char loop);
-void print_seven_seg(unsigned char a,unsigned char b,unsigned char c,unsigned char d);
-void sseg_ticker_test(int t);
-
-/* Analog test set */
-void test_analog(void);
-
-/* Ticker elements */
-void setup_ticker(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 digital.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/digital.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,44 @@
+#include "mbed.h"
+#include "main.h"
+#include "useful.h"
+
+BusOut myleds(p21,p22,p23,p24,p8,p25,p26);
+
+BusOut sio_io(p27,p5,p6,p7);
+
+void digital_test(char l)
+{
+    char    a,b;
+    
+    a = 0;
+    b = 0;
+    while(b != l){
+        while(a!=0x80){
+            myleds = a;
+            a++;
+            wait(0.01);
+        }
+        b++;
+    }
+        
+}
+
+void digital_sio_test(void)
+{
+    char a;
+    char b;
+    
+    lprintf("In SIO Test Code\n\r");
+    
+    a=0;
+    while(a!=4){
+        b = 0;
+        while(b!=16){
+            sio_io = b;
+            myleds = b;
+            b++;
+            wait(0.1);
+        }
+        a++;
+    }
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 digital.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/digital.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,2 @@
+void digital_test(char l);
+void digital_sio_test(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 help_data.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/help_data.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,42 @@
+#define HELP_STRING \
+"Commands for the Diags are\n" \
+"help             - This text\n" \
+"exec <file>      - Exec a command file from the local file system\n" \
+"cat <file>       - Display a file on the current output device \n" \
+"dir              - show files on the local file system\n" \
+"wait <1/10 sec>  - Wait for X tenths of a second\n" \
+"baud <speed>     - Set the serial lines baud rate to X\n" 
+
+#define HELP_STRING2 \
+"print <string>   - Print a string to the console\n\n" \
+"list             - Scan down the I2C bus for devices\n" \
+"i2cw <add> <dat> - Write a value to the I2C bus\n" \
+"i2cr <add>       - Read a value from the I2C bus\n" \
+"led <loop>       - Test the MBED leds, cyle fron X times\n" \
+"sseg <loop>      - Test the Seven Segment display X times\n" \
+"digital <loop>   - Test the digital I/O lines as outputs X times\n" \
+"rs232 <string>   - Send a string out to the serial line\n"
+
+#define HELP_STRING3 \
+"kbd <type>       - Keypad data entery test, type is either 3 or 4 (3*4) or (4*4)\n" \
+"lcd <type>       - LCD test type is 1 or 2, 1 for Robot electronics, 2 for Batron\n" \
+"canrx            - Listen to the can bus only, display received messages\n" \
+"cantx <message>  - Send a message down the can bus to the receiving station\n" \
+"netinit          - Start the tcp/ip network, by DHCP\n" \
+"ticker           - Start the ticker test on LED 4\n" \
+"station <char>   - Station ID for each station\n" \
+"date             - Current RTC date\n" \
+"dateset <secs>   - Set the RTC from the command line in seconds \n" \
+"                   http://www.onlineconversion.com/unix_time.htm\n"
+
+#define HELP_SCRIPT1 \
+"MBED scripting basics\n" \
+"Variables are v0 to V9, jump points are J0 to J9\n" \
+"Following are the actions that can be handled by the scripting language\n\n" \
+"set <var> <value>             - Set a variable to a value\n" \
+"sum <var> <action> <var *>      - sum tow variables together\n" \
+"tst <var> <test> <var *> <jump> - test a variable to see if it passes the test\n" \
+"                                  Jump to the jump lable if needed\n" \
+"point <jump>                    - Set a jump point\n" \
+"\n\n" \
+"Maths actions are +, -, /, * with test actions of <, >, !, =\n"
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 i2c.c
--- a/i2c.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/i2c.c	Wed May 04 08:30:52 2011 +0000
@@ -1,11 +1,21 @@
 #include "mbed.h"
-#include "diags.h"
+
+#include "main.h"
+#include "i2c.h"
+#include "useful.h"
+#include "pca9685_reg.h"    /* Light Driver Chip */
 
 I2C i2c(p9, p10); // sda, scl
 
+#define PIO          0x40
+#define RELAYS       0x40
 #define LCD          0xC6
+#define BAT          0x76    /* Batron LCD device */
+#define BATKBD       0x42    /* batron Keyboard */
 #define SEVEN_SEG    0x70
-#define PIO          0x40
+#define ASCII_OFFSET 0x80
+
+
 /******************************************/
 /*                                        */
 /*   Probe the I2C bus, and show the      */
@@ -16,38 +26,26 @@
 /******************************************/
 void i2c_probe(void) 
 {
-    char buf[0x60];
-    sprintf(buf,"Searching for I2C devices...\n\r");
-    serial_output_string(buf);
-
+    lprintf("Searching for I2C devices...\n\r");
+   
     int count = 0;
     for (int address=4; address<256; address+=2) {
         if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
-            sprintf(buf," - I2C device found at address 0x%02X\n\r", address);
-            serial_output_string(buf);
+            lprintf(" - I2C device found at address 0x%02X\n\r", address);
             count++;
         }
     }
-    sprintf(buf,"%d devices found\n\r", count);
-    serial_output_string(buf);
+    lprintf("%d devices found\n\r", count);
 }
 
 /******************************************/
 /*                                        */
-/*  Should display some basic data        */
-/*  on the LCD interface                  */
+/*  Should drive the I2C based LCD        */
+/*  Display If attached                   */
 /*                                        */
 /*                                        */
 /*                                        */
 /******************************************/
-/* LCD tests */
-void test_lcd(char t)
-{
-    init_lcd();
-    clear_lcd();
-    write_lcd("this is a test");
-}
-
 char init_lcd(void)
 {
     char    buf[4];
@@ -75,25 +73,22 @@
 {
     char    buf[0x60];
     if(strlen(str)>50){
-        printf("Line length to long\n\r");
+        lprintf("Line length to long\n\r");
         return(0);
     }
     sprintf(buf,"%c%s",'\0',str);
     buf[0]=0;
     return(i2c.write(LCD,buf,strlen(str)+1));
 }
+
 /******************************************/
 /*                                        */
-/*   Shoudl get some keys from the user   */
-/*   pressing keys on the keypad          */
-/*   and display this data on the LCD     */
-/*                                        */
+/*   Read key presses from the keyboard   */
+/*   Attached to the LCD interface        */
+/*   It returns 0 if no key is pressed    */
+/*   or the ascii value of the key press  */
 /*                                        */
 /******************************************/
-/* Keyboard test code here */
-void test_kbd(void)
-{
-}
 char read_keyboard(void)
 {
     char    buf[10];
@@ -134,16 +129,218 @@
 }
 /******************************************/
 /*                                        */
-/*  Should read and write data on the     */
-/*  PCF8574 I/O expander, maybe with      */
-/*  a loop back connector in time         */
+/*   Blocking key press, will wait for    */
+/*   the user to press a key              */
+/*                                        */
+/******************************************/
+char blocking_read_keyboard(void)
+{
+    char    c = 0;
+    while((c=read_keyboard())==0)
+   while((read_keyboard())==c);
+    wait(0.5);
+    return(c);
+}
+
+/******************************************/
+/*                                        */
+/* 1 - 8, Relays On,                      */
 /*                                        */
+/******************************************/
+void relay_operate(char r)
+{
+    char buf[0x60];
+        
+    switch(r){
+        case    0    :    /* Turn off the relays */
+            buf[0]=0x00; 
+            break;
+        case    1    :
+            buf[0]=0x01; 
+            break;
+        case    2    :
+            buf[0]=0x02; 
+            break;
+        case    3    :
+            buf[0]=0x04; 
+            break;
+        case    4    :
+            buf[0]=0x08; 
+            break;
+        case    5    :
+            buf[0]=0x10; 
+            break;
+        case    6    :
+            buf[0]=0x20; 
+            break;
+        case    7    :
+            buf[0]=0x40; 
+            break;
+        case    8    :
+            buf[0]=0x80; 
+            break;
+        default      :
+            lprintf("Unknown Relay %d\n\r",r);
+            return;
+    }
+    i2c.write(RELAYS,buf,1);
+}
+
+/******************************************/
+/*                                        */
+/* Read and Write the PIO latch           */
+/*                                        */
+/******************************************/
+void pio_write(unsigned char r, unsigned char d)
+{
+    unsigned char buf[0x60];
+    
+    buf[0]=d;
+    i2c.write(r,(char *)buf,1);
+}
+void pio_read(unsigned char d)
+{
+   unsigned char r;
+   unsigned char buf[0x60];
+    
+   i2c.read(d,(char *)buf,1);
+   r = buf[0];
+   
+   lprintf("Returned value from the PIO was 0x%02x\n\r",r);
+}
+
+/******************************************/
+/*                                        */
+/* Philips PCA9685 I2C Driver, 16 channel */
+/* Lighting controler chip, we have 4     */
+/* running in this system, so we need to  */
+/* think how the channels map ??          */
+/*                                        */
+/******************************************/
+
+/******************************************/
+/*                                        */
+/* Init code for the PCA9685              */
 /*                                        */
 /******************************************/
-/* PCF8574 tests */
-void test_pio(char t)
+
+void init_pca9685(unsigned char address)
+{
+    unsigned char buf[30];
+    
+    lprintf("Setting up channel %d\n\r",address);
+    
+    buf[0] = PCA9685_MODE1;
+    buf[1] = PCA9685_AI;
+    buf[2] = PCA9685_OUTDRV;
+    i2c.write(address,(char *) buf, 3);
+}
+
+/******************************************/
+/*                                        */
+/* Send data to a given channle of a      */
+/* given PCA9685 chip                     */
+/*                                        */
+/******************************************/
+
+void pca9685_led(unsigned char addr, int led, unsigned char *values) 
+{
+    unsigned char buf[5];
+   
+    if (led == PCA9685_ALL_LEDS) {
+        buf[0] = PCA9685_ALL_LED_ON_L;
+    } else {
+        buf[0] = PCA9685_BASE(led);
+    }
+
+    buf[1] = values[0];
+    buf[2] = values[1];
+    buf[3] = values[2];
+    buf[4] = values[3];
+    i2c.write(addr, (char *)buf, 5);
+}
+
+/******************************************/
+/*                                        */
+/* Calculate the register values for a    */
+/* givern brightness percentage           */
+/*                                        */
+/******************************************/
+
+void pca9685_brightness(int percent, unsigned char *values) 
 {
+    unsigned int on, off;
+
+    if (percent == 0) {
+    values[PCA9685_LED_ON_H] = 0;
+    values[PCA9685_LED_OFF_H] = PCA9685_LED_OFF;
+    return;
+    }
+    if (percent == 100) {
+    values[PCA9685_LED_ON_H] = PCA9685_LED_ON;
+    values[PCA9685_LED_OFF_H] = 0;
+    return;
+    }
+    on = 0;
+    off = (4096 * percent) / 100;
+    values[PCA9685_LED_ON_L] = on & 0xff;
+    values[PCA9685_LED_ON_H] = (on >> 8) & 0xf;
+    values[PCA9685_LED_OFF_L] = off & 0xff;
+    values[PCA9685_LED_OFF_H] = (off >> 8) & 0xf;
 }
+
+/******************************************/
+/*                                        */
+/* Set a given channel to a given level   */
+/*                                        */
+/******************************************/
+void channel_light(unsigned char ch, unsigned char lev)
+{
+    char            chip,led;     /* Chip Number, channel number */
+    unsigned char   v[4];         /* register data for givern level */
+    
+    led = ch%16;
+    v[0]=0;
+    v[1]=0;
+    v[2]=0;
+    v[3]=0;
+    
+    if(lev > 100){
+        lprintf("Level percentage range 0 - 100 (Trying for %d)\n\r",lev);
+        return;
+    }
+    
+    switch(ch/16){
+        case    0    :
+            chip=LEDDRV1;
+            break;
+        case    1    :
+            chip=LEDDRV2;
+            break;
+        case    2    :
+            chip=LEDDRV3;
+            break;
+        case    3    :
+            chip=LEDDRV4;
+            break;
+        case    4    :
+            chip=LEDDRV5;
+            break;
+        case    5    :
+            chip=LEDDRV6;
+            break;
+        default      :
+            lprintf("Error unknown chip %d\n\r",ch/16);
+            return;
+    }
+    
+    lprintf("Setting channel %d to brightness leven %d chip = %d(%d),%d\n\r",
+        ch,lev,chip,ch/16,led);
+    pca9685_brightness(lev,v);    /* Calculate the brightness level */
+    lprintf("Brightness level is %02x,%02x,%02x,%02x\n\r",v[0],v[1],v[2],v[3]);
+    pca9685_led(chip,led,v);      /* Send to chip */
+}
+
 /******************************************/
 /*                                        */
 /*  Send some data to the seven segment   */
@@ -181,6 +378,30 @@
     }
 }
 
+void sseg_four_digits(int a)
+{
+    int index = 4;
+    int val = a;
+    char pt[5];
+    
+    pt[1] = 0;
+    pt[2] = 0;
+    pt[3] = 0;
+    pt[4] = 0;
+    
+    do {
+        register unsigned short temp;
+
+        temp = val / 10;
+        pt[index] = (char)(val - (temp * 10));
+        val = temp;
+        index -= 1;
+
+    } while ( val > 0 );
+    
+    print_seven_seg(sseg_map[pt[1]],sseg_map[pt[2]],sseg_map[pt[3]],sseg_map[pt[4]]);
+}                
+
 void print_seven_seg(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
 {
     unsigned char buf[10];
@@ -189,22 +410,217 @@
     buf[1]=0x27;
     buf[2]=a;
     buf[3]=b;
-    buf[4]=d; /* Digits 3 and 4 are the wrong way round */
-    buf[5]=c;
+    buf[4]=c; 
+    buf[5]=d;
     i2c.write(SEVEN_SEG,(char *)buf,7);
 }
 
-void sseg_ticker_test(int t)
+/******************************************/
+/*                                        */
+/*  Test code to drive the Batron LCD     */
+/*                                        */
+/******************************************/
+
+void batron_lcd_init(void)
+{
+    char buf[0x60];
+    
+    lprintf("Init Batron LCD at %02x\n\r",BAT);
+    
+    buf[0]=0x00;
+    buf[1]=0x34;
+    buf[2]=0x0c;
+    buf[3]=0x06;
+    buf[4]=0x35;
+    buf[5]=0x04;
+    buf[6]=0x10;
+    buf[7]=0x42;
+    buf[8]=0x9f;
+    buf[9]=0x34;
+    buf[10]=0x80;
+    buf[11]=0x02;
+    
+    i2c.write(BAT,(char *)buf,12);
+    batron_clear();
+}
+void batron(char *str)
+{
+    lprintf("Testing Batron LCD, Clearing Display\n\r");
+    
+    batron_clear();
+    
+    lprintf("Sending %s\n",str);
+     
+    batron_lcd_write(str);
+}
+
+char batron_lcd_write(char *b)
 {
-    char    a,b,c,d;
-    int     z;
+    char buf[0x60];
+    int a;
+    
+    buf[0]=0x00;
+    buf[1]=0x80;
+    i2c.write(BAT,(char *)buf,2);
+    
+    a=0;
+    buf[0]=0x40;
+    
+    while(a!=strlen(b)){
+        buf[a+1]=ascii_to_lcd(b[a]);
+        a++;
+    }
+    buf[a+1]=0x00;
+    
+    i2c.write(BAT,buf,strlen(b)+1);
+    
+    buf[0]=0x80;
+    buf[1]=0x02;
+    i2c.write(BAT,(char *)buf,2);
+    return(0);
+}
+
+char ascii_to_lcd(char ch)
+{
+    char c;
+
+    c = 0xA0;                         // default: white space
+
+    if((ch>=' ') & (ch<='?'))
+        c = ASCII_OFFSET + ch;
+    if((ch>='A') & (ch<='Z'))    
+        c = ASCII_OFFSET + ch;
+    if((ch>='a') & (ch<='z'))
+        c = ASCII_OFFSET + ch;
+    return c;
+}    
+void batron_clear(void)
+{
+    batron_clear_line(0);                // clear 1st line
+    batron_clear_line(1);                // clear 2nd line
+
+    return;
+}   
+char batron_clear_line(char row)
+{
+    char i=0, state;
+    do
+    //state = LCD_put_xy(LCD_ascii_to_lcd(0x20), row, i);
+        state = batron_put_xy(0xA0, row, i);
+    while((i++<16));
+    return state;
+}
+char batron_put_xy(char ddram_byte, char row, char column)
+{
+    char buf[0x10];
+    char adr;
+
+    if(row == 0)                                // line offset
+        adr = column;
+    else
+        adr = 0x40 + column;
     
-    a = sseg_map[t/1000];
-    z = t%1000;
-    b = sseg_map[z/100];
-    z = z%100;
-    c = sseg_map[z/10];
-    z = z%10;
-    d = sseg_map[z];
-    print_seven_seg(a,b,c,d);
+    buf[0] = 0x00;            // Enter function setting
+    buf[1] = 0x80 + adr;    // LCD adr counter set to "adr"
+
+    i2c.write(BAT,(char *)buf,2);
+
+    buf[0] = 0x40;            // write to DDRAM
+    buf[1] = ddram_byte;
+
+    i2c.write(BAT,(char *)buf,2);
+
+    return(0);
+}
+/******************************************/
+/*                                        */
+/* Test code for a matrix KBD built on a  */
+/* PCF8574 I2C driver                     */
+/* State, 0 - test, 1 - wait till a press */
+/* Out on the lower nibble, in upper      */
+/*                                        */
+/******************************************/
+
+char pcf8574_kbd(char state)
+{
+    char buf[0x60];
+    
+    char r = 0;
+    
+    buf[0]=0xf0;
+    i2c.write(BATKBD,(char *)buf,1);
+    while(r==0){
+        i2c.read(BATKBD,(char *)buf,1);
+        if((buf[0] & 0xf0)!=0xf0){
+            buf[0]=0xfe;
+            i2c.write(BATKBD,(char *)buf,1);
+            i2c.read(BATKBD,(char *)buf,1);
+            if((buf[0] & 0xf0)!=0xf0)
+                r = pcf8584_sub_kbd(buf[0]);
+            buf[0]=0xfd;
+            i2c.write(BATKBD,(char *)buf,1);
+            i2c.read(BATKBD,(char *)buf,1);
+            if((buf[0] & 0xf0)!=0xf0)
+                r = pcf8584_sub_kbd(buf[0]);
+            buf[0]=0xfb;
+            i2c.write(BATKBD,(char *)buf,1);
+            i2c.read(BATKBD,(char *)buf,1);
+            if((buf[0] & 0xf0)!=0xf0)
+                r = pcf8584_sub_kbd(buf[0]);
+            buf[0]=0xf7;
+            i2c.write(BATKBD,(char *)buf,1);
+            i2c.read(BATKBD,(char *)buf,1);
+            if((buf[0] & 0xf0)!=0xf0)
+                r = pcf8584_sub_kbd(buf[0]);
+        } else {
+            buf[0]=0xf0;
+            i2c.write(BATKBD,(char *)buf,1);   
+        }
+        if(state==0)
+            return(r);
+        wait(0.2);
+    }
+    
+    return(r);
+}
+char pcf8584_sub_kbd(unsigned char d)
+{
+    lprintf("Raw Code %02x, ",d);
+    switch(d){
+        case    0xee    :
+            return('c');
+        case    0xed    :
+            return('d');
+        case    0xeb    :
+            return('e');
+        case    0xe7    :
+            return('f');
+        case    0xde    :
+            return('b');
+        case    0xdd    :
+            return('9');
+        case    0xdb    :
+            return('6');
+        case    0xd7    :
+            return('3');
+        case    0xbe    :
+            return('0');
+        case    0xbd    :
+            return('8');
+        case    0xbb    :
+            return('5');
+        case    0xb7    :
+            return('2');
+        case    0x7e    :
+            return('a');
+        case    0x7d    :
+            return('7');
+        case    0x7b    :
+            return('4');
+        case    0x77    :
+            return('1');
+        default         :
+            lprintf("Strange key value passed 0X%02x\n\r",d);
+            return(0);
+    }
 }
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 i2c.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2c.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,37 @@
+/* I2C bus Functions */
+
+void marc(void);
+
+void i2c_probe(void);
+
+char init_lcd(void);
+char clear_lcd(void);
+char set_lcd(char line, char col);
+char write_lcd(char *str);
+
+char read_keyboard(void);
+char blocking_read_keyboard(void);
+
+void relay_operate(char r);
+void pio_write(unsigned char r,unsigned char d);
+void pio_read(unsigned char  d);
+
+void init_pca9685(unsigned char address);
+void channel_light(unsigned char ch, unsigned char lev);
+void pca9685_led(unsigned char addr, int led, unsigned char *values);
+void pca9685_brightness(int percent, unsigned char *values);
+
+void test_seven_seg(char loop);
+void sseg_four_digits(int a);
+void print_seven_seg(unsigned char a,unsigned char b,unsigned char c,unsigned char d);
+
+void batron_lcd_init(void);
+void batron(char *str);
+char batron_lcd_write(char *b);
+char ascii_to_lcd(char ch);
+void batron_clear(void);
+char batron_clear_line(char row);
+char batron_put_xy(char ddram_byte, char row, char column);
+
+char pcf8574_kbd(char state);
+char pcf8584_sub_kbd(unsigned char d);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 led.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/led.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,94 @@
+#include "mbed.h"
+#include "useful.h"
+
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+DigitalOut led4(LED4);
+
+/******************************************/
+/*                                        */
+/*  Simple Diag fr the 4 on board LED's   */
+/*                                        */
+/******************************************/
+
+void test_leds(char t)
+{
+    char a;
+    
+    a = 0;
+    while (a!=t){
+        led1 = 1;
+        wait(0.2);
+        led2 = 1;
+        wait(0.2);
+        led3 = 1;
+        wait(0.2);
+        led4 = 1;
+        wait(0.2);
+        led1=0;
+        led2=0;
+        led3=0;
+        led4=0;
+        a++;
+    }
+}
+
+/******************************************/
+/*                                        */
+/*   Two routines used for debug the      */
+/*   code, these let users turn on/off    */
+/*   LED's in turn                        */
+/*                                        */
+/*                                        */
+/******************************************/
+void led_on(int led)
+{
+    switch(led){
+        case    0    :  /* all on */
+            led1 = 1;
+            led2 = 1;
+            led3 = 1;
+            led4 = 1;
+            break;
+        case    1    :
+            led1=1;
+            break;
+        case    2    :
+            led2=1;
+            break;
+        case    3    :
+            led3=1;
+            break;
+        case    4    :
+            led4=1;
+            break;
+        default      :
+            lprintf("Unknown LED Number to turn on %d (Range 0,1,2,3,4)\n",led);
+    }
+}
+void led_off(int led)
+{
+    switch(led){
+        case    0    :  /* all off */
+            led1 = 0;
+            led2 = 0;
+            led3 = 0;
+            led4 = 0;
+            break;
+        case    1    :
+            led1=0;
+            break;
+        case    2    :
+            led2=0;
+            break;
+        case    3    :
+            led3=0;
+            break;
+        case    4    :
+            led4=0;
+            break;
+        default      :
+            lprintf("Unknown LED Number to turn off %d (Range 0,1,2,3,4)\n",led);
+    }
+}
diff -r 9edfcca7cd25 -r 6877bb99aa17 led.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/led.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,4 @@
+
+void test_leds(char t);
+void led_on(int led);
+void led_off(int led);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 led_diag.c
--- a/led_diag.c	Tue Jan 12 16:49:56 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-#include "mbed.h"
-#include "diags.h"
-
-DigitalOut led1(LED1);
-DigitalOut led2(LED2);
-DigitalOut led3(LED3);
-DigitalOut led4(LED4);
-/******************************************/
-/*                                        */
-/*  Test the onboard MBED LED's           */
-/*  Turn them on in turn with a wait of   */
-/*  X one hundredths of a second          */
-/*                                        */
-/*                                        */
-/******************************************/
-void test_leds(char t)
-{
-    led1 = 1;
-    wait(t/100);
-    led2 = 1;
-    wait(t/100);
-    led3 = 1;
-    wait(t/100);
-    led4 = 1;
-    wait(t/100);
-    led1=0;
-    led2=0;
-    led3=0;
-    led4=0;
-}
-/******************************************/
-/*                                        */
-/*   Two routines used for debug the      */
-/*   code, these let users turn on/off    */
-/*   LED's in turn                        */
-/*                                        */
-/*                                        */
-/******************************************/
-void led_on(char led)
-{
-    switch(led){
-        case    1    :
-            led1=1;
-            break;
-        case    2    :
-            led2=1;
-            break;
-        case    3    :
-            led3=1;
-            break;
-        case    4    :
-            led4=1;
-            break;
-        default      :
-            printf("Unknown LDE Number to turn on %d\n\r",led);
-    }
-}
-void led_off(char led)
-{
-    switch(led){
-        case    1    :
-            led1=0;
-            break;
-        case    2    :
-            led2=0;
-            break;
-        case    3    :
-            led3=0;
-            break;
-        case    4    :
-            led4=0;
-            break;
-        default      :
-            printf("Unknown LDE Number to turn on %d\n\r",led);
-    }
-}
-/******************************************/
-/*                                        */
-/*    Digital I/O tests                   */
-/*    Like the I2C PIO tests it will      */
-/*    need some sort of loop back         */
-/*                                        */
-/*                                        */
-/******************************************/
-void test_real_pio(char t)
-{
-}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 local_defines.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/local_defines.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,10 @@
+#define TO_RS232        0x00000001
+#define TO_USB          0x00000002
+#define TO_CAN          0x00000004
+#define SDCARD          0x00000010      /* Use the SD card for the file system */
+#define MEMSTICK        0x00000020      /* Use the memory stick for the file system */
+#define EXEC_CALLED     0x00010000      /* Execed a script from the user */
+#define INDENT_SET      0x00020000      /* Jump point set */
+
+#define MAX_VAR         10              /* Max number of variables in the stack */
+#define MAX_JMP         10              /* Max jump points in code */
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 main.c
--- a/main.c	Tue Jan 12 16:49:56 2010 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-#include "mbed.h"
-#include "diags.h"
-
-#define BUILD    25
-Serial pc(USBTX, USBRX); // tx, rx
-/******************************************/
-/*                                        */
-/*   Basic test suit for the base board   */
-/*   developed here                       */
-/*                                        */
-/*                                        */
-/*                                        */
-/******************************************/
-int main() 
-{
-    char    a;
-    char    buf[0x60];
-    
-    pc.printf("\n\rExpansion Board Diagnostics build %d\n\r",BUILD);
-    pc.printf("Testing the Onboard LED's\n\r");
-    test_leds(100); 
-    pc.printf("Testing the RS232 Interface\n\rWill then switch ouput to RS232\n\r");
-    test_rs232(100);  
-    sprintf(buf,"Running an I2C bus Probe\n\r");
-    serial_output_string(buf);
-    i2c_probe();
-    sprintf(buf,"Testing the LCD Interface\n\r");
-    serial_output_string(buf);
-    test_lcd(100);      
-    sprintf(buf,"Testing the Analog Interfaces\n\r");
-    serial_output_string(buf);
-    test_analog();
-    sprintf(buf,"Testing the I2C PIO Interface\n\r");
-    serial_output_string(buf);
-    test_pio(100);
-    a = 2;
-    sprintf(buf,"Testing the Seven Segment Interface\n\r");
-    serial_output_string(buf);
-    sprintf(buf,"Will pass through the test look %d times\n\r",a);
-    serial_output_string(buf);
-    test_seven_seg((char)a);
-    sprintf(buf,"Testing the CAN Interface\n\r");
-    serial_output_string(buf);
-    test_can(2);
-    sprintf(buf,"Testing the Network Interface\n\r");
-    serial_output_string(buf);
-    pc.printf("Running tests in the background loop,\n\r");
-    setup_ticker();
-    pc.printf("Testing the keyboard, display to serial channel\n\r");
-    while(1){
-        wait(0.1);
-        a = read_keyboard();
-        if(a!=0){
-            sprintf(buf,"Keyboard read returned (%02x)%c\n\r",a,a);
-            serial_output_string(buf);
-        }
-    }
-}
diff -r 9edfcca7cd25 -r 6877bb99aa17 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,143 @@
+#include "mbed.h"
+#include "main.h"
+#include "serial.h"
+#include "scripting.h"
+#include "local_defines.h"
+#include "useful.h"
+#include "can.h"
+#include "led.h"
+#include "network.h"
+#include "cmd.h"
+
+/* This file looks after the USB serial code */
+Serial pc(USBTX, USBRX); // tx, rx
+
+int sys_state = 0;
+int net_state = 0;
+int set_baud_rate = 0;
+int var[MAX_VAR];
+char pwd[0x20];
+char station_id = 0;
+
+/* This should act as a 'Hard Crash' catcher to the error lights :-)   */
+/* See http://mbed.org/forum/helloworld/topic/624/?page=1#comment-3153 */
+extern "C" void HardFault_Handler() { error("Hard Fault!\n"); } 
+
+/* Local Definitions */
+#define WELCOME "Diags for the Mbed System"
+
+/* Main Code */
+int main() {
+    char buf[80];    /* Input Buffer */
+    int    r,l = 0;
+
+   sys_state = TO_USB;
+   sprintf(pwd,"/local/");      /* set the current directory for the disk functions */
+   clear_var();
+   exec_profile();
+   
+   // Start RTC
+    time_t seconds = time(NULL);
+    if (seconds == (unsigned)-1 || seconds == 0) {
+      seconds = 1265904000;     /* http://www.onlineconversion.com/unix_time.htm  */
+      set_time(seconds);
+      lprintf("RTC initialized, start time %d seconds\r\n", seconds);
+    }
+   
+   sys_state = TO_RS232;
+   
+   lprintf("\n%s\n\n",WELCOME);
+   lprintf("CMD >");
+   sys_state = TO_USB;
+   lprintf("\n%s\n\n",WELCOME);
+   lprintf("CMD >");
+    
+   can_init(); /* Setup the can bus ready for use */
+   
+   //   sys_state = TO_RS232;
+   sys_state = TO_USB;
+   
+   while (1) {
+        r = 0;
+        while(r==0){
+            if(pc.readable()){
+                sys_state = TO_USB;
+                l = usb_gets(buf,sizeof(buf));
+                r = 1;
+            } else if(rs232_readable()){
+                sys_state = TO_RS232;
+                l = rs232_gets(buf,sizeof(buf));
+                r = 2;
+            } 
+            can_receive();        /* Check for CAN messages */
+            if(net_state){
+                network_test();   /* Check the network */
+            }
+        }
+        if(l>2){
+            find_cmd(buf);
+        }
+        
+        if (sys_state & TO_USB)
+            pc_output_string("\n\rCMD > ");
+        if (sys_state & TO_RS232)
+            rs232_output_string("\n\rCMD > ");
+        sys_state = TO_USB;
+    }
+}
+/* Local Sub Routines */
+int usb_gets(char *s,int len) 
+{
+    char   c;
+    int    cnt=0;
+
+    while ((c = pc.getc()) != 0) {
+        if ((c == 0x0a) || (c==0x0d)) {
+            pc.putc('\n');
+            pc.putc('\r');
+            *s++ = '\0';
+            return(cnt);    /* Return length */
+        } else if (c==0x7f) {  /* Delete */
+            pc.putc(0x08);
+            pc.putc(0x20);
+            pc.putc(0x08);
+            cnt--;
+            *s--;
+        } else if (c==0x08) {  /* BS */
+            pc.putc(0x08);
+            pc.putc(0x20);
+            pc.putc(0x08);
+            cnt--;
+            *s--;
+        } else if (c==025) {  /* CTRL-U */
+            while (cnt!=0) {
+                pc.putc(0x08);
+                pc.putc(0x20);
+                pc.putc(0x08);
+                cnt--;
+                *s--;
+            }
+        } else {
+            *s++ = c;
+            pc.putc(c);
+            cnt++;
+        }
+    }
+    return(cnt);
+}
+
+void pc_output_string(char *buf) 
+{
+    int a = 0;
+    while(a != strlen(buf)){
+        pc.putc(buf[a]);
+        if(buf[a]=='\n')
+            pc.putc('\r');
+        a++;
+    }
+}
+void exec_profile(void)
+{
+    char    *a[2] = {"exec","profile.cmd"};
+    exec_file(2,a);
+}
diff -r 9edfcca7cd25 -r 6877bb99aa17 main.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,3 @@
+int usb_gets(char *s,int len);
+void pc_output_string(char *buf);
+void exec_profile(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 mbed.bld
--- a/mbed.bld	Tue Jan 12 16:49:56 2010 +0000
+++ b/mbed.bld	Wed May 04 08:30:52 2011 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0
+http://mbed.org/users/mbed_official/code/mbed/builds/9114680c05da
diff -r 9edfcca7cd25 -r 6877bb99aa17 network.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/network.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,353 @@
+//#include "TCPCallbackConnection.h"
+//#include "NetServer.h"
+#include "mbed.h"
+#include "led.h"
+#include "can.h"
+#include "cmd.h"
+#include "help_data.h"
+#include "SNTPClient.h"
+#include "breakup.h"
+#include "ticker.h"
+#include "useful.h"
+
+#include "lwip/opt.h"
+#include "lwip/stats.h"
+#include "lwip/sys.h"
+#include "lwip/pbuf.h"
+#include "lwip/udp.h"
+#include "lwip/tcp.h"
+#include "lwip/dns.h"
+#include "lwip/dhcp.h"
+#include "lwip/init.h"
+#include "lwip/netif.h"
+#include "netif/etharp.h"
+#include "netif/loopif.h"
+#include "device.h"
+
+Ethernet ethernet;
+extern int net_state;
+extern char station_id;
+volatile char stage = 0;
+
+struct netif    netif_data;
+
+char *header = "HTTP/1.1 200 OK\r\n"
+                        "Content-Type: text/html\r\n"
+                        "Connection: Close\r\n\r\n"
+                        "<html>\r\n"
+                        "<head>\r\n"
+                        "<title>%s</title>\r\n"
+                        "<style type='text/css'>\r\n"
+                        "body{font-family:'Arial, sans-serif', sans-serif;font-size:.8em;background-color:#fff;}\r\n"
+                        "</style>\r\n"
+                        "</head>\r\n";
+
+char network_write_packet(struct tcp_pcb *pcb, char *buf)
+{
+    if (tcp_write(pcb, (void *)buf, strlen(buf), 1) == ERR_OK) {
+        tcp_output(pcb);
+        lprintf("Wrote packet String (Size %d bytes)OK...\n",strlen(buf));
+        return(1);
+    } else {
+        lprintf("Transission Problem (Size %d bytes), Closing connection...\n",strlen(buf));
+        tcp_close(pcb);
+        return(0);
+    }
+}
+void network_send_page(struct tcp_pcb *pcb,char *head, char *body, char *tail)
+{
+    if(network_write_packet(pcb, head)){
+        if(network_write_packet(pcb, body)){
+            if(network_write_packet(pcb, tail)){
+                tcp_close(pcb);
+            } else {
+               tcp_close(pcb);
+            }
+        } else {
+            tcp_close(pcb);
+        }
+    } else {
+        tcp_close(pcb);
+    }
+}
+int network_text_packet(struct tcp_pcb *pcb, char *buf)
+{
+    char    str[0x1200];    /* So we can take a 1024 byte string max */
+    char    c;
+    int     a = 0;          /* Input pointer */
+    int     b = 0;          /* output pointer */
+    
+    str[b]='<';
+    b++;
+    str[b]='p';
+    b++;
+    str[b]='r';
+    b++;
+    str[b]='e';
+    b++;
+    str[b]='>';
+    b++;
+    
+    while(a != strlen(buf)){
+        c = buf[a];
+        if(c=='\n'){
+            str[b]='<';
+            b++;
+            str[b]='b';
+            b++;
+            str[b]='r';
+            b++;
+            str[b]='>';
+            b++;
+            str[b]='\n';
+            b++;
+            a++;
+        } else if(c=='<') {
+            a++;
+        } else if(c=='>') {
+            a++;
+        } else {
+            str[b] = c;
+            a++;
+            b++;
+        }
+    }
+    str[b]='<';
+    b++;
+    str[b]='/';
+    b++;
+    str[b]='p';
+    b++;
+    str[b]='r';
+    b++;
+    str[b]='e';
+    b++;
+    str[b]='>';
+    b++;
+    str[b]='\0';
+    if(!network_write_packet(pcb, str)){
+        lprintf("Problem Packet is:\n%s",str);
+        tcp_close(pcb);
+        return(1);
+    }
+    return(0);
+}
+err_t recv_callback(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) 
+{
+    struct netif   *netif = &netif_data;
+    char *p1[100];   /* Used for the broke apart GET request */
+    char *p2[3];     /* Diagnostics call */
+    char *p3[10];    /* Diagnostics data */
+    char head[1024],body[1024],tail[200];
+    int  ret;
+     
+    lprintf("TCP callback from %d.%d.%d.%d\n", ip4_addr1(&(pcb->remote_ip)),ip4_addr2(&(pcb->remote_ip)),ip4_addr3(&(pcb->remote_ip)),ip4_addr4(&(pcb->remote_ip)));
+    char *data;
+    /* Check if status is ok and data is arrived. */
+    if (err == ERR_OK && p != NULL) {
+        /* Inform TCP that we have taken the data. */
+        tcp_recved(pcb, p->tot_len);
+        data = static_cast<char *>(p->payload);
+        /* If the data is a GET request we can handle it. */
+        if (strncmp(data, "GET ", 4) == 0) {
+            lprintf("Handling GET request...\r\n");
+            lprintf("Request:\r\n%s\r\n", data);
+            breakup(data,p1,'/');
+            time_t seconds = time(NULL);
+            sprintf(tail,"<br><small><A href=\"mailto:pcc@cs.york.ac.uk\">"
+                "pcc@cs.york.ac.uk</a>\n\r</small>\n\r"
+                "<small>mbed RTC time:%s</small><br/>\n\r"
+                "<a href=0>Home</a><br><br>\n\r"
+                "</body>\n\r</html>\n\r",ctime(&seconds));
+            switch(p1[2][0]){
+                case    '0'     :   /* Home Page */
+                    sprintf(head,header,"MBED Home");
+                    sprintf(body,"<h1>Petes MBED Homepage</h1>\n\r"
+                        "<a href=1>Board Type</a><br>\n\r"
+                        "<a href=2>Networking</a><br>\n\r"
+                        "<a href=3>Commands</a><br>\n\r"
+                        "<a href=4>CAN Bus</a><br>\n\r"
+                        "<a href=5>Diags</a><br>\n\r");
+                    network_send_page(pcb,head,body,tail);
+                    break;
+                case    '1'     :   /* Do something for page 1 */
+                    sprintf(head,header,"Board Type");
+                    sprintf(body,"<h1>MBED Board Data</h1>\n\r"
+                                "Philips NXP <a href=http://mbed.org/nxp/lpc1768/>LPC1768</a>"
+                                " Micro Controler <br>\n\r"
+                                "512K Flash Memory, 64K SRAM<br>\n\r"
+                                "<h4>MCP Solution gives:-</h4>\n\r"
+                                "1 * RS232 channel, 1 * CAN bus channel<br>\n\r"
+                                "Audio in and out, plus 4 analog inputs<br>\n\r"
+                                "Micro SD card slot, USB + TCPIP networking<br>\n\r"
+                                "+ I2C bus and selected I/O<br><br>\n\r"
+                                "See mbed.org for data<br>\n\r");
+                    network_send_page(pcb,head,body,tail);
+                break;
+                case    '2'     :   /* Networking */
+                    sprintf(head,header,"Network");
+                    sprintf(body,     "<h1>MBED Networking</h1>\n\r"
+                    "<h2>mbed Network Configuration</h2>\n\r"
+                    "mbed HW address: %02x:%02x:%02x:%02x:%02x:%02x<br/>\n\r"
+                    "mbed IP Address: %s<br/>\n\r"
+                    "Station: %d<br>",
+                    (char*) netif->hwaddr[0],
+                    (char*) netif->hwaddr[1],
+                    (char*) netif->hwaddr[2],
+                    (char*) netif->hwaddr[3],
+                    (char*) netif->hwaddr[4],
+                    (char*) netif->hwaddr[5],
+                    inet_ntoa(*(struct in_addr*)&(netif->ip_addr)),
+                    station_id
+                   );
+                    network_send_page(pcb,head,body,tail);
+                break;
+                case    '3'     :   /* Do something for page 3 */
+                    sprintf(head,header,"Commands");
+                    network_write_packet(pcb,head);
+                    sprintf(body,"<h1>MBED Commands</h1>\n\r");
+                    network_write_packet(pcb,body);
+                    network_text_packet(pcb,HELP_STRING);
+                    network_text_packet(pcb,HELP_STRING2);
+                    network_text_packet(pcb,HELP_STRING3);
+                    network_write_packet(pcb,tail);
+                    tcp_close(pcb);
+                break;
+                case    '4'     :   /* Do something for page 4 */
+                    sprintf(head,header,"CAN Bus<br>");
+                    network_send_page(pcb,head,body,tail);
+                break;
+                case    '5'     :   /* Diagnostics page */
+                    sprintf(head,header,"Board Diags");
+                    network_write_packet(pcb,head);
+                    /* Command handler */
+                    if(breakup(p1[2],p2,'?')>1){
+                        ret = breakup(p2[1],p3,'&');
+                        if((strcmp(p3[0],"ticker"))==0)
+                            setup_ticker();
+                        else if((strcmp(p3[0],"lcd"))==0)
+                            lcd_test(ret,p3);
+                        else
+                            lprintf("Command not found, Looking for %s\n",p3[0]);
+                    }
+                    network_write_packet(pcb,"<a href=5?ticker&1>Ticker Start</a><br>\n\r");
+                    network_write_packet(pcb,"<a href=5?lcd&1>String to LCD 1</a><br>\n\r");
+                    network_write_packet(pcb,"<a href=5?lcd&2>String to LCD 2</a><br>\n\r");
+                    network_write_packet(pcb,"<a href=5?sseg>Seven Segment driver test</a><br>\n\r");
+                    network_write_packet(pcb,tail);
+                    tcp_close(pcb);
+                    
+                break;
+                default         :
+                    sprintf(head,header,"MBED Board");
+                    sprintf(body,"<h1>404 Error</h1>\n\r");
+                    network_send_page(pcb,head,body,tail);
+                break;
+            }
+
+
+              
+        } else {
+            lprintf("Non GET request...\r\nRequest:\r\n%s\r\n", data);
+        }
+
+        pbuf_free(p);
+    }
+
+    else {
+        /* No data arrived */
+        /* That means the client closes the connection and sent us a packet with FIN flag set to 1. */
+        /* We have to cleanup and destroy out TCPConnection. */
+        lprintf("Connection closed by client.\r\n");
+        pbuf_free(p);
+    }
+    /* Don't panic! Everything is fine. */
+    return ERR_OK;
+}
+/* Accept an incomming call on the registered port */
+err_t accept_callback(void *arg, struct tcp_pcb *npcb, err_t err) {
+    LWIP_UNUSED_ARG(arg);
+    /* Subscribe a receive callback function */
+    tcp_recv(npcb, &recv_callback);
+    /* Don't panic! Everything is fine. */
+    return ERR_OK;
+}
+
+void network_init(void)
+{
+    lprintf("l\r\nNetwork Starting Up...\r\n");
+    stage = 0;
+    struct netif   *netif = &netif_data;
+    struct ip_addr  ipaddr;
+    struct ip_addr  netmask;
+    struct ip_addr  gateway;
+    Ticker tickFast, tickSlow, tickARP, eth_tick, dns_tick, dhcp_coarse, dhcp_fine;
+//    stage_blinker.attach_us(&stageblinker, 1000*500);
+
+    char *hostname = "my-mbed";
+
+    lprintf("Configuring device for DHCP...\r\n");
+    /* Start Network with DHCP */
+    IP4_ADDR(&netmask, 255,255,255,255);
+    IP4_ADDR(&gateway, 0,0,0,0);
+    IP4_ADDR(&ipaddr, 0,0,0,0);
+    /* Initialise after configuration */
+    lwip_init();
+    netif->hwaddr_len = ETHARP_HWADDR_LEN;
+    device_address((char *)netif->hwaddr);
+    netif = netif_add(netif, &ipaddr, &netmask, &gateway, NULL, device_init, ip_input);
+    netif->hostname = hostname;
+    netif_set_default(netif);
+    dhcp_start(netif); // <-- Use DHCP
+
+    /* Initialise all needed timers */
+    tickARP.attach_us( &etharp_tmr,  ARP_TMR_INTERVAL  * 1000);
+    tickFast.attach_us(&tcp_fasttmr, TCP_FAST_INTERVAL * 1000);
+    tickSlow.attach_us(&tcp_slowtmr, TCP_SLOW_INTERVAL * 1000);
+    dns_tick.attach_us(&dns_tmr, DNS_TMR_INTERVAL * 1000);
+    dhcp_coarse.attach_us(&dhcp_coarse_tmr, DHCP_COARSE_TIMER_MSECS * 1000);
+    dhcp_fine.attach_us(&dhcp_fine_tmr, DHCP_FINE_TIMER_MSECS * 1000);
+    stage = 1; 
+    while (!netif_is_up(netif)) {
+        device_poll();
+    }
+
+    /*
+        while (!(netif->dhcp->state == DHCP_BOUND || netif->dhcp->state == DHCP_PERMANENT))
+        {
+            ledLink = ethernet.link();
+            device_poll();
+            //printf("Waiting for DHCP response, state = %d\r\n", netif->dhcp->state);
+            //wait_ms(100);
+            }
+        */
+    stage = 2;
+    lprintf("Interface %02x.%02x.%02x.%02x.%02x.%02x is up, local IP is %s\r\n",
+            (char*) netif->hwaddr[0],
+            (char*) netif->hwaddr[1],
+            (char*) netif->hwaddr[2],
+            (char*) netif->hwaddr[3],
+            (char*) netif->hwaddr[4],
+            (char*) netif->hwaddr[5],
+           inet_ntoa(*(struct in_addr*)&(netif->ip_addr)));
+
+    lprintf("Starting Web Server...\r\n");
+
+    /* Bind a function to a tcp port */
+    struct tcp_pcb *pcb = tcp_new();
+    if (tcp_bind(pcb, IP_ADDR_ANY, 80) == ERR_OK) {
+        pcb = tcp_listen(pcb);
+        tcp_accept(pcb, &accept_callback);
+    }
+    net_state = 1;
+    
+    lprintf("Waiting for connection...\n");
+}
+
+void network_test(void) 
+{
+    led_on(2);
+    device_poll();
+    ethernet.link();
+    led_off(2);
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 network.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/network.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,3 @@
+void network_send_page(struct tcp_pcb *pcb,char *head, char *body, char *tail);
+void network_init(void);
+void network_test(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 pca9685_reg.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pca9685_reg.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,120 @@
+#ifndef __PCA9685_H
+#define __PCA9685_H
+
+/* Devices */
+#define LEDDRV1    0xbe
+#define LEDDRV2    0xbf
+#define LEDDRV3    0xc0
+#define LEDDRV4    0xc1
+#define LEDDRV5    0xc2
+#define LEDDRV6    0xc3
+
+/* Registers */
+#define PCA9685_MODE1            0x00
+#define PCA9685_MODE2            0x01
+#define PCA9685_SUBADR1            0x02
+#define PCA9685_SUBADR2            0x03
+#define PCA9685_SUBADR3            0x04
+#define PCA9685_ALLCALLADR        0x05
+#define PCA9685_LED0_ON_L        0x06
+#define PCA9685_LED0_ON_H        0x07
+#define PCA9685_LED0_OFF_L        0x08
+#define PCA9685_LED0_OFF_H        0x09
+#define PCA9685_LED1_ON_L        0x0a
+#define PCA9685_LED1_ON_H        0x0b
+#define PCA9685_LED1_OFF_L        0x0c
+#define PCA9685_LED1_OFF_H        0x0d
+#define PCA9685_LED2_ON_L        0x0e
+#define PCA9685_LED2_ON_H        0x0f
+#define PCA9685_LED2_OFF_L        0x10
+#define PCA9685_LED2_OFF_H        0x11
+#define PCA9685_LED3_ON_L        0x12
+#define PCA9685_LED3_ON_H        0x13
+#define PCA9685_LED3_OFF_L        0x14
+#define PCA9685_LED3_OFF_H        0x15
+#define PCA9685_LED4_ON_L        0x16
+#define PCA9685_LED4_ON_H        0x17
+#define PCA9685_LED4_OFF_L        0x18
+#define PCA9685_LED4_OFF_H        0x19
+#define PCA9685_LED5_ON_L        0x1a
+#define PCA9685_LED5_ON_H        0x1b
+#define PCA9685_LED5_OFF_L        0x1c
+#define PCA9685_LED5_OFF_H        0x1d
+#define PCA9685_LED6_ON_L        0x1e
+#define PCA9685_LED6_ON_H        0x1d
+#define PCA9685_LED6_OFF_L        0x20
+#define PCA9685_LED6_OFF_H        0x21
+#define PCA9685_LED7_ON_L        0x22
+#define PCA9685_LED7_ON_H        0x23
+#define PCA9685_LED7_OFF_L        0x24
+#define PCA9685_LED7_OFF_H        0x25
+#define PCA9685_LED8_ON_L        0x26
+#define PCA9685_LED8_ON_H        0x27
+#define PCA9685_LED8_OFF_L        0x28
+#define PCA9685_LED8_OFF_H        0x29
+#define PCA9685_LED9_ON_L        0x2a
+#define PCA9685_LED9_ON_H        0x2b
+#define PCA9685_LED9_OFF_L        0x2c
+#define PCA9685_LED9_OFF_H        0x2d
+#define PCA9685_LED10_ON_L        0x2e
+#define PCA9685_LED10_ON_H        0x2f
+#define PCA9685_LED10_OFF_L        0x30
+#define PCA9685_LED10_OFF_H        0x31
+#define PCA9685_LED11_ON_L        0x32
+#define PCA9685_LED11_ON_H        0x33
+#define PCA9685_LED11_OFF_L        0x34
+#define PCA9685_LED11_OFF_H        0x35
+#define PCA9685_LED12_ON_L        0x36
+#define PCA9685_LED12_ON_H        0x37
+#define PCA9685_LED12_OFF_L        0x38
+#define PCA9685_LED12_OFF_H        0x39
+#define PCA9685_LED13_ON_L        0x3a
+#define PCA9685_LED13_ON_H        0x3b
+#define PCA9685_LED13_OFF_L        0x3c
+#define PCA9685_LED13_OFF_H        0x3d
+#define PCA9685_LED14_ON_L        0x3e
+#define PCA9685_LED14_ON_H        0x3f
+#define PCA9685_LED14_OFF_L        0x40
+#define PCA9685_LED14_OFF_H        0x41
+#define PCA9685_LED15_ON_L        0x42
+#define PCA9685_LED15_ON_H        0x43
+#define PCA9685_LED15_OFF_L        0x44
+#define PCA9685_LED15_OFF_H        0x45
+#define PCA9685_ALL_LED_ON_L       0xfa
+#define PCA9685_ALL_LED_ON_H       0xfb
+#define PCA9685_ALL_LED_OFF_L      0xfc
+#define PCA9685_ALL_LED_OFF_H      0xfd
+#define PCA9685_PRE_SCALE      0xfe
+
+/* MODE1 bits */
+#define PCA9685_RESTART    0x80
+#define PCA9685_EXTCLK    0x40
+#define PCA9685_AI    0x20
+#define PCA9685_SLEEP    0x10
+#define PCA9685_SUB1    0x08
+#define PCA9685_SUB2    0x04
+#define PCA9685_SUB3    0x02
+#define PCA9685_ALLCALL    0x01
+
+/* MODE2 bits */
+#define PCA9685_INVRT    0x10
+#define PCA9685_OCH    0x08
+#define PCA9685_OUTDRV    0x04
+#define PCA9685_OUTNE1    0x02
+#define PCA9685_OUTNE0    0x01
+
+/* LEDX_ON_H bits */
+#define PCA9685_LED_ON 0x10
+
+/* LEDX_OFF_H bits */
+#define PCA9685_LED_OFF 0x10
+
+#define PCA9685_LED_BUFSIZ       0x04
+#define PCA9685_BASE(led) ((led * 4) + 6)
+#define PCA9685_LED_ON_L       0x00
+#define PCA9685_LED_ON_H       0x01
+#define PCA9685_LED_OFF_L      0x02
+#define PCA9685_LED_OFF_H      0x03
+#define PCA9685_ALL_LEDS    -1
+
+#endif
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 precomp.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/precomp.lib	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/lwip/
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 scripting.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripting.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,178 @@
+#include "mbed.h"
+#include "local_defines.h"
+#include "useful.h"
+#include "scripting.h"
+
+extern int var[MAX_VAR];
+extern int sys_state;
+extern FILE    *exec_fp;
+
+long jmp[MAX_JMP];      /* Jump points */
+
+void clear_var(void)
+{
+    int a = 0;
+    
+    while(a != MAX_VAR){
+        var[a] = 0;
+        a++;
+    }
+}
+
+void set_var(int c, char **a)
+{
+    int v,val;
+    
+    if(sys_state & EXEC_CALLED){
+        if(c != 3)
+            var_exec_error(VAR_SET_CNT_ERROR);
+        else {
+            v = return_var(a[1]);
+            val = htoi(a[2]);
+            var[v]=val;
+        }
+            
+    } else 
+        var_exec_error(VAR_EXEC_ERROR);
+    
+}
+
+void sum_var(int c, char **a)
+{   
+    int v,val1,val2;
+       
+    if(sys_state & EXEC_CALLED){
+        if(c != 4)
+            var_exec_error(VAR_SUM_CNT_ERROR);
+        else {
+            val1 = htoi(a[1]);
+            val2 = htoi(a[3]);
+            v = return_var(a[1]);
+            switch(a[2][0]){
+                case    '+' :
+                    var[v] = val1 + val2;
+                    break;
+                case    '-' :
+                    var[v] = val1 - val2;
+                    break;
+                case    '/' :
+                    var[v] = val1 / val2;
+                    break;
+                case    '*' :
+                    var[v] = val1 * val2;
+                    break;
+                case    '%' :
+                    var[v] = val1 * val2;
+                    break;
+                default     :
+                    var_exec_error(VAR_SUM_TYPE_ERROR);
+            }
+        }
+    } else 
+        var_exec_error(VAR_EXEC_ERROR);
+}
+void point_var(int c, char **a)
+{
+    int v;
+    if(sys_state & EXEC_CALLED){
+        v = return_jmp(a[1]);
+       jmp[v] = ftell(exec_fp);         /* Read the current file pointers position */
+       sys_state = sys_state | INDENT_SET;  /* Mark the state as set */
+    } else 
+        var_exec_error(VAR_EXEC_ERROR);
+}
+void tst_var(int c, char **a)
+{
+    int v,val,j;
+    int doit=0;
+    
+    if(sys_state & EXEC_CALLED){
+        if(sys_state & INDENT_SET){
+            if(c != 5)
+                var_exec_error(VAR_TST_CNT_ERROR);
+            else {
+                v = return_var(a[1]);
+                j = return_jmp(a[4]);
+                val = htoi(a[3]);
+                switch(a[2][0]){
+                    case    '<' :
+                        if(var[v] < val)
+                            doit = 1;
+                        break;
+                    case    '>' :
+                        if(var[v] > val)
+                            doit = 1;
+                        break;
+                    case    '=' :
+                        if(var[v] == val)
+                            doit = 1;
+                        break;
+                    case    '!' :
+                        if(var[v] != val)
+                            doit = 1;
+                        break;
+                    default     :
+                        var_exec_error(VAR_TST_TYPE_ERROR);
+                }
+                if(doit)
+                    fseek (exec_fp ,jmp[j] , SEEK_SET );
+            }
+        } else
+            var_exec_error(VAR_INDENT_ERROR);
+    } else 
+        var_exec_error(VAR_EXEC_ERROR);
+}
+void clr_var(int c, char **a)
+{
+    if(sys_state & EXEC_CALLED){
+         clear_var();
+    } else 
+        var_exec_error(VAR_EXEC_ERROR);
+}
+void var_exec_error(int state)
+{
+    switch(state){
+        case    VAR_EXEC_ERROR  :
+            lprintf("Can only be called from an exec call\n");
+            break;
+        case    VAR_SET_CNT_ERROR :
+            lprintf("Format: set v<num> <value>\n");
+            break;
+        case    VAR_SUM_CNT_ERROR :
+            lprintf("Format: sum v<num> <action> v<num>\n");
+            break;
+        case    VAR_TST_CNT_ERROR :
+            lprintf("Format: tst v<num> <type> <value>\n");
+            break;
+        case    VAR_INDENT_ERROR :
+            lprintf("In branch test, with no point to loop back to\n");
+            break;
+        case    VAR_SUM_TYPE_ERROR :
+            lprintf("Unknown test type should be either +-/*\n");
+            break;
+        case    VAR_TST_TYPE_ERROR :
+            lprintf("Unknown test type should be either <>=!\n");
+            break;
+        default     :
+            lprintf("Unknown exec_error %04x\n",state);
+    }
+}
+
+int return_jmp(char *str)
+{
+    char    buf[0x4];
+    int     a;
+    
+    buf[0] = str[1];
+    buf[1] = str[2];
+    buf[2] = str[3];
+    buf[3] = str[4];
+    a = atoi(buf);
+    if(a > MAX_VAR){
+        lprintf("In Return_jmp, jmp number %d more than MAXJMP %d, returned -1\n",
+            a,MAX_JMP);
+        return(-1);
+    }
+    return(a);
+}
+
diff -r 9edfcca7cd25 -r 6877bb99aa17 scripting.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripting.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,17 @@
+void clear_var(void);
+void set_var(int c, char **a);
+void sum_var(int c, char **a);
+void point_var(int c, char **a);
+void tst_var(int c, char **a);
+void clr_var(int c, char **a);
+void var_exec_error(int state);
+int return_jmp(char *str);
+
+
+#define     VAR_EXEC_ERROR      0x0001      /* Function called out side of an exec call */
+#define     VAR_SET_CNT_ERROR   0x0002      /* Set Var call, wrong number of arguments */
+#define     VAR_SUM_TYPE_ERROR  0x0004      /* Unknown type in sum call */
+#define     VAR_SUM_CNT_ERROR   0x0008      /* SuM var call, wrong number of arguments */
+#define     VAR_TST_CNT_ERROR   0x0010      /* Tst var call, wrong number of arguments */
+#define     VAR_INDENT_ERROR    0x0020      /* No point to jump back to */
+#define     VAR_TST_TYPE_ERROR  0x0040      /* Unknown type in test call */
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 serial.c
--- a/serial.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/serial.c	Wed May 04 08:30:52 2011 +0000
@@ -1,7 +1,9 @@
 #include "mbed.h"
-#include "diags.h"
+#include "useful.h"
 
-Serial device(p13, p14);  // tx, rx
+extern int set_baud_rate;
+
+Serial rs232(p13, p14);  // tx, rx
 /******************************************/
 /*                                        */
 /*  Test the RS232 interface              */
@@ -10,14 +12,107 @@
 /*  back what is returned from the RX     */
 /*                                        */
 /******************************************/
-void test_rs232(char t)
+void rs232_opener(void)
+{
+    rs232.baud(9600);
+    rs232.printf("\n\r");
+    rs232.printf("MBED Testbed\n\r");
+}
+
+int rs232_readable(void)
 {
-    device.baud(19200);
-    device.printf("\n\r");
-    device.printf("Sending a test string to the serial port\n\r");
+    return(rs232.readable());
+}
+
+void rs232_output_string(char *buf)
+{
+    int a = 0;
+    while(a != strlen(buf)){
+        rs232.putc(buf[a]);
+        if(buf[a]=='\n')
+            rs232.putc('\r');
+        a++;
+    }
 }
 
-void serial_output_string(char *buf)
+int rs232_gets(char *s,int len) 
 {
-    device.printf(buf);
+    char   c;
+    int    cnt=0;
+
+    while ((c = rs232.getc()) != 0) {
+        if ((c == 0x0a) || (c==0x0d)) {
+            rs232.printf("\n\r");
+            *s++ = '\0';
+            return(cnt);    /* Return length */
+        } else if (c==0x7f) {  /* Delete */
+            rs232.putc(0x08);
+            rs232.putc(0x20);
+            rs232.putc(0x08);
+            cnt--;
+            *s--;
+        } else if (c==0x08) {  /* BS */
+            rs232.putc(0x08);
+            rs232.putc(0x20);
+            rs232.putc(0x08);
+            cnt--;
+            *s--;
+        } else if (c==025) {  /* CTRL-U */
+            while (cnt!=0) {
+                rs232.putc(0x08);
+                rs232.putc(0x20);
+                rs232.putc(0x08);
+                cnt--;
+                *s--;
+            }
+        } else {
+            *s++ = c;
+            rs232.putc(c);
+            cnt++;
+        }
+    }
+    return(cnt);
+}
+
+/******************************************/
+/*                                        */
+/* Set the baud rate of the serial line   */
+/* from the command line input            */
+/*                                        */
+/******************************************/
+#define BAUD_NUMBER 10
+void baud_rate(int c, char **a)
+{
+    int    b,cnt;
+    int    v[BAUD_NUMBER] = {300,600,1200,2400,4800,9600,19200,38400,57600,15200};
+    
+    b = atoi(a[1]);
+    cnt = 0;
+    while(cnt < BAUD_NUMBER){
+        if(v[cnt]==b){    
+            rs232.baud(b);
+            set_baud_rate = b;
+            return;
+        }
+        cnt++;
+    }
+    cnt=0;
+    lprintf("Select a speed from ");
+    while(cnt < BAUD_NUMBER){
+        lprintf("%d ",v[cnt]);
+        cnt++;
+    }
+    lprintf("\n\r");
+}
+/******************************************/
+/*                                        */
+/* Send a string to the serial port       */
+/*                                        */
+/******************************************/
+void rs232_test_code(int c, char **a)
+{
+    char    buf[0x100];
+    sprintf(buf,"%s\n",a[1]);
+    rs232_output_string(buf);
+        
 }
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 serial.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/serial.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,6 @@
+void rs232_opener(void);
+int rs232_readable(void);
+void rs232_output_string(char *buf);
+int rs232_gets(char *s,int len);
+void baud_rate(int c, char **a);
+void rs232_test_code(int c, char **a);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 sntp.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sntp.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,696 @@
+/*
+ * @file
+ *SNTP client module
+ *
+ */
+
+
+/*
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ * 
+ * Author: Simon Goldschmidt (lwIP raw API part)
+ */
+
+#include "lwip/opt.h"
+
+//#include "sntp.h"
+
+#include "lwip/sys.h"
+#include "lwip/sockets.h"
+#include "lwip/udp.h"
+#include "lwip/dns.h"
+
+#include "sntp.h"    // [iva2k] moving below for re-defines
+#include "useful.h"
+#include <string.h>
+#include <time.h>
+#define static
+
+/** This is simple "SNTP" client for socket or raw API.
+ * It is a minimal implementation of SNTPv4 as specified in RFC 4330.
+ * 
+ * For a list of some public NTP servers, see this link :
+ * http://support.ntp.org/bin/view/Servers/NTPPoolServers
+ *
+ * @todo:
+ * - set/change servers at runtime
+ * - complete SNTP_CHECK_RESPONSE checks 3 and 4
+ * - support broadcast/multicast mo
+ */
+
+
+
+/** Decide whether to build SNTP for socket or raw API
+ * The socket API SNTP client is a very minimal implementation that does no
+ * fully confor to the SNTPv4 RFC, especially regarding server load and error
+ * procesing. */
+#ifndef SNTP_SOCKET
+#define SNTP_SOCKET                 0
+#endif
+
+/**
+ * SNTP_DEBUG: Enable debugging for SNTP.
+ */
+#ifndef SNTP_DEBUG
+#define SNTP_DEBUG                  LWIP_DBG_OFF
+#endif
+
+/** SNTP server port */
+#ifndef SNTP_PORT
+#define SNTP_PORT                   123
+#endif
+
+
+
+/** Set this to 1 to allow SNTP_SERVER_ADDRESS to be a DNS name */
+
+#ifndef SNTP_SERVER_DNS
+#define SNTP_SERVER_DNS             0
+#endif
+
+/** Set this to 1 to support more than one server */
+#ifndef SNTP_SUPPORT_MULTIPLE_SERVERS
+#define SNTP_SUPPORT_MULTIPLE_SERVERS 1
+#endif
+
+/** SNTP server address:
+ * - as IPv4 address in "u32_t" format
+ * - as a DNS name if SNTP_SERVER_DNS is set to 1
+ * May contain multiple server names (e.g. "pool.ntp.org","second.time.server")
+ */
+#ifndef SNTP_SERVER_ADDRESS
+#if SNTP_SERVER_DNS
+#define SNTP_SERVER_ADDRESS         "pool.ntp.org"
+#else
+#define SNTP_SERVER_ADDRESS         "213.161.194.93" /* pool.ntp.org */
+#endif
+#endif
+
+/** Sanity check:
+ * Define this to
+ * - 0 to turn off sanity checks (default; smaller code)
+ * - >= 1 to check address and port of the response packet to ensure the
+ *        response comes from the server we sent the request to.
+ * - >= 2 to check returned Originate Timestamp against Transmit Timestamp
+ *        sent to the server (to ensure response to older request).
+ * - >= 3 @todo: discard reply if any of the LI, Stratum, or Transmit Timestamp
+ *        fields is 0 or the Mode field is not 4 (unicast) or 5 (broadcast).
+ * - >= 4 @todo: to check that the Root Delay and Root Dispersion fields are each
+ *        greater than or equal to 0 and less than infinity, where infinity is
+ *        currently a cozy number like one second. This check avoids using a
+ *        server whose synchronization source has expired for a very long time.
+ */
+#ifndef SNTP_CHECK_RESPONSE
+#define SNTP_CHECK_RESPONSE         0
+#endif
+
+/** According to the RFC, this shall be a random delay
+ * between 1 and 5 minutes (in milliseconds) to prevent load peaks.
+ * This can be defined to a random generation function,
+ * which must return the delay in milliseconds as u32_t.
+ * Turned off by default.
+ */
+#ifndef SNTP_STARTUP_DELAY
+#define SNTP_STARTUP_DELAY          0
+#endif
+
+/** SNTP receive timeout - in milliseconds
+ * Also used as retry timeout - this shouldn't be too low.
+ * Default is 3 seconds.
+ */
+#ifndef SNTP_RECV_TIMEOUT
+#define SNTP_RECV_TIMEOUT           3000
+#endif
+
+/** SNTP update delay - in milliseconds
+ * Default is 1 hour.
+ */
+#ifndef SNTP_UPDATE_DELAY
+#define SNTP_UPDATE_DELAY           3600000
+#endif
+#if (SNTP_UPDATE_DELAY < 15000) && !SNTP_SUPPRESS_DELAY_CHECK
+#error "SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds!"
+#endif
+
+/** SNTP macro to change system time and/or the update the RTC clock */
+#ifndef SNTP_SET_SYSTEM_TIME
+#define SNTP_SET_SYSTEM_TIME(sec)
+#endif
+
+/** SNTP macro to change system time including microseconds */
+#ifdef SNTP_SET_SYSTEM_TIME_US
+#define SNTP_CALC_TIME_US           1
+#define SNTP_RECEIVE_TIME_SIZE      2
+#else
+#define SNTP_SET_SYSTEM_TIME_US(sec, us)
+#define SNTP_CALC_TIME_US           0
+#define SNTP_RECEIVE_TIME_SIZE      1
+#endif
+
+/** SNTP macro to get system time, used with SNTP_CHECK_RESPONSE >= 2
+ * to send in request and compare in response.
+ */
+#ifndef SNTP_GET_SYSTEM_TIME
+#define SNTP_GET_SYSTEM_TIME(sec, us)     do { (sec) = 0; (us) = 0; } while(0)
+#endif
+
+/** Default retry timeout (in milliseconds) if the response
+ * received is invalid.
+ * This is doubled with each retry until SNTP_RETRY_TIMEOUT_MAX is reached.
+ */
+#ifndef SNTP_RETRY_TIMEOUT
+#define SNTP_RETRY_TIMEOUT          SNTP_RECV_TIMEOUT
+#endif
+
+/** Maximum retry timeout (in milliseconds). */
+#ifndef SNTP_RETRY_TIMEOUT_MAX
+#define SNTP_RETRY_TIMEOUT_MAX      (SNTP_RETRY_TIMEOUT * 10)
+#endif
+
+/** Increase retry timeout with every retry sent
+ * Default is on to conform to RFC.
+ */
+#ifndef SNTP_RETRY_TIMEOUT_EXP
+#define SNTP_RETRY_TIMEOUT_EXP      1
+#endif
+
+/* the various debug levels for this file */
+#define SNTP_DEBUG_TRACE        (SNTP_DEBUG | LWIP_DBG_TRACE)
+#define SNTP_DEBUG_STATE        (SNTP_DEBUG | LWIP_DBG_STATE)
+#define SNTP_DEBUG_WARN         (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING)
+#define SNTP_DEBUG_WARN_STATE   (SNTP_DEBUG | LWIP_DBG_LEVEL_WARNING | LWIP_DBG_STATE)
+#define SNTP_DEBUG_SERIOUS      (SNTP_DEBUG | LWIP_DBG_LEVEL_SERIOUS)
+
+#define SNTP_ERR_KOD                1
+
+/* SNTP protocol defines */
+#define SNTP_MSG_LEN                48
+
+#define SNTP_OFFSET_LI_VN_MODE      0
+#define SNTP_LI_MASK                0xC0
+#define SNTP_LI_NO_WARNING          0x00
+#define SNTP_LI_LAST_MINUTE_61_SEC  0x01
+#define SNTP_LI_LAST_MINUTE_59_SEC  0x02
+#define SNTP_LI_ALARM_CONDITION     0x03 /* (clock not synchronized) */
+
+#define SNTP_VERSION_MASK           0x38
+#define SNTP_VERSION                (4/* NTP Version 4*/<<3) 
+
+#define SNTP_MODE_MASK              0x07
+#define SNTP_MODE_CLIENT            0x03
+#define SNTP_MODE_SERVER            0x04
+#define SNTP_MODE_BROADCAST         0x05
+
+#define SNTP_OFFSET_STRATUM         1
+#define SNTP_STRATUM_KOD            0x00
+
+#define SNTP_OFFSET_ORIGINATE_TIME  24
+#define SNTP_OFFSET_RECEIVE_TIME    32
+#define SNTP_OFFSET_TRANSMIT_TIME   40
+
+/* number of seconds between 1900 and 1970 */
+#define DIFF_SEC_1900_1970         (2208988800)
+
+
+/**
+ * SNTP packet format (without optional fields)
+ * Timestamps are coded as 64 bits:
+ * - 32 bits seconds since Jan 01, 1970, 00:00
+ * - 32 bits seconds fraction (0-padded)
+ * For future use, if the MSB in the seconds part is set, seconds are based
+ * on Feb 07, 2036, 06:28:16.
+ */
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/bpstruct.h"
+#endif
+PACK_STRUCT_BEGIN
+struct sntp_msg {
+ PACK_STRUCT_FIELD(u8_t           li_vn_mode);
+ PACK_STRUCT_FIELD(u8_t           stratum);
+ PACK_STRUCT_FIELD(u8_t           poll);
+ PACK_STRUCT_FIELD(u8_t           precision);
+ PACK_STRUCT_FIELD(u32_t          root_delay);
+ PACK_STRUCT_FIELD(u32_t          root_dispersion);
+ PACK_STRUCT_FIELD(u32_t          reference_identifier);
+ PACK_STRUCT_FIELD(u32_t          reference_timestamp[2]);
+ PACK_STRUCT_FIELD(u32_t          originate_timestamp[2]);
+ PACK_STRUCT_FIELD(u32_t          receive_timestamp[2]);
+ PACK_STRUCT_FIELD(u32_t          transmit_timestamp[2]);
+} PACK_STRUCT_STRUCT;
+PACK_STRUCT_END
+#ifdef PACK_STRUCT_USE_INCLUDES
+#  include "arch/epstruct.h"
+#endif
+
+/* function prototypes */
+static void sntp_request(void *arg);
+
+/** The UDP pcb used by the SNTP client */
+static struct udp_pcb* sntp_pcb;
+/** Addresses of servers */
+static char* sntp_server_addresses[] = {SNTP_SERVER_ADDRESS};
+#if SNTP_SUPPORT_MULTIPLE_SERVERS
+/** The currently used server (initialized to 0) */
+static u8_t sntp_current_server;
+static u8_t sntp_num_servers = sizeof(sntp_server_addresses)/sizeof(char*);
+#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
+#define sntp_current_server 0
+#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
+
+#if SNTP_RETRY_TIMEOUT_EXP
+#define SNTP_RESET_RETRY_TIMEOUT() sntp_retry_timeout = SNTP_RETRY_TIMEOUT
+/** Retry time, initialized with SNTP_RETRY_TIMEOUT and doubled with each retry. */
+static u32_t sntp_retry_timeout;
+#else /* SNTP_RETRY_TIMEOUT_EXP */
+#define SNTP_RESET_RETRY_TIMEOUT()
+#define sntp_retry_timeout SNTP_RETRY_TIMEOUT
+#endif /* SNTP_RETRY_TIMEOUT_EXP */
+
+#if SNTP_CHECK_RESPONSE >= 1
+/** Saves the last server address to compare with response */
+static struct ip_addr sntp_last_server_address;
+#endif /* SNTP_CHECK_RESPONSE >= 1 */
+
+#if SNTP_CHECK_RESPONSE >= 2
+/** Saves the last timestamp sent (which is sent back by the server)
+ * to compare against in response */
+static u32_t sntp_last_timestamp_sent[2];
+#endif /* SNTP_CHECK_RESPONSE >= 2 */
+
+/**
+ * SNTP processing of received timestamp
+ */
+static void
+sntp_process(u32_t *receive_timestamp)
+{
+  /* convert SNTP time (1900-based) to unix GMT time (1970-based)
+   * @todo: if MSB is 1, SNTP time is 2036-based!
+   */
+  time_t t = (ntohl(receive_timestamp[0]) - DIFF_SEC_1900_1970);
+
+#if SNTP_CALC_TIME_US
+  u32_t us = ntohl(receive_timestamp[1]) / 4295;
+  SNTP_SET_SYSTEM_TIME_US(t, us);
+  /* display local time from GMT time */
+  LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s, %"U32_F" us", ctime(&t), us));
+
+#else /* SNTP_CALC_TIME_US */
+
+  /* change system time and/or the update the RTC clock */
+  SNTP_SET_SYSTEM_TIME(t);
+  /* display local time from GMT time */
+  LWIP_DEBUGF(SNTP_DEBUG_TRACE, ("sntp_process: %s", ctime(&t)));
+#endif /* SNTP_CALC_TIME_US */
+}
+
+/**
+ * Initialize request struct to be sent to server.
+ */
+static void
+sntp_initialize_request(struct sntp_msg *req)
+{
+  memset(req, 0, SNTP_MSG_LEN);
+  req->li_vn_mode = SNTP_LI_NO_WARNING | SNTP_VERSION | SNTP_MODE_CLIENT;
+
+#if SNTP_CHECK_RESPONSE >= 2
+  {
+    u32_t sntp_time_sec, sntp_time_us;
+    /* fill in transmit timestamp and save it in 'sntp_last_timestamp_sent' */
+    SNTP_GET_SYSTEM_TIME(sntp_time_sec, sntp_time_us);
+    sntp_last_timestamp_sent[0] = htonl(sntp_time_sec + DIFF_SEC_1900_1970);
+    req->transmit_timestamp[0] = sntp_last_timestamp_sent[0];
+    /* we send/save us instead of fraction to be faster... */
+    sntp_last_timestamp_sent[1] = htonl(sntp_time_us);
+    req->transmit_timestamp[1] = sntp_last_timestamp_sent[1];
+  }
+#endif /* SNTP_CHECK_RESPONSE >= 2 */
+}
+#if SNTP_SOCKET
+
+/**
+ * Send an SNTP request via sockets.
+ * This is a very minimal implementation that does not fully conform
+ * to the SNTPv4 RFC, especially regarding server load and error procesing.
+ */
+static void
+sntp_request(void *arg)
+{
+  int                sock;
+  struct sockaddr_in local;
+  struct sockaddr_in to;
+  int                tolen;
+  int                size;
+  int                timeout;
+  struct sntp_msg    sntpmsg;
+  u32_t              sntp_server_address;
+
+  LWIP_UNUSED_ARG(arg);
+
+  /* if we got a valid SNTP server address... */
+  if (inet_aton(SNTP_SERVER_ADDRESS, (struct in_addr*)&sntp_server_address)) {
+    /* create new socket */
+    sock = lwip_socket(AF_INET, SOCK_DGRAM, 0);
+    if (sock >= 0) {
+      /* prepare local address */
+      memset(&local, 0, sizeof(local));
+      local.sin_family      = AF_INET;
+      local.sin_port        = htons(INADDR_ANY);
+      local.sin_addr.s_addr = htonl(INADDR_ANY);
+
+      /* bind to local address */
+      if (lwip_bind(sock, (struct sockaddr *)&local, sizeof(local)) == 0) {
+        /* set recv timeout */
+        timeout = SNTP_RECV_TIMEOUT;
+        lwip_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(timeout));
+
+        /* prepare SNTP request */
+        sntp_initialize_request(&sntpmsg);
+
+        /* prepare SNTP server address */
+        memset(&to, 0, sizeof(to));
+        to.sin_family      = AF_INET;
+        to.sin_port        = htons(SNTP_PORT);
+        to.sin_addr.s_addr = sntp_server_address;
+    
+        /* send SNTP request to server */
+        if (lwip_sendto(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, sizeof(to)) >= 0) {
+          /* receive SNTP server response */
+          tolen = sizeof(to);
+          size  = lwip_recvfrom(sock, &sntpmsg, SNTP_MSG_LEN, 0, (struct sockaddr *)&to, (socklen_t *)&tolen);
+          /* if the response size is good */
+          if (size == SNTP_MSG_LEN) {
+            /* if this is a SNTP response... */
+            if (((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_SERVER) ||
+                ((sntpmsg.li_vn_mode & SNTP_MODE_MASK) == SNTP_MODE_BROADCAST)) {
+              /* do time processing */
+              sntp_process(sntpmsg.receive_timestamp);
+            } else {
+              LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not response frame code\n"));
+            }
+          }
+        } else {
+          LWIP_DEBUGF( SNTP_DEBUG_WARN, ("sntp_request: not sendto==%i\n", errno));
+        }
+      }
+      /* close the socket */
+      closesocket(sock);
+    }
+  }
+}
+
+/**
+ * SNTP thread
+ */
+static void
+sntp_thread(void *arg)
+{
+  LWIP_UNUSED_ARG(arg);
+  while(1) {
+    sntp_request(NULL);
+    sys_msleep(SNTP_UPDATE_DELAY);
+  }
+}
+
+/**
+ * Initialize this module when using sockets
+ */
+void
+sntp_init(void)
+{
+  sys_thread_new("sntp_thread", sntp_thread, NULL, DEFAULT_THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);
+}
+
+#else /* SNTP_SOCKET */
+
+/**
+ * Retry: send a new request (and increase retry timeout).
+ *
+ * @param arg is unused (only necessary to conform to sys_timeout)
+ */
+static void
+sntp_retry(void* arg)
+{
+  LWIP_UNUSED_ARG(arg);
+
+  LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_retry: Next request will be sent in %"U32_F" ms\n",
+    sntp_retry_timeout));
+
+  /* set up a timer to send a retry and increase the retry delay */
+  sys_timeout(sntp_retry_timeout, sntp_request, NULL);
+
+#if SNTP_RETRY_TIMEOUT_EXP
+  {
+    u32_t new_retry_timeout;
+    /* increase the timeout for next retry */
+    new_retry_timeout = sntp_retry_timeout << 1;
+    /* limit to maximum timeout and prevent overflow */
+    if ((new_retry_timeout <= SNTP_RETRY_TIMEOUT_MAX) &&
+        (new_retry_timeout > sntp_retry_timeout)) {
+      sntp_retry_timeout = new_retry_timeout;
+    }
+  }
+#endif /* SNTP_RETRY_TIMEOUT_EXP */
+}
+
+#if SNTP_SUPPORT_MULTIPLE_SERVERS
+/**
+ * If Kiss-of-Death is received (or another packet parsing error),
+ * try the next server or retry the current server and increase the retry
+ * timeout if only one server is available.
+ *
+ * @param arg is unused (only necessary to conform to sys_timeout)
+ */
+static void
+sntp_try_next_server(void* arg)
+{
+  LWIP_UNUSED_ARG(arg);
+
+  if (sntp_num_servers > 1) {
+    /* new server: reset retry timeout */
+    SNTP_RESET_RETRY_TIMEOUT();
+    sntp_current_server++;
+    if (sntp_current_server >= sntp_num_servers) {
+      sntp_current_server = 0;
+    }
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_try_next_server: Sending request to server %"U16_F"\n",
+      (u16_t)sntp_current_server));
+    /* instantly send a request to the next server */
+    sntp_request(NULL);
+  } else {
+    sntp_retry(NULL);
+  }
+}
+#else /* SNTP_SUPPORT_MULTIPLE_SERVERS */
+/* Always retry on error if only one server is supported */
+#define sntp_try_next_server    sntp_retry
+#endif /* SNTP_SUPPORT_MULTIPLE_SERVERS */
+
+/** UDP recv callback for the sntp pcb */
+static void
+sntp_recv(void *arg, struct udp_pcb* pcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
+{
+  u8_t mode;
+  u8_t stratum;
+  u32_t receive_timestamp[SNTP_RECEIVE_TIME_SIZE];
+  err_t err;
+
+  LWIP_UNUSED_ARG(arg);
+  LWIP_UNUSED_ARG(pcb);
+  /* packet received: stop retry timeout  */
+  sys_untimeout(sntp_try_next_server, NULL);
+  sys_untimeout(sntp_request, NULL);
+
+  err = ERR_ARG;
+#if SNTP_CHECK_RESPONSE >= 1
+  /* check server address and port */
+  if ((addr->addr == sntp_last_server_address.addr) &&
+    (port == SNTP_PORT))
+#else /* SNTP_CHECK_RESPONSE >= 1 */
+  LWIP_UNUSED_ARG(addr);
+  LWIP_UNUSED_ARG(port);
+#endif /* SNTP_CHECK_RESPONSE >= 1 */
+  {
+    /* process the response */
+    if (p->tot_len == SNTP_MSG_LEN) {
+      pbuf_copy_partial(p, &mode, 1, SNTP_OFFSET_LI_VN_MODE);
+      mode &= SNTP_MODE_MASK;
+      /* if this is a SNTP response... */
+      if ((mode == SNTP_MODE_SERVER) ||
+          (mode == SNTP_MODE_BROADCAST)) {
+        pbuf_copy_partial(p, &stratum, 1, SNTP_OFFSET_STRATUM);
+        if (stratum == SNTP_STRATUM_KOD) {
+          /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
+          err = SNTP_ERR_KOD;
+          LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Received Kiss-of-Death\n"));
+        } else {
+#if SNTP_CHECK_RESPONSE >= 2
+          /* check originate_timetamp against sntp_last_timestamp_sent */
+          u32_t originate_timestamp[2];
+          pbuf_copy_partial(p, &originate_timestamp, 8, SNTP_OFFSET_ORIGINATE_TIME);
+          if ((originate_timestamp[0] != sntp_last_timestamp_sent[0]) ||
+              (originate_timestamp[1] != sntp_last_timestamp_sent[1]))
+          {
+            LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid originate timestamp in response\n"));
+          } else
+#endif /* SNTP_CHECK_RESPONSE >= 2 */
+          /* @todo: add code for SNTP_CHECK_RESPONSE >= 3 and >= 4 here */
+          {
+            /* correct answer */
+            err = ERR_OK;
+            pbuf_copy_partial(p, &receive_timestamp, SNTP_RECEIVE_TIME_SIZE * 4, SNTP_OFFSET_RECEIVE_TIME);
+          }
+        }
+      } else {
+        LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid mode in response: %"U16_F"\n", (u16_t)mode));
+      }
+    } else {
+      LWIP_DEBUGF(SNTP_DEBUG_WARN, ("sntp_recv: Invalid packet length: %"U16_F"\n", p->tot_len));
+    }
+  }
+  pbuf_free(p);
+
+  if (err == ERR_OK) {
+    /* Correct response, reset retry timeout */
+    SNTP_RESET_RETRY_TIMEOUT();
+    sntp_process(receive_timestamp);
+
+    /* Set up timeout for next request */
+    sys_timeout((u32_t)SNTP_UPDATE_DELAY, sntp_request, NULL);
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_recv: Scheduled next time request: %"U32_F" ms\n",
+      (u32_t)SNTP_UPDATE_DELAY));
+  } else if (err == SNTP_ERR_KOD) {
+    /* Kiss-of-death packet. Use another server or increase UPDATE_DELAY. */
+    sntp_try_next_server(NULL);
+  } else {
+    /* another error, try the same server again */
+    sntp_retry(NULL);
+  }
+}
+
+/** Actually send an sntp request to a server.
+ *
+ * @param server_addr resolved IP address of the SNTP server
+ */
+static void
+sntp_send_request(struct ip_addr *server_addr)
+{
+  struct pbuf* p;
+  p = pbuf_alloc(PBUF_TRANSPORT, SNTP_MSG_LEN, PBUF_RAM);
+  if (p != NULL) {
+    struct sntp_msg *sntpmsg = (struct sntp_msg *)p->payload;
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_send_request: Sending request to server\n"));
+    /* initialize request message */
+    sntp_initialize_request(sntpmsg);
+    /* send request */
+    udp_sendto(sntp_pcb, p, server_addr, SNTP_PORT);
+pbuf_free(p);    // [iva2k] fixing memory leak
+    /* set up receive timeout: try next server or retry on timeout */
+    sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
+#if SNTP_CHECK_RESPONSE >= 1
+    /* save server address to verify it in sntp_recv */ 
+    sntp_last_server_address.addr = server_addr->addr;
+#endif /* SNTP_CHECK_RESPONSE >= 1 */
+  } else {
+    LWIP_DEBUGF(SNTP_DEBUG_SERIOUS, ("sntp_send_request: Out of memory, trying again in %"U32_F" ms\n",
+      (u32_t)SNTP_RETRY_TIMEOUT));
+    /* out of memory: set up a timer to send a retry */
+    sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_request, NULL);
+  }
+}
+
+/**
+ * DNS found callback when using DNS names as server address.
+ */
+static void
+sntp_dns_found(const char* hostname, struct ip_addr *ipaddr, void *arg)
+{
+  LWIP_UNUSED_ARG(hostname);
+  LWIP_UNUSED_ARG(arg);
+
+  if (ipaddr != NULL) {
+    /* Address resolved, send request */
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_dns_found: Server address resolved, sending request\n"));
+    sntp_send_request(ipaddr);
+  } else {
+    /* DNS resolving failed -> try another server */
+    LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_dns_found: Failed to resolve server address resolved, trying next server\n"));
+//    sntp_try_next_server(NULL);
+// [iva2k] changing to delayed - having no DNS may mean that there is something wrong. don't hang in here.
+    sys_timeout((u32_t)SNTP_RECV_TIMEOUT, sntp_try_next_server, NULL);
+  }
+}
+/**
+ * Send out an sntp request via raw API.
+ *
+ * @param arg is unused (only necessary to conform to sys_timeout)
+ */
+static void
+sntp_request(void *arg)
+{
+  struct ip_addr sntp_server_address;
+  err_t err;
+
+  LWIP_UNUSED_ARG(arg);
+  /* initialize SNTP server address */
+#if SNTP_SERVER_DNS
+  err = dns_gethostbyname(sntp_server_addresses[sntp_current_server], &sntp_server_address,
+    sntp_dns_found, NULL);
+  if (err == ERR_INPROGRESS) {
+    /* DNS request sent, wait for sntp_dns_found being called */
+    LWIP_DEBUGF(SNTP_DEBUG_STATE, ("sntp_request: Waiting for server address to be resolved.\n"));
+    return;
+  }
+#else /* SNTP_SERVER_DNS */
+  err = inet_aton(sntp_server_addresses[sntp_current_server], (struct in_addr*)&sntp_server_address)
+    ? ERR_OK : ERR_ARG;
+#endif /* SNTP_SERVER_DNS */
+  if (err == ERR_OK) {
+    sntp_send_request(&sntp_server_address);
+  } else {
+    /* address conversion failed, try another server */
+    LWIP_DEBUGF(SNTP_DEBUG_WARN_STATE, ("sntp_request: Invalid server address, trying next server.\n"));
+    sys_timeout((u32_t)SNTP_RETRY_TIMEOUT, sntp_try_next_server, NULL);
+  }
+}
+/**
+ * Initialize this module when using raw API.
+ * Send out request instantly or after SNTP_STARTUP_DELAY.
+ */
+void
+sntp_init(void)
+{
+  SNTP_RESET_RETRY_TIMEOUT();
+  sntp_pcb = udp_new();
+  LWIP_ASSERT("Failed to allocate udp pcb for sntp client", sntp_pcb != NULL);
+  if (sntp_pcb != NULL) {
+    udp_recv(sntp_pcb, sntp_recv, NULL);
+#if SNTP_STARTUP_DELAY
+    sys_timeout((u32_t)SNTP_STARTUP_DELAY, sntp_request, NULL);
+#else
+    sntp_request(NULL);
+#endif
+  }
+}
+#endif /* SNTP_SOCKET */
diff -r 9edfcca7cd25 -r 6877bb99aa17 sntp.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sntp.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,18 @@
+#ifndef __SNTP_H__
+#define __SNTP_H__
+
+void sntp_init(void);
+
+// [iva2k] Plugging SYS_
+#if NO_SYS
+void sntp_sys_timeout(u32_t timeout_ms, void (*func)(void *arg), void *arg);
+void sntp_sys_untimeout(void (*sntp_request)(void *arg), void *arg);
+#endif  // NO_SYS
+
+#undef sys_timeout
+#define sys_timeout sntp_sys_timeout
+
+#undef sys_untimeout
+#define sys_untimeout sntp_sys_untimeout
+
+#endif /* __SNTP_H__ */
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 sound.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sound.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,97 @@
+#include "mbed.h"
+#include "Synth.h"
+Synth s(p18);
+void fly_me_to_the_moon(Synth *s) {
+    //Fly me to the moon
+    s->add_note(NOTE_C5, 1.5);
+    s->add_note(NOTE_B4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 1.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_C5, 0.5);
+    s->add_note(NOTE_B4, 1.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 3);
+    s->add_note(NOTE_A4, 1.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_D4, 1.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_A_FLAT4, 1.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_D4, 0.5);
+    s->add_note(NOTE_C4, 2);
+    s->add_note(NOTE_C_SHARP4, 1);
+    s->add_note(NOTE_D4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_A4, 3);
+    s->add_note(NOTE_C5, 1);
+    s->add_note(NOTE_B4, 1);
+    s->add_note(NOTE_G4, 5);
+    s->add_note(NOTE_B3, 1);
+    s->add_note(NOTE_C4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_F4, 3);
+    s->add_note(NOTE_A4, 1);
+    s->add_note(NOTE_G4, 1);
+    s->add_note(NOTE_F4, 1);
+    s->add_note(NOTE_E4, 5);
+    s->add_note(NOTE_C5, 1.5);
+    s->add_note(NOTE_B4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 1.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_C5, 0.5);
+    s->add_note(NOTE_B4, 1.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 3);
+    s->add_note(NOTE_A4, 1.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_D4, 1.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_G4, 0.5);
+    s->add_note(NOTE_A_FLAT4, 1.5);
+    s->add_note(NOTE_F4, 0.5);
+    s->add_note(NOTE_E4, 0.5);
+    s->add_note(NOTE_D4, 0.5);
+    s->add_note(NOTE_C4, 2);
+    s->add_note(NOTE_C_SHARP4, 1);
+    s->add_note(NOTE_D4, 0.5);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_A4, 3);
+    s->add_note(NOTE_C5, 1);
+    s->add_note(NOTE_B4, 1);
+    s->add_note(NOTE_G4, 5);
+    s->add_note(NOTE_A_FLAT4, 1);
+    s->add_note(NOTE_A4, 0.5);
+    s->add_note(NOTE_C4, 0.5);
+    s->add_note(NOTE_C4, 3);
+    s->add_note(NOTE_C4, 1);
+    s->add_note(NOTE_D4, 1);
+    s->add_note(NOTE_C4, 3);
+}
+int sound(void)
+{
+    PluckedGuitar *g = new PluckedGuitar();
+    s.set_bpm(200);
+    s.set_instrument(g);
+    fly_me_to_the_moon(&s);
+    s.set_repeat(true);
+    s.play();
+    return(0);
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 sound.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sound.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+int sound(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 ticker.c
--- a/ticker.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/ticker.c	Wed May 04 08:30:52 2011 +0000
@@ -1,15 +1,17 @@
 #include "mbed.h"
-#include "diags.h"
+#include "led.h"
+#include "i2c.h"
+#include "useful.h"
+#include "can.h"
+
 
 char ticker_led;
 int  ticker_cnt=0;
 
-Ticker f;
+Ticker led_ticker;
 
 void led_tick(void)
 {
-    char    buf[0x60];
-    
     ticker_cnt++;
     
     if(ticker_led){
@@ -19,14 +21,12 @@
         led_on(4);
         ticker_led=1;
     }
-    sprintf(buf,"In Ticker loop\n\rlooped %d times",ticker_cnt);
-    clear_lcd();
-    write_lcd(buf);
-    sseg_ticker_test(ticker_cnt);
-    
+    sseg_four_digits(ticker_cnt);
+    can_ticker_tx(ticker_cnt);
 }
 
 void setup_ticker(void)
 {
-   f.attach(&led_tick,1); 
+   lprintf("Setting a 1 second ticker running on LED4\n");
+   led_ticker.attach(&led_tick,1.0); 
 }
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 ticker.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ticker.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,2 @@
+void led_tick(void);
+void setup_ticker(void);
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 useful.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/useful.c	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,112 @@
+#include "mbed.h"
+#include <stdarg.h>
+#include "main.h"
+#include "serial.h"
+#include "local_defines.h"
+#include "useful.h"
+
+extern int var[MAX_VAR];
+extern int sys_state;
+
+/* Function: hexview
+ *  Prints an array of char to stdout in hex.
+ *  The data is grouped in two 8 byte groups per line.
+ *  Each byte is displayed as 2 hex digits and every 
+ *  line starts with the address of the first byte.
+ *
+ *  There is no text view of a line.
+ *
+ * Variables:
+ *  buffer - The array to display.
+ *  size - The length of buffer.
+ * 
+ * Author: rmeyer
+ */
+void hexview(char *buffer, unsigned int size) {
+    printf("\n");
+    for(int i = 0; i < size; ++i) {
+        if((i%16)!=0) {
+            printf(" ");
+        } else {
+            printf("%04X:  ", (i));
+        }
+        printf("%02hhx", buffer[i]);
+        if((i%16) ==  7) { 
+            printf(" ");
+        }
+        if((i%16) == 15) {
+            printf("\n\r");
+        }
+    }
+    printf("\n\r\n\r\n\r");
+}
+
+/******************************************/
+/*                                        */
+/* Lprintf, Bring the printf under our    */
+/* control, so we can use either rs232    */
+/* or the USB-Serial connections as an    */
+/* I/O channel.                           */
+/*                                        */
+/******************************************/
+
+void lprintf(const char* fmt, ...)
+{
+    char    str[0x1000];
+    
+    va_list ap;
+    va_start(ap, fmt); 
+    vsprintf(str, fmt, ap);   
+    if (sys_state & TO_RS232){
+        rs232_output_string(str);
+    } else if (sys_state & TO_USB){
+        pc_output_string(str);           
+    }
+    va_end(ap);
+}
+
+/******************************************/
+/*                                        */
+/* Read a value in from a user, workout   */
+/* if its hex or decimal, and return an   */
+/* int to the user                        */
+/*                                        */
+/******************************************/
+int htoi(char *str)
+{
+    if(strlen(str)>=2){
+        if(str[0]=='v' || str[0]=='V'){
+            return(var[return_var(str)]);
+        } else if(str[1]=='x' || str[1]=='X'){
+            return(strtol(str, NULL, 16));
+        }        
+    }
+    return(atoi(str));
+}
+
+/******************************************/
+/*                                        */
+/* Given the input string, return the     */
+/* number of the variable the user wants  */
+/* its added to htoi, so all inputs       */
+/* should get access to the variable data */
+/*                                        */
+/******************************************/
+
+int return_var(char *str)
+{
+    char    buf[0x4];
+    int     a;
+    
+    buf[0] = str[1];
+    buf[1] = str[2];
+    buf[2] = str[3];
+    buf[3] = str[4];
+    a = atoi(buf);
+    if(a > MAX_VAR){
+        lprintf("In Return_var, var number %d more than MAXVAR %d, returned -1\n",
+            a,MAX_VAR);
+        return(-1);
+    }
+    return(a);
+}
\ No newline at end of file
diff -r 9edfcca7cd25 -r 6877bb99aa17 useful.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/useful.h	Wed May 04 08:30:52 2011 +0000
@@ -0,0 +1,1 @@
+void hexview(char *buffer, unsigned int size);
void lprintf(const char* fmt, ...);
int htoi(char *str);
int return_var(char *str);
\ No newline at end of file