Multicast.c

Multicast.c example details
Multicast details

/***************************************************************************//**
@file multicast.c
@brief UDP multicast test program
@verbatim
_ _ _
__| | ___(_) ____ _ __ | |_
/ _` | / __| |/ _` | '_ \| __|
| (_| | _ \__ \ | (_| | | | | |_
\__,_|(_) ___/_|\__, |_| |_|\__|
Signalprocessing |___/ Technology
@endverbatim
@author D.SignT GmbH & Co. KG, Claus Hermbusche
@date 2019-06-03
@anchor MULTICASTEX
Simple DSP program for receiving multicast UDP - packets. The received
data is used to switch the LED's on and off. The DSP IP address is
configured to 192.168.168.200. The multicast group is 239.255.1.1 port 5555.
@cond Software License Agreement
Copyright (C) 2001-2019 D.SignT GmbH & Co. KG - http://www.dsignt.de
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the
distribution.
Neither the name of D.SignT GmbH & Co. KG nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
Disclaimer
THIS SOFTWARE IS PROVIDED BY D.SIGNT GMBH & CO. KG "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL D.SIGNT GMBH & CO. KG BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@endcond
*******************************************************************************/
/*******************************************************************************
include stdtypes.h to avoid data type mismatch
*******************************************************************************/
/*******************************************************************************
include Runtime Source
*******************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <inttypes.h>
#include <time.h>
#include <string.h>
/*******************************************************************************
network support functions
*******************************************************************************/
#include <Libs/NETlib/net.h> /* D.Module network support */
/*******************************************************************************
board specific functions
*******************************************************************************/
#include <BoardSupport/inc/BoardSpecific.h> /* board support functions */
/*******************************************************************************
common support functions
*******************************************************************************/
#include <Common/Common.h> /* on exit function */
#include <Common/uartio.h> /* UART support */
#include <Common/timer.h> /* timer setting */
#include <Common/CPrintf.h> /* CPrintf defines */
/*******************************************************************************
network configuration
*******************************************************************************/
#include <BoardSupport/config/netconfig.c> /* network configuration */
#ifdef __cplusplus
extern "C" {
#endif /* !__cplusplus */
/*******************************************************************************
local prototypes
*******************************************************************************/
#pragma CODE_SECTION(udp_call_back , ".commontext")
int32_t udp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec);
#ifdef __cplusplus
} // extern "C"
#endif
/*******************************************************************************
* *
* DEFINES *
* *
*******************************************************************************/
/*******************************************************************************
Multicast configuration
*******************************************************************************/
#define MCAST_IP_ADDR "239.255.1.1" /* organisations local multicast */
#define MCAST_IP_ADDR2 "239.255.1.2" /* organisations local multicast */
#define MCAST_PORT 5555
#define MCAST_PORT2 5556
#define DSP_PORT 5031
/*******************************************************************************
command list
*******************************************************************************/
#define CMD_LED_INIT 1
#define CMD_LED_ON 2
#define CMD_LED_OFF 3
/*******************************************************************************
* *
* GLOBALS *
* *
*******************************************************************************/
/*******************************************************************************
program name
*******************************************************************************/
char *program_name = "multicast";
SOCKET *udp_socket; /* socket descriptor */
char *udp_data; /* data buffer for socket */
/*******************************************************************************
* *
* FUNCTIONS *
* *
*******************************************************************************/
/*******************************************************************************
@brief This function is called each time new data is received
@param so - socket
@param data - pointer to received data
@param len - received data length
@param ec - error code
@return SOCKET_CB_OK - if message processed
@return SOCKET_CB_CLOSED - if socket was closed
*******************************************************************************/
int32_t udp_call_back (SOCKET *so, void *data, uint32_t len, uint32_t ec)
{
/***************************************************************************
locals
***************************************************************************/
char *udp_data = (char *)data;
int32_t data_length; // net_recv_event_handler() return parameter
char buffer[20]; /* small buffer for ip-address conversion */
/***************************************************************************
suppress unused parameter warning
***************************************************************************/
UNREFERENCED_PARAMETER(ec); // handled in net_recv_event_handler()
/***************************************************************************
Check events
Use net_recv_event_handler() to determine the data length waiting in the
receive buffer
If NULL is passed as pLog parameter, no message is printed to output.
CPrintf is used here for demonstration purpose only. You shouldn't use
long blocking operation in callback functions.
***************************************************************************/
data_length = net_recv_event_handler (so, CPrintf); /* with messages */
// data_length = net_recv_event_handler (so, NULL); /* without messages */
/***************************************************************************
net_recv_event_handler() returns the amount of data waiting in the buffer
***************************************************************************/
if (data_length)
{
/*******************************************************************
a new command received:
1. byte: command
2. byte: led number
*******************************************************************/
switch ( udp_data[0] )
{
break;
case CMD_LED_ON:
LED_on(udp_data[1]);
break;
LED_off(udp_data[1]);
break;
default :
/* no more commands defined*/
break;
} // switch
/*******************************************************************
print some more details on received data
CPrintf is used here for demonstration purpose only. You shouldn't
use long blocking operation in callback functions.
*******************************************************************/
if (IS_MULTICAST(so-> mc_group_addr))
{
/***************************************************************
when this is a multicast UDP packet, so-> dest_addr, so-> src_addr
and so-> src_port, so-> dest_port are invalid! Use a new offset
to access valid connection data:
***************************************************************/
CPuts (" New multicast data received\r\n");
CPrintf (" Destination Address: %s\r\n", inet_ntoa ( so-> mc_dest_addr, buffer));
CPrintf (" Multicast Group Address: %s\r\n", inet_ntoa ( so-> mc_group_addr, buffer));
CPrintf (" Destination Port: %d\r\n", so-> mc_dest_port);
CPrintf (" Source Multicast Port: %d\r\n", so-> mc_src_port);
}
else
{
CPrintf (" New data received\r\n"
" Destination Address: %s\r\n"
" Source Address: %s\r\n"
" Destination Port: %d\r\n"
" Source Port: %d\r\n\n",
inet_ntoa ( so-> dest_addr, buffer),
inet_ntoa ( so-> src_addr, buffer),
so-> dest_port,
so-> src_port);
}
#ifdef USE_UART_CONTROL
udp_data[len] = 0x0; /* string termination */
CPuts ( udp_data); /* send string back over UART */
CPuts ( CRLF);
#endif
}
/***************************************************************************
return true, if message processed
***************************************************************************/
return (SOCKET_CB_OK);
}
/*******************************************************************************
@brief Main application
@param -
@return never
*******************************************************************************/
#pragma CODE_SECTION(main , ".commontext");
int main ( void )
{
/***************************************************************************
locals
***************************************************************************/
int main_loop = 1; /* main loop switch, set to 0 to exit */
timeval stamp1, stamp2, delta; /* used to determine startup time */
/***************************************************************************
initialize application (e.g. timer clocks, PLL settings, EMIF etc.)
(ref. \Common\Common.c)
***************************************************************************/
/***************************************************************************
select output device for CPrintf (ref. \Common\cprintf.c)
possible settings:
CPRINTF_UART_OUTPUT -> output to UART
CPRINTF_CCS_OUTPUT -> output to CCS
CPRINTF_UART_OUTPUT | CPRINTF_CCS_OUTPUT -> output to UART and CCS
***************************************************************************/
/***************************************************************************
print a start up message
***************************************************************************/
/**************************************************************************/
// CPrintfProgress (" Heap check ");
// at least 0x2000 bytes required for this app
/**************************************************************************/
// CPrintfProgressSuccess();
/***************************************************************************
malloc space for data
***************************************************************************/
CPrintfProgress (" Try to allocate data buffer ");
udp_data = (char *) malloc (UDP_MAX_PACKET_SIZE * sizeof(char));
if ( udp_data == NULL )
{
prg_exit ("out of memory error");
}
/**************************************************************************/
CPrintfProgress (" Setup system time ");
// 1 milli seconds resolution
/**************************************************************************/
CPrintf (" *** timer %d mapped to CPU int %d ***\r\n",
/**************************************************************************/
CPrintfProgress (" Enable interrupts ");
/**************************************************************************/
/**************************************************************************/
CPrintfProgress (" Start system timer ");
/**************************************************************************/
CPrintf (" *** timer %d running at %"PRId32" Hz ***\r\n", SystemTimerDev, RES_SECONDS/GetSystemTimerRes());
/***************************************************************************
measure network initialization time
***************************************************************************/
stamp1 = GetTimeStamp();
/**************************************************************************/
CPrintfProgress (" Initialize network ");
/**************************************************************************/
InitializeNetwork ( 64); // 64 bytes for ping
/***************************************************************************
open socket: receive data from any address and port
***************************************************************************/
udp_socket = socket_open (ANY_ADDRESS, /* all addresses */
ANY_PORT, /* destination port */
DSP_PORT, /* source port */
DATATYPE_CHAR, /* data type char */
UDP_INIT_FUNC); /* udp protocol */
{
prg_exit ("socket_open() error"); /* possibly insufficient heap */
} // if
/***************************************************************************
define callback function for received UDP packets
***************************************************************************/
stamp2 = GetTimeStamp();
tv_interval (&delta, &stamp1, &stamp2);
CPuts (" network startup time [sec]: ");
"%"PRId32".%03"PRId32"\r\n"
delta.tv_sec,
delta.tv_usec/1000);
/***************************************************************************
join a multicast group
***************************************************************************/
/***************************************************************************
join another multicast group
***************************************************************************/
// multicast_join_group (udp_socket, MCAST_IP_ADDR2, MCAST_PORT2);
/***************************************************************************
main program loop: set main_loop to 0 to exit loop
***************************************************************************/
CPuts ("\r\n Entering main loop ...\r\n");
while ( main_loop )
{
/***********************************************************************
process net_isq()
***********************************************************************/
net_isq (); // process ISQ
/***********************************************************************
monitor link status
***********************************************************************/
/***********************************************************************
try to detect IP assignment
if DHCP is used, the assigned IP address may change
***********************************************************************/
/***********************************************************************
show that the program is running, perform symbol animation
***********************************************************************/
}
/***************************************************************************
exit program, shut down peripherals
***************************************************************************/
return (0);
}