cynshard / arduino-ntp

A simple ntp library for arduino

This URL has Read+Write access

arduino-ntp / NTP.cpp
100644 139 lines (121 sloc) 3.128 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "WProgram.h"
#include "NTP.h"
 
NTP::NTP(byte address[])
{
    _address[0] = address[0];
    _address[1] = address[1];
    _address[2] = address[2];
    _address[3] = address[3];
}
 
NTP::~NTP()
{
}
 
unsigned long NTP::get_gmt()
{
    call();
    return _send_timestamp;
}
 
unsigned long NTP::get_unix_gmt()
{
    call();
    unsigned long seventy_years = 2208988800UL;
    return _send_timestamp - seventy_years;
}
 
unsigned long NTP::get_unix_tz(int offset)
{
    unsigned long t = get_unix_gmt();
    return t + (offset * 60 * 60);
}
 
int NTP::get_leap_indicator(byte b)
{
    return b >> 6;
}
 
int NTP::get_version(byte b)
{
    byte c = b << 2;
    return c >> 5;
}
 
int NTP::get_mode(byte b)
{
    byte c = b << 5;
    return c >> 5;
}
 
unsigned long NTP::get_ulong()
{
    unsigned long ulong = (unsigned long)UdpBytewise.read() << 24;
    ulong |= (unsigned long)UdpBytewise.read() << 16;
    ulong |= (unsigned long)UdpBytewise.read() << 8;
    ulong |= (unsigned long)UdpBytewise.read();
    return ulong;
}
 
unsigned long NTP::get_time_discard_precision()
{
    unsigned long time = get_ulong();
    // we are going to discard the sub-second stuff
    UdpBytewise.read();
    UdpBytewise.read();
    UdpBytewise.read();
    UdpBytewise.read();
    return time;
}
 
void NTP::write_n(int what, int how_many)
{
    for( int i = 0; i < how_many; i++ )
        UdpBytewise.write(what);
}
 
int NTP::send_ntp_packet()
{
    UdpBytewise.begin(123);
    UdpBytewise.beginPacket(_address, 123);
    // LI, Version, Mode
    UdpBytewise.write(B11100011);
    // Stratum
    UdpBytewise.write(0);
    // Polling Interval
    UdpBytewise.write(6);
    // Peer Clock Precision
    UdpBytewise.write(0xEC);
    // Root Delay
    write_n(0, 4);
    // Root Dispersion
    write_n(0, 4);
    // Reference Clock Id
    UdpBytewise.write(49);
    UdpBytewise.write(0x4E);
    UdpBytewise.write(49);
    UdpBytewise.write(52);
    // Reference CLock Update Time
    write_n(0, 8);
    // Originate Time Stamp
    write_n(0, 8);
    // Receive Time Stamp
    write_n(0, 8);
    // Transmit Time Stamp
    write_n(0, 8);
    // End
    return UdpBytewise.endPacket();
}
 
void NTP::call()
{
    send_ntp_packet();
 
    delay(1000);
 
    if ( UdpBytewise.available() ) {
        byte first_byte = UdpBytewise.read();
        _leap_indicator = get_leap_indicator(first_byte);
        _version = get_version(first_byte);
        _mode = get_mode(first_byte);
        _stratum = (int)UdpBytewise.read();
        _polling_interval = 1 << ((int)UdpBytewise.read());
        _precision = (char)UdpBytewise.read();
        _delay_interval = (float) get_ulong();
        _dispersion = (float) get_ulong();
 
        _ref_clock_id[0] = UdpBytewise.read();
        _ref_clock_id[1] = UdpBytewise.read();
        _ref_clock_id[2] = UdpBytewise.read();
        _ref_clock_id[3] = UdpBytewise.read();
 
        _ref_clock_update_time = get_time_discard_precision();
        _orig_timestamp = get_time_discard_precision();
        _recv_timestamp = get_time_discard_precision();
        _send_timestamp = get_time_discard_precision();
    }
}