Timo Karppinen / Mbed OS UDP_RoundTripDelay_OS6_K64F

Dependencies:   ntp-client

main.cpp

Committer:
timo_k2
Date:
2021-04-24
Revision:
5:837b2680bebb
Parent:
4:4118d38b68e1

File content as of revision 5:837b2680bebb:

/*
 * Copyright (c) 2006-2020 Arm Limited and affiliates.
 * SPDX-License-Identifier: Apache-2.0
 ***********************************
 * Round trip delay meter.
 * Mbed OS Timer with microsecond precision used for a stopwatch.  
 * A microcontroller board with an Ethernet interface.
 * For measuring documentation the date and time is taken from a NTP server.
 * An other microcontroller with "Round trip echo" will be needed. 
 * NXP FRDM-K64F used for testing.
 *   
 * Timo Karppinen 24.4.2021
 ***********************************/
#include "mbed.h"
#include "EthernetInterface.h"
#include "ntp-client/NTPClient.h"

#define REMOTE_PORT 5000
#define LOCAL_PORT 5001
#define BUFF_SIZE 512  // test with 32, 128, 512

//Network interface
EthernetInterface net;

//Threads
    Thread recv_thread;

// UDP
SocketAddress clientUDP;  // Client on remote device. IP address from incoming message.
UDPSocket serverUDP;   // UDP server in this device

//NTP server is a time server used for delivering timing information for networks.
//Returns 32 bits for seconds and 32 bits for fraction of seconds. 
//#define ntpAddress "2.pool.ntp.org"
#define ntpAddress "time.mikes.fi"  // The VTT Mikes in Helsinki
#define ntpPort 123
// The address and port number can be replaced with the ones for the local 
// network NTP server. 

// Functions
//time_t getNTP();
void udpReceive( void );
void udpSend( int ii );

DigitalIn sw2(SW2);     // sw2 on K64F, button pressed = FALSE
DigitalOut led2(LED2);  // RGB LED on K64F, FALSE = Green
int sw2state = 0;
int sw2old = 1;

char in_data[BUFF_SIZE]; // 512 taken as max message size
int newDatagram = 0;
int newDatagramOld = 0;
//time_t timeNTP = 0;

Timer stopwatch; // Timer is an operating system class since OS 6.0
Timer armedFor;
    
int main() {
    printf("\nRound trip delay in UDP messaging (using Ethernet)\n");
    
    //Bring up the network interface
    //eth.set_network(IP_Adress,MASK, GATEWAY); // leave out if using DHCP
    net.set_network("192.168.1.10","255.255.252.0","192.168.1.1");
    net.connect();
    
    // Show network address
    SocketAddress netAddress;
    net.get_ip_address(&netAddress);
    printf("\n\n NTPClient - UDPServer IP Address: %s\n", netAddress.get_ip_address() ? netAddress.get_ip_address():"None");
    
   
    // NTP client 
    
    //printf("Message to NTP time server...\n");
    //timeNTP = getNTP();
    //printf("Current time in day month hour.min.sec year is  %s\r\n", ctime(&timeNTP));
    
    // UDP server 
    
    serverUDP.open(&net);
    int err = serverUDP.bind(LOCAL_PORT);
    printf("Port status is: %d\n",err);
    
    recv_thread.start(udpReceive);
    printf("Listening has been started at port number %d\n", LOCAL_PORT);
    printf("The operator for the \"Echo board\" should send a message!\n ");
    printf("The IP will be taken from the incoming message\n");
    printf("Press the blue switch after receiving \"Echo server listening\"\n");
  
    while(1) {  
    sw2state = sw2.read();
    printf( "\nsw2  %d  -  Push for sending Echo Request\n", sw2state); 
    
    if((sw2state == 0)&&(sw2state != sw2old)) {   // Note! Checking for FALSE sw
      led2.write(1);
      for ( int i=0; i < 5; ++i){
        armedFor.reset();   // reset timer to zero
        stopwatch.reset();   // reset stopwatch timer to zero
        //timeNTP = getNTP();
        ThisThread::sleep_for(10ms); //time for resetting
        armedFor.start();
        //stopwatch.start();  // moved to udpSend subroutine
        udpSend(i);
        
    
        // Start polling for the incoming "Echo" UDP datagram   
        while ( armedFor.elapsed_time().count() <2000000 ){
            if((newDatagram == 1)&&(newDatagram != newDatagramOld)){
                stopwatch.stop(); 
                char firstChar;
                firstChar = in_data[0];
                printf( "\nfirstChar: %s\n", &firstChar);
                ThisThread::sleep_for(120ms); // waiting for print buffer, 100 ms was just too short
                for (int k =0; k < BUFF_SIZE; k++){
                    in_data[k] = 0;
                    } 
                // printing for testing. Replace with writing once to a SD memory card.
                //printf("Measured at ( day month hour.min.sec year ) %s\r\n", ctime(&timeNTP));
                printf("The time taken was %llu microseconds\n", stopwatch.elapsed_time().count());
            } // if new datagram
            newDatagramOld = newDatagram; //Reading the stopwatch once only 
            newDatagram = 0;  
        } // while armed
        ThisThread::sleep_for(70ms); // Delay of 10ms + 120ms + 70ms = 200ms
      } //for i loop
        
        // printing for testing. Replace with writing once to a SD memory card.
        //printf("Measured at ( day month hour.min.sec year ) %s\r\n", ctime(&timeNTP));
        //printf("The time taken was %llu microseconds\n", stopwatch.elapsed_time().count()); 
    } // if sw2
    sw2old = sw2state; // Once only with pushing the button as long as you like.
    led2.write(0);
    armedFor.stop();
    stopwatch.stop();  // Stop the stopwatch if we did not receive the echo.
    
    ThisThread::sleep_for(1000ms);
    } // while loop
} // main

// The functions
  
time_t getNTP() {
    NTPClient ntp(&net);
    ntp.set_server(ntpAddress, ntpPort);
    time_t timestamp = ntp.get_timestamp();
    if (timestamp < 0) {
        printf("An error occurred when getting the time. Code: %u\r\n", timestamp);
    } 
    else {     // the printings for testing only!
        printf("The timestamp seconds from the NTP server in\r\n  32 bit hexadecimal number is %X\r\n", timestamp);
        printf("  decimal number is %u\r\n", timestamp);
        timestamp += (60*60*2);  //  GMT +2  for Finland for the winter time.
        printf("Current time is %s\r\n", ctime(&timestamp));
    } 
    return timestamp; 
}
    
void udpReceive()
{
    int bytes;
    while(1) {
        bytes = serverUDP.recvfrom(&clientUDP, &in_data, 512); // 512 as largest possible
        newDatagram = 1;    // set this before using time for printing
        ThisThread::sleep_for(50ms); // waiting for the print buffer
        printf("bytes received: %d\n",bytes);
        printf("string: %s\n",in_data);
        printf("client address: %s\n", clientUDP.get_ip_address());
        }
}

void udpSend(int ii)
{
        int BUFF_SIZE_NOW;
        switch(ii){
            case 0:
            BUFF_SIZE_NOW = BUFF_SIZE/16;
            break;
            case 1:
            BUFF_SIZE_NOW = BUFF_SIZE/8;
            break;
            case 2:
            BUFF_SIZE_NOW = BUFF_SIZE/4;
            break;
            case 3:
            BUFF_SIZE_NOW = BUFF_SIZE/2;
            break;
            case 4:
            BUFF_SIZE_NOW = BUFF_SIZE;
            break;
        }
        char out_data[BUFF_SIZE_NOW];
        snprintf(out_data, BUFF_SIZE_NOW, "UDP message for getting the Echo" );
        printf("\nSending out: %s\n", out_data);
        printf("with %d" , sizeof(out_data));
        printf(" data bytes in UDP datagram\n");
        clientUDP.set_port(REMOTE_PORT);
        stopwatch.start();  // starting the stopwatch after preparations are done
        serverUDP.sendto(clientUDP, out_data, sizeof(out_data)); 
}