Tiny SNTP(NTP) Client

Dependencies:   EthernetNetIf mbed

Files at this revision

API Documentation at this revision

Comitter:
okini3939
Date:
Thu Jul 21 17:53:11 2011 +0000
Child:
1:d3c1871be1e9
Commit message:

Changed in this revision

EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
TinySNTP.cpp Show annotated file Show diff for this revision Revisions of this file
TinySNTP.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Thu Jul 21 17:53:11 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/EthernetNetIf/#bc7df6da7589
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TinySNTP.cpp	Thu Jul 21 17:53:11 2011 +0000
@@ -0,0 +1,143 @@
+/*
+ * 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[100];
+    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)) {
+            getSntpResponse(buf, (uint32_t*)&sntptime);
+        }
+    }
+}
+
+int ntpdate (const char* name, uint32_t *tim) {
+    UDPSocketErr err;
+    Host myhost, sntphost;
+    char buf[100];
+    int i, len;
+    DNSRequest dns;
+    DNSRequestErr dnsErr;
+
+    sntptime = 0;
+    sntp = new UDPSocket;
+    sntp->setOnEvent(isr_sntp);
+
+    // bind
+    myhost.setIp(eth.getIp());
+    myhost.setPort(NTP_SRC_PORT);
+    err = sntp->bind(myhost);
+    if (err != UDPSOCKET_OK) goto exit;
+
+    // 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;
+            break;
+        }
+        if (i % 500 == 499) {
+            sntp->sendto(buf, len, &sntphost);
+        }
+        Net::poll();
+        wait_ms(10);
+    }
+
+exit:
+    sntp->resetOnEvent();
+    delete sntp;
+
+    return sntptime ? 0 : -1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TinySNTP.h	Thu Jul 21 17:53:11 2011 +0000
@@ -0,0 +1,53 @@
+/*
+ * 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
+ */
+
+#ifndef TinySNTP_h
+#define TinySNTP_h
+
+#include <inttypes.h>
+
+#define DEBUG
+
+#define NTP_PORT 123
+#define NTP_SRC_PORT 50420
+#define NTP_TIMESTAMP_DELTA 2208988800ull
+#define NTP_TIMEOUT 15000 // ms
+
+struct SNTPPacket {
+    uint8_t info;
+    uint8_t stratum;
+    uint8_t poll;
+    uint8_t precision;
+
+    uint32_t rootDelay;
+    uint32_t rootDispersion;
+    uint32_t refId;
+
+    uint32_t refTm_s;
+    uint32_t refTm_f;
+    uint32_t origTm_s;
+    uint32_t origTm_f;
+    uint32_t rxTm_s;
+    uint32_t rxTm_f;
+    uint32_t txTm_s;
+    uint32_t txTm_f;
+} __attribute__((packed));
+
+int createSntpRequest (char*);
+int getSntpResponse (const char*, uint32_t *time);
+
+/** resolv host by name
+ * @param name NTP server
+ * @param tim time (return)
+ * @return 0:success, -1:failue
+ */
+int ntpdate (const char* name, uint32_t *tim);
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Jul 21 17:53:11 2011 +0000
@@ -0,0 +1,32 @@
+#include "mbed.h"
+#include "EthernetNetIf.h"
+#include "TinySNTP.h"
+
+DigitalOut myled(LED1);
+Serial pc(USBTX, USBRX);
+EthernetNetIf eth;
+
+int main () {
+    EthernetErr ethErr;
+    uint32_t t;
+    struct tm *tm_buf;
+    time_t seconds = time(NULL);
+
+    myled = 1;
+    printf("Time as a string = %s\r\n", ctime(&seconds));
+
+    ethErr = eth.setup();
+    if(ethErr) {
+        return -1;
+    }
+
+    ntpdate("ntp1.sakura.ad.jp", &t);
+
+    t += 60 * 60 * 9; // JST
+    tm_buf = localtime((time_t*)&t);
+    printf("now: %04d/%02d/%02d %02d:%02d:%02d\n", 1900 + tm_buf->tm_year, tm_buf->tm_mon + 1, tm_buf->tm_mday,
+                            tm_buf->tm_hour, tm_buf->tm_min, tm_buf->tm_sec);
+
+    myled = 0;
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Jul 21 17:53:11 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/63bcd7ba4912