Peter Cooper
/
diags
test code for our MBED board
Revision 1:6877bb99aa17, committed 2011-05-04
- Comitter:
- lolpcc
- Date:
- Wed May 04 08:30:52 2011 +0000
- Parent:
- 0:9edfcca7cd25
- Commit message:
Changed in this revision
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( ðarp_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