Pico Led Controller 1.0.3
A project to control LEDs using Raspberry Pi Pico W
ntp.c File Reference
#include "ntp.h"
#include <string.h>
#include <time.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "lwip/dns.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"

Go to the source code of this file.

Functions

static void ntp_result (NTP_T *state, int status, time_t *result)
 
static void ntp_request (NTP_T *state)
 
static int64_t ntp_failed_handler (alarm_id_t id, void *user_data)
 
static void ntp_dns_found (const char *hostname, const ip_addr_t *ipaddr, void *arg)
 
static void ntp_recv (void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
 
static NTP_Tntp_init (void)
 
void ntp_deinit (void)
 NTP deinit. More...
 
void ntp_update_time (void)
 NTP update time. More...
 

Variables

volatile struct tm * utc = NULL
 UTC time struct. More...
 
volatile struct tm * current_utc = NULL
 UTC time struct. More...
 

Function Documentation

◆ ntp_deinit()

void ntp_deinit ( void  )

NTP deinit.

Function de-initializes the NTP.

Definition at line 114 of file ntp.c.

115 {
116  if (utc)
117  {
118  free((void*)utc);
119  utc = NULL;
120  }
121 }
volatile struct tm * utc
UTC time struct.
Definition: ntp.c:13

References utc.

Referenced by main().

◆ ntp_dns_found()

static void ntp_dns_found ( const char *  hostname,
const ip_addr_t *  ipaddr,
void *  arg 
)
static

Definition at line 56 of file ntp.c.

57 {
58  NTP_T *state = (NTP_T*)arg;
59  if (ipaddr)
60  {
61  state->ntp_server_address = *ipaddr;
62  printf("NTP address %s\n", ipaddr_ntoa(ipaddr));
63  ntp_request(state);
64  }
65  else
66  {
67  printf("NTP DNS request failed\n");
68  ntp_result(state, -1, NULL);
69  }
70 }
static void ntp_result(NTP_T *state, int status, time_t *result)
Definition: ntp.c:16
static void ntp_request(NTP_T *state)
Definition: ntp.c:36
NTP struct.
Definition: ntp.h:35
ip_addr_t ntp_server_address
Definition: ntp.h:36

References ntp_request(), ntp_result(), and NTP_T_::ntp_server_address.

Referenced by ntp_update_time().

◆ ntp_failed_handler()

static int64_t ntp_failed_handler ( alarm_id_t  id,
void *  user_data 
)
static

Definition at line 48 of file ntp.c.

49 {
50  NTP_T* state = (NTP_T*)user_data;
51  printf("NTP request failed\n");
52  ntp_result(state, -1, NULL);
53  return 0;
54 }

References ntp_result().

Referenced by ntp_update_time().

◆ ntp_init()

static NTP_T* ntp_init ( void  )
static

Definition at line 95 of file ntp.c.

96 {
97  NTP_T *state = (NTP_T*)calloc(1, sizeof(NTP_T));
98  if (!state)
99  {
100  printf("Failed to allocate state\n");
101  return NULL;
102  }
103  state->ntp_pcb = udp_new_ip_type(IPADDR_TYPE_ANY);
104  if (!state->ntp_pcb)
105  {
106  printf("Failed to create PCB\n");
107  free(state);
108  return NULL;
109  }
110  udp_recv(state->ntp_pcb, ntp_recv, state);
111  return state;
112 }
static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
Definition: ntp.c:72
struct udp_pcb * ntp_pcb
Definition: ntp.h:38

References NTP_T_::ntp_pcb, and ntp_recv().

Referenced by ntp_update_time().

◆ ntp_recv()

static void ntp_recv ( void *  arg,
struct udp_pcb *  pcb,
struct pbuf *  p,
const ip_addr_t *  addr,
u16_t  port 
)
static

Definition at line 72 of file ntp.c.

73 {
74  NTP_T *state = (NTP_T*)arg;
75  uint8_t mode = pbuf_get_at(p, 0) & 0x7;
76  uint8_t stratum = pbuf_get_at(p, 1);
77 
78  if (ip_addr_cmp(addr, &state->ntp_server_address) && port == NTP_PORT && p->tot_len == NTP_MSG_LEN &&mode == 0x4 && stratum != 0)
79  {
80  uint8_t seconds_buf[4] = {0};
81  pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40);
82  uint32_t seconds_since_1900 = seconds_buf[0] << 24 | seconds_buf[1] << 16 | seconds_buf[2] << 8 | seconds_buf[3];
83  uint32_t seconds_since_1970 = seconds_since_1900 - NTP_DELTA;
84  time_t epoch = seconds_since_1970;
85  ntp_result(state, 0, &epoch);
86  }
87  else
88  {
89  printf("Invalid NTP response\n");
90  ntp_result(state, -1, NULL);
91  }
92  pbuf_free(p);
93 }
#define NTP_PORT
Definition: ntp.h:16
#define NTP_DELTA
Definition: ntp.h:17
#define NTP_MSG_LEN
Definition: ntp.h:15

References NTP_DELTA, NTP_MSG_LEN, NTP_PORT, ntp_result(), and NTP_T_::ntp_server_address.

Referenced by ntp_init().

◆ ntp_request()

static void ntp_request ( NTP_T state)
static

Definition at line 36 of file ntp.c.

37 {
38  cyw43_arch_lwip_begin();
39  struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, NTP_MSG_LEN, PBUF_RAM);
40  uint8_t *req = (uint8_t *) p->payload;
41  memset(req, 0, NTP_MSG_LEN);
42  req[0] = 0x1b;
43  udp_sendto(state->ntp_pcb, p, &state->ntp_server_address, NTP_PORT);
44  pbuf_free(p);
45  cyw43_arch_lwip_end();
46 }

References NTP_MSG_LEN, NTP_T_::ntp_pcb, NTP_PORT, and NTP_T_::ntp_server_address.

Referenced by ntp_dns_found(), and ntp_update_time().

◆ ntp_result()

static void ntp_result ( NTP_T state,
int  status,
time_t *  result 
)
static

Definition at line 16 of file ntp.c.

17 {
18  if (status == 0 && result)
19  {
20  // *result += TIMEZONE_OFFSET;
21  if (!utc)
22  utc = gmtime(result);
23  current_utc = gmtime(result);
24  printf("Got NTP response: %02d/%02d/%04d %02d:%02d:%02d\n", current_utc->tm_mday, current_utc->tm_mon + 1, current_utc->tm_year + 1900, current_utc->tm_hour, current_utc->tm_min, current_utc->tm_sec);
25  }
26 
27  if (state->ntp_resend_alarm > 0)
28  {
29  cancel_alarm(state->ntp_resend_alarm);
30  state->ntp_resend_alarm = 0;
31  }
32  state->ntp_test_time = make_timeout_time_ms(NTP_TEST_TIME);
33  state->dns_request_sent = false;
34 }
volatile struct tm * current_utc
UTC time struct.
Definition: ntp.c:14
#define NTP_TEST_TIME
Definition: ntp.h:18
absolute_time_t ntp_test_time
Definition: ntp.h:39
bool dns_request_sent
Definition: ntp.h:37
alarm_id_t ntp_resend_alarm
Definition: ntp.h:40

References current_utc, NTP_T_::dns_request_sent, NTP_T_::ntp_resend_alarm, NTP_TEST_TIME, NTP_T_::ntp_test_time, and utc.

Referenced by ntp_dns_found(), ntp_failed_handler(), ntp_recv(), and ntp_update_time().

◆ ntp_update_time()

void ntp_update_time ( void  )

NTP update time.

Function updates the NTP time.

Definition at line 123 of file ntp.c.

124 {
125  NTP_T *state = ntp_init();
126  if (!state)
127  return;
128  if (absolute_time_diff_us(get_absolute_time(), state->ntp_test_time) < 0 && !state->dns_request_sent)
129  {
130  state->ntp_resend_alarm = add_alarm_in_ms(NTP_RESEND_TIME, ntp_failed_handler, state, true);
131  cyw43_arch_lwip_begin();
132  int err = dns_gethostbyname(NTP_SERVER, &state->ntp_server_address, ntp_dns_found, state);
133  cyw43_arch_lwip_end();
134 
135  state->dns_request_sent = true;
136  if (err == ERR_OK)
137  ntp_request(state);
138  else if (err != ERR_INPROGRESS)
139  {
140  printf("DNS request failed\n");
141  ntp_result(state, -1, NULL);
142  }
143  }
144  free(state);
145 }
static int64_t ntp_failed_handler(alarm_id_t id, void *user_data)
Definition: ntp.c:48
static void ntp_dns_found(const char *hostname, const ip_addr_t *ipaddr, void *arg)
Definition: ntp.c:56
static NTP_T * ntp_init(void)
Definition: ntp.c:95
#define NTP_SERVER
Definition: ntp.h:14
#define NTP_RESEND_TIME
Definition: ntp.h:19

References NTP_T_::dns_request_sent, ntp_dns_found(), ntp_failed_handler(), ntp_init(), ntp_request(), NTP_T_::ntp_resend_alarm, NTP_RESEND_TIME, ntp_result(), NTP_SERVER, NTP_T_::ntp_server_address, and NTP_T_::ntp_test_time.

Variable Documentation

◆ current_utc

volatile struct tm* current_utc = NULL

UTC time struct.

Struct for the last checked UTC time.

Definition at line 14 of file ntp.c.

Referenced by ntp_result().

◆ utc

volatile struct tm* utc = NULL

UTC time struct.

Struct for the UTC time of program start.

Definition at line 13 of file ntp.c.

Referenced by ntp_deinit(), ntp_result(), and ssi_handler().