mbed Weather Platform firmware http://mbed.org/users/okini3939/notebook/mbed-weather-platform-firmware/

Dependencies:   ChaNFSSD EthernetNetIf I2CLEDDisp Agentbed ChaNFSUSB ILinterpreter mbed BMP085 WeatherMeters ConfigFile ChaNFS I2CLCD

TinyNet/TinySNTP.cpp

Committer:
okini3939
Date:
2012-03-16
Revision:
8:bed0b81794ba
Parent:
7:f7c98d836f81

File content as of revision 8:bed0b81794ba:

/*
 * mbed Tiny SNTP(NTP) Client
 * Copyright (c) 2011 Hiroshi Suga
 * Released under the MIT License: http://mbed.org/license/mit
 */

/** @file
 * @brief Tiny DNS Resolver
 */

#include "mbed.h"
#include "EthernetNetIf.h"
#include "UDPSocket.h"
#include "DNSRequest.h"
#include "TinySNTP.h"

// host to network short
#define htons( x ) ( (( (x) << 8 ) & 0xFF00) | (( (x) >> 8 ) & 0x00FF) )
#define ntohs( x ) htons(x)
// host to network long
#define htonl( x ) ( (( (x) << 24 ) & 0xFF000000)  \
                   | (( (x) <<  8 ) & 0x00FF0000)  \
                   | (( (x) >>  8 ) & 0x0000FF00)  \
                   | (( (x) >> 24 ) & 0x000000FF)  )
#define ntohl( x ) htonl(x)

static UDPSocket *sntp;
static volatile unsigned long sntptime;
extern EthernetNetIf eth;

int createSntpRequest (char *buf) {
    struct SNTPPacket *sntp;

    sntp = (struct SNTPPacket *)buf;
    memset(sntp, 0, sizeof(struct SNTPPacket));
    sntp->info = 0x1b; // Ver.3, client
    sntp->txTm_s = htonl(NTP_TIMESTAMP_DELTA + time(NULL));

    return sizeof(struct SNTPPacket);
}

int getSntpResponse (const char *buf, uint32_t *tim) {
    struct SNTPPacket *sntp;
//    uint32_t now;
//    long int delay, offset;

    sntp = (struct SNTPPacket *)buf;
    if ((sntp->info & 0x3f) == 0x1c || (sntp->info & 0x3f) == 0x24) {
        // Ver.3or4, Server

/*
        now = htonl(NTP_TIMESTAMP_DELTA + time(NULL));
        delay = (now - sntp->origTm_s) - (sntp->rxTm_s - sntp->txTm_s);
        offset = ((sntp->rxTm_s - sntp->origTm_s) + (sntp->txTm_s - now));

        *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA + (delay / 2);
*/
        *tim = ntohl(sntp->txTm_s) - NTP_TIMESTAMP_DELTA;
#ifdef DEBUG
        printf("now %08x\r\n", ntohl(now));
        printf("ref %08x\r\n", ntohl(sntp->refTm_s));
        printf("orig %08x\r\n", ntohl(sntp->origTm_s));
        printf("rx %08x\r\n", ntohl(sntp->rxTm_s));
        printf("tx %08x\r\n", ntohl(sntp->txTm_s));
//        printf("delay %d / offset %d\r\n", delay, offset);
#endif
        return 0;
    }

    return -1;
}

void isr_sntp (UDPSocketEvent e) {
    char buf[200];
    Host dsthost;
    int len;

    if (e == UDPSOCKET_READABLE) {
        // recv responce;
        len = sntp->recvfrom(buf, sizeof(buf), &dsthost);
#ifdef DEBUG
        for (int i = 0; i < len; i ++) {
            printf(" %02x", (unsigned char)buf[i]);
        }
        puts("\r");
#endif
        if (len >= sizeof(struct SNTPPacket) && ! sntptime) {
            getSntpResponse(buf, (uint32_t*)&sntptime);
        }
    }
}

int ntpdate (const char* name, uint32_t *tim) {
//    UDPSocketErr err;
    Host sntphost;
    char buf[100];
    int i, len;
    DNSRequest dns;
    DNSRequestErr dnsErr;

    sntptime = 0;
    sntp = new UDPSocket;
    sntp->setOnEvent(isr_sntp);

    // send request
    sntphost.setName(name);
    sntphost.setPort(NTP_PORT);
    dnsErr = dns.resolve(&sntphost);
    if (dnsErr != DNS_OK) goto exit;
    len = createSntpRequest(buf);
#ifdef DEBUG
    for (int i = 0; i < len; i ++) {
        printf(" %02x", (unsigned char)buf[i]);
    }
    puts("\r");
#endif
    sntp->sendto(buf, len, &sntphost);

    // wait responce
    for (i = 0; i < NTP_TIMEOUT / 10; i ++) {
        if (sntptime) {
            *tim = sntptime;
            Net::poll();
            wait_ms(10);
            Net::poll();
            break;
        }
        if (i % 500 == 499) {
            sntp->sendto(buf, len, &sntphost);
        }
        Net::poll();
        wait_ms(10);
    }

exit:
    sntp->resetOnEvent();
    sntp->close();
    delete sntp;

    return sntptime ? 0 : -1;
}