<repo_name>MicrochipTech/unicens-bare-metal-sam-v71<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_print.h
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Stucture Printing module                                                               */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#ifndef UCSI_PRINT_H_
#define UCSI_PRINT_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdarg.h>
#include "ucs_api.h"
#include "ucs_cfg.h"
#include "ucs_xrm_cfg.h"

#define UCSI_PRINT_MAX_NODES (UCS_NUM_REMOTE_DEVICES + 1)
#define UCSI_PRINT_MAX_RESOURCES (UCS_XRM_NUM_RESOURCES)

typedef enum
{
    ObjState_Unused,
    ObjState_Build,
    ObjState_Failed
} UCSIPrint_ObjectState_t;

typedef enum
{
    NodeState_NotAvailable,
    NodeState_Ignored,
    NodeState_Available
} UCSIPrint_NodeState_t;

void UCSIPrint_Init(Ucs_Rm_Route_t *pRoutes, uint16_t routesSize, void *tag);
void UCSIPrint_Service(uint32_t timestamp);
void UCSIPrint_SetNetworkAvailable(bool available, uint8_t maxPos);
void UCSIPrint_SetNodeAvailable(uint16_t nodeAddress, uint16_t nodePosAddr, UCSIPrint_NodeState_t nodeState);
void UCSIPrint_SetRouteState(uint16_t routeId, bool isActive, uint16_t connectionLabel);
void UCSIPrint_SetObjectState(Ucs_Xrm_ResObject_t *element, UCSIPrint_ObjectState_t state);
void UCSIPrint_UnicensActivity(void);

/**
 * \brief Callback when ever UNICENS_PRINT needs to be serviced. Call UCSIPrint_Service in next service cycle.
 * \param tag - user pointer given along with UCSIPrint_Init
 */
extern void UCSIPrint_CB_NeedService(void *tag);

/**
 * \brief Callback when ever UNICENS_PRINT forms a human readable message.
 * \param tag - user pointer given along with UCSIPrint_Init
 * \param pMsg - zero terminated human readable string
 */
extern void UCSIPrint_CB_OnUserMessage(void *tag, const char pMsg[]);

#ifdef __cplusplus
}
#endif

#endif
<file_sep>/audio-source/samv71-ucs/src/default_config.c
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Generated Network Configuration                                                        */
/* Generator: xml2struct for Windows V4.4.0                                                       */
/*------------------------------------------------------------------------------------------------*/
#include "ucs_api.h"

uint16_t PacketBandwidth = 12;
uint16_t RoutesSize = 3;
uint16_t NodeSize = 4;

/* Route 1 from source-node=0x200 to sink-node=0x2B0 */
Ucs_Xrm_DefaultCreatedPort_t SrcOfRoute1_DcPort = { 
    UCS_XRM_RC_TYPE_DC_PORT,
    UCS_XRM_PORT_TYPE_MLB,
    0 };
Ucs_Xrm_MlbSocket_t SrcOfRoute1_MlbSocket = { 
    UCS_XRM_RC_TYPE_MLB_SOCKET,
    &SrcOfRoute1_DcPort,
    UCS_SOCKET_DIR_INPUT,
    UCS_MLB_SCKT_SYNC_DATA,
    4,
    0x0A };
Ucs_Xrm_NetworkSocket_t SrcOfRoute1_NetworkSocket = { 
    UCS_XRM_RC_TYPE_NW_SOCKET,
    0x0D00,
    UCS_SOCKET_DIR_OUTPUT,
    UCS_NW_SCKT_SYNC_DATA,
    4 };
Ucs_Xrm_SyncCon_t SrcOfRoute1_SyncCon = { 
    UCS_XRM_RC_TYPE_SYNC_CON,
    &SrcOfRoute1_MlbSocket,
    &SrcOfRoute1_NetworkSocket,
    UCS_SYNC_MUTE_MODE_NO_MUTING,
    0 };
Ucs_Xrm_ResObject_t *SrcOfRoute1_JobList[] = {
    &SrcOfRoute1_DcPort,
    &SrcOfRoute1_MlbSocket,
    &SrcOfRoute1_NetworkSocket,
    &SrcOfRoute1_SyncCon,
    NULL };
Ucs_Xrm_NetworkSocket_t SnkOfRoute1_NetworkSocket = { 
    UCS_XRM_RC_TYPE_NW_SOCKET,
    0x0D00,
    UCS_SOCKET_DIR_INPUT,
    UCS_NW_SCKT_SYNC_DATA,
    4 };
Ucs_Xrm_DefaultCreatedPort_t SnkOfRoute1_DcPort = { 
    UCS_XRM_RC_TYPE_DC_PORT,
    UCS_XRM_PORT_TYPE_MLB,
    0 };
Ucs_Xrm_MlbSocket_t SnkOfRoute1_MlbSocket = { 
    UCS_XRM_RC_TYPE_MLB_SOCKET,
    &SnkOfRoute1_DcPort,
    UCS_SOCKET_DIR_OUTPUT,
    UCS_MLB_SCKT_SYNC_DATA,
    4,
    0x0A };
Ucs_Xrm_SyncCon_t SnkOfRoute1_SyncCon = { 
    UCS_XRM_RC_TYPE_SYNC_CON,
    &SnkOfRoute1_NetworkSocket,
    &SnkOfRoute1_MlbSocket,
    UCS_SYNC_MUTE_MODE_NO_MUTING,
    0 };
Ucs_Xrm_ResObject_t *SnkOfRoute1_JobList[] = {
    &SnkOfRoute1_NetworkSocket,
    &SnkOfRoute1_DcPort,
    &SnkOfRoute1_MlbSocket,
    &SnkOfRoute1_SyncCon,
    NULL };
/* Route 2 from source-node=0x200 to sink-node=0x270 */
Ucs_Xrm_NetworkSocket_t SnkOfRoute2_NetworkSocket = { 
    UCS_XRM_RC_TYPE_NW_SOCKET,
    0x0D00,
    UCS_SOCKET_DIR_INPUT,
    UCS_NW_SCKT_SYNC_DATA,
    4 };
Ucs_Xrm_StrmPort_t SnkOfRoute2_StrmPort0 = { 
    UCS_XRM_RC_TYPE_STRM_PORT,
    0,
    UCS_STREAM_PORT_CLK_CFG_64FS,
    UCS_STREAM_PORT_ALGN_LEFT16BIT };
Ucs_Xrm_StrmPort_t SnkOfRoute2_StrmPort1 = { 
    UCS_XRM_RC_TYPE_STRM_PORT,
    1,
    UCS_STREAM_PORT_CLK_CFG_WILD,
    UCS_STREAM_PORT_ALGN_LEFT16BIT };
Ucs_Xrm_StrmSocket_t SnkOfRoute2_StrmSocket = { 
    UCS_XRM_RC_TYPE_STRM_SOCKET,
    &SnkOfRoute2_StrmPort0,
    UCS_SOCKET_DIR_OUTPUT,
    UCS_STREAM_PORT_SCKT_SYNC_DATA,
    4,
    UCS_STREAM_PORT_PIN_ID_SRXA0 };
Ucs_Xrm_SyncCon_t SnkOfRoute2_SyncCon = { 
    UCS_XRM_RC_TYPE_SYNC_CON,
    &SnkOfRoute2_NetworkSocket,
    &SnkOfRoute2_StrmSocket,
    UCS_SYNC_MUTE_MODE_NO_MUTING,
    0 };
Ucs_Xrm_ResObject_t *SnkOfRoute2_JobList[] = {
    &SnkOfRoute2_NetworkSocket,
    &SnkOfRoute2_StrmPort0,
    &SnkOfRoute2_StrmPort1,
    &SnkOfRoute2_StrmSocket,
    &SnkOfRoute2_SyncCon,
    NULL };
/* Route 3 from source-node=0x200 to sink-node=0x240 */
Ucs_Xrm_NetworkSocket_t SnkOfRoute3_NetworkSocket = { 
    UCS_XRM_RC_TYPE_NW_SOCKET,
    0x0D00,
    UCS_SOCKET_DIR_INPUT,
    UCS_NW_SCKT_SYNC_DATA,
    4 };
Ucs_Xrm_StrmPort_t SnkOfRoute3_StrmPort0 = { 
    UCS_XRM_RC_TYPE_STRM_PORT,
    0,
    UCS_STREAM_PORT_CLK_CFG_64FS,
    UCS_STREAM_PORT_ALGN_LEFT16BIT };
Ucs_Xrm_StrmPort_t SnkOfRoute3_StrmPort1 = { 
    UCS_XRM_RC_TYPE_STRM_PORT,
    1,
    UCS_STREAM_PORT_CLK_CFG_WILD,
    UCS_STREAM_PORT_ALGN_LEFT16BIT };
Ucs_Xrm_StrmSocket_t SnkOfRoute3_StrmSocket = { 
    UCS_XRM_RC_TYPE_STRM_SOCKET,
    &SnkOfRoute3_StrmPort0,
    UCS_SOCKET_DIR_OUTPUT,
    UCS_STREAM_PORT_SCKT_SYNC_DATA,
    4,
    UCS_STREAM_PORT_PIN_ID_SRXA1 };
Ucs_Xrm_SyncCon_t SnkOfRoute3_SyncCon = { 
    UCS_XRM_RC_TYPE_SYNC_CON,
    &SnkOfRoute3_NetworkSocket,
    &SnkOfRoute3_StrmSocket,
    UCS_SYNC_MUTE_MODE_NO_MUTING,
    0 };
Ucs_Xrm_ResObject_t *SnkOfRoute3_JobList[] = {
    &SnkOfRoute3_NetworkSocket,
    &SnkOfRoute3_StrmPort0,
    &SnkOfRoute3_StrmPort1,
    &SnkOfRoute3_StrmSocket,
    &SnkOfRoute3_SyncCon,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest1ForNode270[] = {
    0x00, 0x00, 0x01, 0x01 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request1ForNode270 = {
    0x00,
    0x01,
    0x06C1,
    0x02,
    0x04,
    PayloadRequest1ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response1ForNode270 = {
    0x00,
    0x01,
    0x06C1,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest2ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x1B, 0x80 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request2ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest2ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response2ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest3ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x11, 0xB8 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request3ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest3ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response3ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest4ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x12, 0x60 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request4ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest4ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response4ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest5ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x13, 0xA0 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request5ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest5ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response5ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest6ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x14, 0x48 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request6ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest6ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response6ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest7ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x05, 0x00, 0x64, 0x20, 0x00, 0x89, 0x77, 0x72 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request7ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0D,
    PayloadRequest7ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response7ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest8ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x06, 0x00 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request8ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest8ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response8ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest9ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x02, 0x00, 0x64, 0x05, 0x00 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request9ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0A,
    PayloadRequest9ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response9ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest10ForNode270[] = {
    0x0F, 0x00, 0x00, 0x00, 0x2A, 0x03, 0x00, 0x64, 0x07, 0x01, 0x50 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request10ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x0B,
    PayloadRequest10ForNode270 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response10ForNode270 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST Ucs_Ns_Script_t ScriptsForNode270[] = {
    {
        0,
        &Request1ForNode270,
        &Response1ForNode270
    }, {
        0,
        &Request2ForNode270,
        &Response2ForNode270
    }, {
        0,
        &Request3ForNode270,
        &Response3ForNode270
    }, {
        0,
        &Request4ForNode270,
        &Response4ForNode270
    }, {
        0,
        &Request5ForNode270,
        &Response5ForNode270
    }, {
        0,
        &Request6ForNode270,
        &Response6ForNode270
    }, {
        0,
        &Request7ForNode270,
        &Response7ForNode270
    }, {
        0,
        &Request8ForNode270,
        &Response8ForNode270
    }, {
        0,
        &Request9ForNode270,
        &Response9ForNode270
    }, {
        0,
        &Request10ForNode270,
        &Response10ForNode270
    } };
UCS_NS_CONST uint8_t PayloadRequest1ForNode240[] = {
    0x00, 0x00, 0x01, 0x01 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request1ForNode240 = {
    0x00,
    0x01,
    0x06C1,
    0x02,
    0x04,
    PayloadRequest1ForNode240 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response1ForNode240 = {
    0x00,
    0x01,
    0x06C1,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest2ForNode240[] = {
    0x0F, 0x00, 0x02, 0x0A, 0x18, 0x03, 0x00, 0x64, 0x00, 0x0F, 0x02, 0x01, 0x00, 0x00, 0x02, 0xA5, 0xDF, 0x03, 0x3F, 0x3F, 0x04, 0x02, 0x02, 0x10, 0x40, 0x40, 0x11, 0x00, 0x00, 0x12, 0x00, 0x00, 0x13, 0x00, 0x00, 0x14, 0x00, 0x00 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request2ForNode240 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x26,
    PayloadRequest2ForNode240 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response2ForNode240 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST uint8_t PayloadRequest3ForNode240[] = {
    0x0F, 0x00, 0x02, 0x04, 0x18, 0x03, 0x00, 0x64, 0x20, 0x00, 0x00, 0x21, 0x00, 0x00, 0x22, 0x00, 0x00, 0x23, 0x00, 0x00 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Request3ForNode240 = {
    0x00,
    0x01,
    0x06C4,
    0x02,
    0x14,
    PayloadRequest3ForNode240 };
UCS_NS_CONST Ucs_Ns_ConfigMsg_t Response3ForNode240 = {
    0x00,
    0x01,
    0x06C4,
    0x0C,
    0x00,
    NULL };
UCS_NS_CONST Ucs_Ns_Script_t ScriptsForNode240[] = {
    {
        0,
        &Request1ForNode240,
        &Response1ForNode240
    }, {
        0,
        &Request2ForNode240,
        &Response2ForNode240
    }, {
        0,
        &Request3ForNode240,
        &Response3ForNode240
    } };
Ucs_Signature_t SignatureForNode200 = { 0x200 };
Ucs_Signature_t SignatureForNode2B0 = { 0x2B0 };
Ucs_Signature_t SignatureForNode270 = { 0x270 };
Ucs_Signature_t SignatureForNode240 = { 0x240 };
Ucs_Rm_Node_t AllNodes[] = {
    {
        &SignatureForNode200,
        NULL,
        0
    }, {
        &SignatureForNode2B0,
        NULL,
        0
    }, {
        &SignatureForNode270,
        ScriptsForNode270,
        10
    }, {
        &SignatureForNode240,
        ScriptsForNode240,
        3
    } };
Ucs_Rm_EndPoint_t SourceEndpointForRoute1 = {
    UCS_RM_EP_SOURCE,
    SrcOfRoute1_JobList,
    &AllNodes[0] };
Ucs_Rm_EndPoint_t SinkEndpointForRoute1 = {
    UCS_RM_EP_SINK,
    SnkOfRoute1_JobList,
    &AllNodes[1] };
Ucs_Rm_EndPoint_t SinkEndpointForRoute2 = {
    UCS_RM_EP_SINK,
    SnkOfRoute2_JobList,
    &AllNodes[2] };
Ucs_Rm_EndPoint_t SinkEndpointForRoute3 = {
    UCS_RM_EP_SINK,
    SnkOfRoute3_JobList,
    &AllNodes[3] };
Ucs_Rm_Route_t AllRoutes[] = { {
        &SourceEndpointForRoute1,
        &SinkEndpointForRoute1,
        1,
        0x0010
    }, {
        &SourceEndpointForRoute1,
        &SinkEndpointForRoute2,
        1,
        0x0011
    }, {
        &SourceEndpointForRoute1,
        &SinkEndpointForRoute3,
        1,
        0x0012
    } };
<file_sep>/audio-source/samv71-ucs/src/gmac/gmac_init.h
#ifndef _GMAC_INIT_H_
#define _GMAC_INIT_H_

#include "gmac.h"
#include "gmac_init.h"
#include "gmacb_phy.h"
#include "gmacd.h"
#include "gmii.h"

#ifdef __cplusplus
extern "C" {
#endif
    
void init_gmac(sGmacd  *pGmacd);

#ifdef __cplusplus
}
#endif

#endif
<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_api.h
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Integration Helper Component                                                           */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#ifndef UCSI_H_
#define UCSI_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "ucsi_cfg.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                            Public API                                */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Initializes UNICENS Integration module.
 * \note Must be called before any other function of this component
 *
 * \param pPriv - External allocated memory area for this particular
 *                instance (static allocated or allocated with malloc)
 * \param pTag - Pointer given by the integrator. This pointer will be
 *               returned by any callback function of this component
 */
void UCSI_Init(UCSI_Data_t *pPriv, void *pTag);

/**
 * \brief Runs in programming mode. All nodes will be treated as unknown. 
 *        If the node address of a node is not correct, it will be new programmed.
 * \note This is a special mode. All public functions of this component will not be 
 *       accepted if this mode is set.
 *       Except: UCSI_ProcessRxData, UCSI_Service, UCSI_Timeout, UCSI_ProgramIdentStringRam, UCSI_ProgramIdentStringRom.
 * \note Call UCSI_Init again, to leave this mode.
 *
 * \param pPriv - private data section of this instance
 * \param amountOfNodes - Programming starts only if the found node count in the network is like the given value.
 */
bool UCSI_RunInProgrammingMode(UCSI_Data_t *pPriv, uint8_t amountOfNodes);

/**
 * \brief Executes the given configuration. If already started, all
 *        existing local and remote INIC resources will be destroyed
 * \note All given pointers must stay valid until this callback is
 *       raised: "UCSI_CB_OnStop"
 *
 * \param pPriv - private data section of this instance
 * \param packetBw - The amount of bytes per frame, reserved for Ethernet channel.
 * \param pRoutesList - Reference to a list of routes
 * \param routesListSize - Number of routes in the list
 * \param pNodesList - Reference to the list of nodes
 * \param nodesListSize - Reference to a list of routes
 * \return true, configuration successfully enqueued, false otherwise
 */
bool UCSI_NewConfig(UCSI_Data_t *pPriv,
    uint16_t packetBw, Ucs_Rm_Route_t *pRoutesList, uint16_t routesListSize,
    Ucs_Rm_Node_t *pNodesList, uint16_t nodesListSize);

/**
 * \brief Executes the given script. If already started, all
 *        existing local and remote INIC resources will be destroyed
 * \note pScriptList pointer must stay valid until this callback is
 *       raised: "UCSI_CB_OnStop"
 * \note UCSI_NewConfig must called first, before calling the function
 *
 * \param pPriv - private data section of this instance
 * \param targetAddress - targetAddress - The target node address
 * \param pScriptList - Pointer to the array of scripts
 * \param scriptListLength - Number of scripts in the array
 * \return true, script successfully enqueued, false otherwise
 */
bool UCSI_ExecuteScript(UCSI_Data_t *pPriv, uint16_t targetAddress, Ucs_Ns_Script_t *pScriptList, uint8_t scriptListLength);

/**
 * \brief Offer the received control data from LLD to UNICENS
 * \note Call this function only from single context (not from ISR)
 * \note This function can be called repeated until it return false
 *
 * \param pPriv - private data section of this instance
 * \param pBuffer - Received bytes from MOST control channel
 * \param len - Length of the received data array
 * \return true, if the data could be enqueued for processing, remove
 *         the data from LLD queue in this case.
 *         false, data could not be processed due to lag of resources.
 *         In this case do not discard the data. Offer the same
 *         data again after UCSI_CB_OnServiceRequired was
 *         raised or any time later.
 */
bool UCSI_ProcessRxData(UCSI_Data_t *pPriv,
    const uint8_t *pBuffer, uint32_t len);

/**
 * \brief Gives UNICENS Integration module time to do its job
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 */
void UCSI_Service(UCSI_Data_t *pPriv);


/**
 * \brief Call after timer set by UCSI_CB_OnSetServiceTimer
 *        expired.
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 */
void UCSI_Timeout(UCSI_Data_t *pPriv);

/**
 * \brief Sends an AMS message to the control channel
 *
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 * \param msgId - The AMS message id
 * \param targetAddress - The node / group target address
 * \param pPayload - The AMS payload to be sent
 * \param payloadLen - The length of the AMS payload
 *
 * \return true, if operation was successful. false if the message could not be sent.
 */
bool UCSI_SendAmsMessage(UCSI_Data_t *my, uint16_t msgId, uint16_t targetAddress, uint8_t *pPayload, uint32_t payloadLen);

/**
 * \brief Gets the queued AMS message from UNICENS stack
 *
 * \note Call this function only from single context (not from ISR)
 * \note This function may be called cyclic or when UCSI_CB_OnAmsMessageReceived was raised
 *
 * \param pPriv - private data section of this instance
 * \param pMsgId - The received AMS message id will be written to this pointer
 * \param pSourceAddress - The received AMS source address will be written to this pointer
 * \param pPayload - The received AMS payload will be written to this pointer
 * \param pPayloadLen - The received AMS payload length will be written to this pointer
 *
 * \return true, if operation was successful. false if no message got be retrieved.
 */
bool UCSI_GetAmsMessage(UCSI_Data_t *my, uint16_t *pMsgId, uint16_t *pSourceAddress, uint8_t **pPayload, uint32_t *pPayloadLen);

/**
 * \brief Releases the message memory returned by UCSI_GetAmsMessage.
 *
 * \note Call this function only from single context (not from ISR)
 * \note This function must be called when the data of UCSI_GetAmsMessage has been processed.
 *       If this function is not called, UCSI_GetAmsMessage will return always the reference to the same data.
 * \note UCSI_Service may also free the data returned by UCSI_GetAmsMessage!
 *
 * \param pPriv - private data section of this instance
 */
void UCSI_ReleaseAmsMessage(UCSI_Data_t *my);

/**
 * \brief Enables or disables a route by the given routeId
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 * \param routeId - identifier as given in XML file along with MOST socket (unique)
 * \param isActive - true, route will become active. false, route will be deallocated
 *
 * \return true, if route was found and the specific command was enqueued to UNICENS.
 */
bool UCSI_SetRouteActive(UCSI_Data_t *pPriv, uint16_t routeId, bool isActive);

/**
 * \brief Performs an remote I2C write command
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 * \param targetAddress - targetAddress - The node / group target address
 * \param isBurst - true, write blockCount I2C telegrams dataLen with a single call. false, write a single I2C message.
 * \param blockCount - amount of blocks to write. Only used when isBurst is set to true.
 * \param slaveAddr - The I2C address.
 * \param timeout - Timeout in milliseconds.
 * \param dataLen - Amount of bytes to send via I2C
 * \param pData - The payload to be send.
 *
 * \return true, if route command was enqueued to UNICENS.
 */
bool UCSI_I2CWrite(UCSI_Data_t *pPriv, uint16_t targetAddress, bool isBurst, uint8_t blockCount,
    uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, const uint8_t *pData);

/**
 * \brief Performs an remote I2C read command.
 * \note UCSI_CB_OnI2CRead will be called after this command has been executed
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 * \param targetAddress - targetAddress - The node / group target address
 * \param slaveAddr - The I2C address.
 * \param timeout - Timeout in milliseconds.
 * \param dataLen - Amount of bytes to send via I2C
 *
 * \return true, if route command was enqueued to UNICENS.
 */
bool UCSI_I2CRead(UCSI_Data_t *pPriv, uint16_t targetAddress,
    uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen);

/**
 * \brief Enables or disables a route by the given routeId
 * \note Call this function only from single context (not from ISR)
 *
 * \param pPriv - private data section of this instance
 * \param targetAddress - targetAddress - The node / group target address
 * \param gpioPinId - INIC GPIO PIN starting with 0 for the first GPIO.
 * \param isHighState - true, high state = 3,3V. false, low state = 0V.
 *
 * \return true, if GPIO command was enqueued to UNICENS.
 */
bool UCSI_SetGpioState(UCSI_Data_t *pPriv, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState);

/**
 * \brief Programs the IdentString into the specified INICs RAM
 *
 * \param pPriv - private data section of this instance
 * \param signature - The signature of the node to be programmed
 * \param newIdentString - newIdentString - The data to be programmed
 *
 * \return true, if program to RAM command was enqueued to UNICENS.
 */
bool UCSI_ProgramIdentStringRam(UCSI_Data_t *pPriv, const Ucs_Signature_t *signature, const Ucs_IdentString_t *newIdentString);

/**
 * \brief Programs the IdentString into the specified INICs RAM
 *
 * \param pPriv - private data section of this instance
 * \param signature - The signature of the node to be programmed
 * \param newIdentString - newIdentString - The data to be programmed
 *
 * \return true, if program to RAM command was enqueued to UNICENS.
 */
bool UCSI_ProgramIdentStringRom(UCSI_Data_t *pPriv, const Ucs_Signature_t *signature, const Ucs_IdentString_t *newIdentString);

/**
 * \brief Enables Promiscuous Mode on the given Node.
 *
 * \param pPriv - private data section of this instance
 * \param targetAddress - targetAddress - The node / group target address
 * \param enablePromiscuous - true, perfect match filter will be disabled. false, otherwise.
 *
 * \return true, if command was enqueued to UNICENS.
 */
bool UCSI_EnablePromiscuousMode(UCSI_Data_t *pPriv, uint16_t targetAddress, bool enablePromiscuous);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                        CALLBACK SECTION                              */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Callback when ever a function above was tried to be executed.
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param command - Enumeration value, identify the used command
 * \param success - true, if given command was successfully executed. false, either the direct call of the command or its async callback signaled an error
 * \param nodeAddress - the address of the node reporting this event. 0x1 in case of the local master node. 0xFFFF in case if the node address is unknown.
 */
extern void UCSI_CB_OnCommandResult(void *pTag, UnicensCmd_t command, bool success, uint16_t nodeAddress);

/**
 * \brief Callback when ever a timestamp is needed
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \return timestamp in milliseconds
 */
extern uint16_t UCSI_CB_OnGetTime(void *pTag);


/**
 * \brief Callback when the implementer needs to arm a timer.
 * \note This function must be implemented by the integrator
 * \note After timer expired, call the UCSI_Timeout from service
 *       Thread. (Not from callback!)
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param timeout - milliseconds from now on to call back. (0=disable)
 */
extern void UCSI_CB_OnSetServiceTimer(void *pTag, uint16_t timeout);

/**
 * \brief Callback when ever the state of the Network has changed.
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param isAvailable - true, if the network is operable. false, network is down. No message or stream can be sent or received.
 * \param packetBandwidth - The amount of bytes per frame reserved for the Ethernet channel. Must match to the given packetBw value passed to UCSI_NewConfig.
 * \param amountOfNodes - The amount of network devices found in the ring.
 */
extern void UCSI_CB_OnNetworkState(void *pTag, bool isAvailable, uint16_t packetBandwidth, uint8_t amountOfNodes);

/**
 * \brief Callback when ever UNICENS forms a human readable message.
 *        This can be error events or when enabled also debug messages.
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param isError - true, if this message is an important error message. false, user/debug message, not important.
 * \param format - Zero terminated format string (following printf rules)
 * \param vargsCnt - Amount of parameters stored in "..."
 */
extern void UCSI_CB_OnUserMessage(void *pTag, bool isError, const char format[],
    uint16_t vargsCnt, ...);

/**
 * \brief Callback when the overview with all nodes and routes is getting printed
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param pString - Zero terminated format string forming a table with informations
 */
extern void UCSI_CB_OnPrintRouteTable(void *pTag, const char pString[]);

/**
 * \brief Callback when ever this instance needs to be serviced.
 * \note Call UCSI_Service by your scheduler at the next run
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 */
extern void UCSI_CB_OnServiceRequired(void *pTag);

/**
 * \brief Callback when ever the INIC should be reseted by the integration code
  * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 */
extern void UCSI_CB_OnResetInic(void *pTag);

/**
 * \brief Callback when ever this instance of UNICENS wants to send control data to the LLD.
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param pPayload - Byte array to be sent on the INIC control channel
 * \param payloadLen - Length of pPayload in Byte
 */
extern void UCSI_CB_OnTxRequest(void *pTag,
    const uint8_t *pPayload, uint32_t payloadLen);

/**
 * \brief Callback when UNICENS instance has been started.
 * \note This event can be used to enable control message reception
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 */
extern void UCSI_CB_OnStart(void *pTag);

/**
 * \brief Callback when UNICENS instance has been stopped.
 * \note This event can be used to free memory holding the resources
 *       passed with UCSI_NewConfig
 * \note This event can be used to stop control message reception
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 */
extern void UCSI_CB_OnStop(void *pTag);

/**
 * \brief Callback when UNICENS instance has received an AMS message
 * \note This function must be implemented by the integrator
 * \note After this callback, call UCSI_GetAmsMessage indirect by setting a flag
 * \param pTag - Pointer given by the integrator by UCSI_Init
 */
extern void UCSI_CB_OnAmsMessageReceived(void *pTag);

/**
 * \brief Callback when a route become active / inactive.
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param routeId - identifier as given in XML file along with MOST socket (unique)
 * \param isActive - true, if the route is now in use. false, the route is not established.
 * \param connectionLabel - The connection label used on the Network. Only valid, if isActive=true
 */
extern void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive, uint16_t connectionLabel);

/**
 * \brief Callback when a INIC GPIO changes its state
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param nodeAddress - Node Address of the INIC sending the update.
 * \param gpioPinId - INIC GPIO PIN starting with 0 for the first GPIO.
 * \param isHighState - true, high state = 3,3V. false, low state = 0V.
 */
extern void UCSI_CB_OnGpioStateChange(void *pTag, uint16_t nodeAddress, uint8_t gpioPinId, bool isHighState);

/**
 * \brief Callback when nodes are discovered or disappear
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param code - Report code
 * \param signature - Signature of the found device. Maybe NULL in error cases
 * \param pNode - Reference to the node structure found in nodes list. Maybe NULL.
 */
extern void UCSI_CB_OnMgrReport(void *pTag, Ucs_MgrReport_t code, Ucs_Signature_t *signature, Ucs_Rm_Node_t *pNode);

/**
 * \brief Callback when programming (collision resolving) is finished
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param changed - true, if at least one node was programmed with new configuration. false, nothing was changed.
 */
extern void UCSI_CB_OnProgrammingDone(void *pTag, bool changed);

/**
 * \brief Callback when an I2C Read (triggered by UCSI_I2CRead) command has been executed
 * \note This function must be implemented by the integrator
 * \param pTag - Pointer given by the integrator by UCSI_Init
 * \param success - true, if the data could be read. false, otherwise
 * \param targetAddress - targetAddress - The node / group target address
 * \param slaveAddr - The I2C address.
 * \param pBuffer - If success is set to true, then the payload in this buffer is valid
 * \param bufLen - Length of buffer
 */
extern void UCSI_CB_OnI2CRead(void *pTag, bool success, uint16_t targetAddress, uint8_t slaveAddr, const uint8_t *pBuffer, uint32_t bufLen);

#ifdef __cplusplus
}
#endif

#endif /* UCSI_H_ */<file_sep>/README.md
# UNICENS example for Atmel SAM V71

This project is a bare metal example integration of the [UNICENS library](https://github.com/MicrochipTech/unicens) for the Atmel SAM V71 controller.

### Needed components

__Hardware:__
* [Atmel SAM V71 Xplained Ultra Evaluation Kit](http://www.microchip.com/DevelopmentTools/ProductDetails.aspx?PartNO=atsamv71-xult)
* Atmel SAM-ICE (min. HW-Version 7)
* OS81118 Phy+Board Variant 3 or OS81210/OS81212/OS81214 Phy+Board Variant 3
* Depending on your use case, you can start with any devices of the [K2L Slim Board Familiy](https://www.k2l.de/products/34/MOST150%20Slim%20Board%20Family/)

__Software:__
* Microsoft Windows 7 or newer
* [Atmel Studio 7](http://www.microchip.com/development-tools/atmel-studio-7)
* [Git for Windows](https://gitforwindows.org)
    
To get the source code, enter:
```bash
$ git clone --recurse-submodules https://github.com/MicrochipTech/unicens-bare-metal-sam-v71.git
```
### Build

* Open Atmel Studio 7
* __File -> Open -> Project/Solution... (Ctrl+Shift+O)__
* Select __[your-projects]\\audio-source\\SAMV71-UNICENS-example.atsln__
* Navigate to __Project -> Properties -> Tool__ and select your connected __SAM-ICE__.  
Use __SWD__ as interface and save the configuration file.
* Build the project with __F7__
* Build the project, flash it to the SAM V71 and start debugging with __F5__

### Change Network Configuration

The configuration of the entire network is done via a single XML file.  
It's located at __[your-projects]\\audio-source\config.xml__  

**Hint:** Edit the config.xml file within the Atmel Studio.  
It will validate it and help filling the correct tags and attributes by using the XML schema  __unicens.xsd__ in the same folder.

Once you edited it, double click the __[your-projects]\\audio-source\\convertXML.bat__ batch file.  
It will interpret the XML file and generate a static C-Source code file at  
__[your-projects]\\audio-source\\samv71-ucs\\src\default_config.c__  
After successful conversion, you need to build the project again and download it to the hardware in order to apply the new network configuration.<file_sep>/audio-source/samv71-ucs/src/driver/dim2/dim2_lld.h
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#ifndef DIM2_LLD_H_
#define DIM2_LLD_H_

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>

typedef enum {
    ///MOST Control Channel (ADS, AMS)
    DIM2LLD_ChannelType_Control,
    ///MOST Async Channel (MEP, MAMAC, MHP)
    DIM2LLD_ChannelType_Async,
    ///Synchronous channel (PCM audio)
    DIM2LLD_ChannelType_Sync,
    ///Isochronous channel (TS video/audio multiplex)
    DIM2LLD_ChannelType_Isoc,
    ///Don't use BOUNDARY (internal use)
    DIM2LLD_ChannelType_BOUNDARY
} DIM2LLD_ChannelType_t;

typedef enum {
    ///From EHC to MOST
    DIM2LLD_ChannelDirection_TX,
    ///From MOST to EHC
    DIM2LLD_ChannelDirection_RX,
    ///Don't use BOUNDARY (internal use)
    DIM2LLD_ChannelDirection_BOUNDARY
} DIM2LLD_ChannelDirection_t;

/** \brief Initializes the DIM Low Level Driver
* \return true, if the module could be initialized, false otherwise.
*/
bool DIM2LLD_Init(void);

/** \brief Setup a communication channel
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
* \param channelAddress - The MLB channel address to use. This must be an even value!
* \param bufferSize - The maximum amount of bytes, which may be used by the DIM2 module to buffer data
* \param subSize - This value is only used for Sync and Isoc data types (you may use 0 for Control and Async). It sets the amount of bytes of the smallest data chunk (4 Byte of 16Bit Stereo, 188 Byte for TS).
* \param numberOfBuffers - The maximum amount of messages which is stored in LLD driver (DIM2 uses Ping/Pong Buffer).
* \param bufferOffset - If non zero, the given amount of bytes will be appended to the specific buffer. For RX, this area can be filled for example with header data and passed to different software stacks (TCP/IP e.g.). For TX this value will be ignored.
* \return true, if the channel could be initialized, false otherwise.
*/
bool DIM2LLD_SetupChannel(DIM2LLD_ChannelType_t cType,
                          DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint16_t channelAddress,
                          uint16_t bufferSize, uint16_t subSize, uint16_t numberOfBuffers, uint16_t bufferOffset);


/** \brief Deinitializes the DIM Low Level Driver
*
*/
void DIM2LLD_Deinit(void);


/** \brief Must be called cyclic from task context
*
*/
void DIM2LLD_Service(void);


/** \brief Checks if the MLB and INIC have reached locked state.
*
* \return true, if there is a lock, false otherwise.
*/
bool DIM2LLD_IsMlbLocked(void);


/** \brief Returns the amount of available data buffers (max. "numberOfBuffers" passed with DIM2LLD_SetupChannel), which can be returned by calling DIM2LLD_GetRxData.
* \note This is thought to get health informations of the system (debugging).
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
* \return true, if there is a lock, false otherwise.
*/
uint32_t DIM2LLD_GetQueueElementCount(DIM2LLD_ChannelType_t cType, DIM2LLD_ChannelDirection_t dir, uint8_t instance);


/** \brief Retrieves received data from the given channel, if available.
* \note The payload passed by pBuffer stays valid until the function DIM2LLD_ReleaseRxData is called.
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
* \param pos - The position to read, starting with 0 for the oldest entry. Use DIM2LLD_GetQueueElementCount to get maximum pos count (max -1).
* \param pBuffer - This function will deliver a pointer to the data. It may be used for further processing, don't forget to call DIM2LLD_ReleaseRxData after wise! If there is no data available, this pointer will be set to NULL.
* \param pOffset - To this pointer the offset value will be written. This must be exactly the same value, as the one given with DIM2LLD_SetupChannel, Parameter bufferOffset. The given buffer is extended by this size. 
*                  The user may write into the first pOffset bytes, without destroying any informations. The received data starts after wise. May be left NULL.
* \param  pPacketCounter - To this pointer a unique packet counter will be written. The application can identify this buffer by this value in order to mark it as processed. May be left NULL.
* \return Returns the amount of bytes which can be accessed by the pBuffer.
*/
uint16_t DIM2LLD_GetRxData(DIM2LLD_ChannelType_t cType, DIM2LLD_ChannelDirection_t dir, 
                           uint8_t instance, uint32_t pos, const uint8_t **pBuffer, uint16_t *pOffset, uint8_t *pPacketCounter);


/** \brief Releases the passed data from the DIM2LLD_GetRxData function call. Call DIM2LLD_ReleaseRxData only in case you received valid data from DIM2LLD_GetRxData (Not if returned NULL).
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
*/
void DIM2LLD_ReleaseRxData(DIM2LLD_ChannelType_t cType,
                           DIM2LLD_ChannelDirection_t dir, uint8_t instance);


/** \brief Gives a pointer to a LLD buffer, if available. The user may fill the buffer asynchronously. After wise call DIM2LLD_SendTxData to finally send the data.
* \note The payload passed by pBuffer stays valid until the function DIM2LLD_SendTxData is called.
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
* \param pBuffer - This function will deliver a pointer an empty buffer. It may be used for asynchronous filling with data. If there is no buffers free in the LLD module, this pointer is NULL and the return value is 0.
* \return Returns the amount of bytes which can be filled into pBuffer. ==> Max buffer size
*/
uint16_t DIM2LLD_GetTxData(DIM2LLD_ChannelType_t cType,
                           DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint8_t **pBuffer);


/** \brief Finally sends the passed data from the DIM2LLD_GetTxData function call. Call DIM2LLD_SendTxData only in case you got valid data from DIM2LLD_GetTxData (Not if returned NULL).
* \param cType - The data type which shall be used for this channel
* \param dir - The direction for this unidirectional channel
* \param instance - For Isoc or Sync channels multiple instances may be used, starting with 0 for the first instance. For Control and Async there is only instance per direction allowed.
* \param payloadLength - The length of the data stored in pBuffer returned by DIM2LLD_GetTxData. Make sure that the length is less or equal to the return val of DIM2LLD_GetTxData!
*/
void DIM2LLD_SendTxData(DIM2LLD_ChannelType_t cType,
                        DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint32_t payloadLength);

#ifdef __cplusplus
}
#endif

#endif /* DIM2_LLD_H_ */<file_sep>/audio-source/samv71-ucs/src/board_init.c
/*------------------------------------------------------------------------------------------------*/
/* Board Init Component                                                                           */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/


#include "board_init.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      FUNCTION PROTOTYPES                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void TCM_StackInit(void);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      DEFINES AND LOCAL VARIABLES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

Twid twid;
sGmacd gGmacd;
GMacb gGmacb;
sXdmad xdma;

/** GMAC power control pin */
#if !defined(BOARD_GMAC_POWER_ALWAYS_ON)
static const Pin gmacPwrDn[]    = {BOARD_GMAC_PIN_PWRDN};
#endif

/** The PINs for GMAC */
static const Pin gmacPins[]     = {BOARD_GMAC_RUN_PINS};
static const Pin gmacResetPin   = BOARD_GMAC_RESET_PIN;

/** The PINs for TWI*/
static const Pin twiPins[]      = PINS_TWI0;
/** TWI clock frequency in Hz. */
#define TWCK            400000
/** Slave address of twi_eeprom AT24MAC.*/
#define AT24MAC_SERIAL_NUM_ADD  0x5F
/** Page size of an AT24MAC402 chip (in bytes)*/
#define PAGE_SIZE       16
/** Page numbers of an AT24MAC402 chip */
#define EEPROM_PAGES    16
/** EEPROM Pins definition */
#define BOARD_PINS_TWI_EEPROM PINS_TWI0
/** TWI0 peripheral ID for EEPROM device*/
#define BOARD_ID_TWI_EEPROM   ID_TWIHS0
/** TWI0 base address for EEPROM device */
#define BOARD_BASE_TWI_EEPROM TWIHS0

/* Push button pin */
static const Pin pushbutton[] = {PIN_PUSHBUTTON_0, PIN_PUSHBUTTON_1};

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         PUBLIC FUNCTIONS                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void Board_Init()
{
    /* Initialize the SAM system */
    WDT_Disable(WDT);
    #ifdef ENABLE_TCM
    TCM_StackInit();
    #endif

    SCB_EnableICache();
    SCB_EnableDCache();	// Please edit __DCACHE_PRESENT in samv71q21.h to en/disable DCache

    // Configure systick for 1 ms
    if (TimeTick_Configure())
    {
        assert(false);
    }

    LED_Configure(0);
    LED_Configure(1);
    LED_Clear(0);
    LED_Clear(1);

    // enable GMAC interrupts
    NVIC_ClearPendingIRQ(GMAC_IRQn);
    NVIC_EnableIRQ(GMAC_IRQn);

    // Configure Board Pushbuttons
    // SW1 is a ERASE system function, switch it to port function
    MATRIX->CCFG_SYSIO |= (1u << 12);
    // have to disable the pull down on PB12 for SW1 before the pull up can be enabled
    PIOB->PIO_PPDDR = 1 << 12;
    PIO_Configure(pushbutton, PIO_LISTSIZE(pushbutton));
    // Adjust pio debounce filter parameters
    PIO_SetDebounceFilter(&pushbutton[0], 10);
    PIO_SetDebounceFilter(&pushbutton[1], 10);

    /* Configure TWI pins. */
    PIO_Configure(twiPins, ARRAY_SIZE(twiPins));
    /* Enable TWI */
    PMC_EnablePeripheral(BOARD_ID_TWI_EEPROM);
    TWI_ConfigureMaster(BOARD_BASE_TWI_EEPROM, TWCK, BOARD_MCK);
    TWID_Initialize(&twid, BOARD_BASE_TWI_EEPROM);
    NVIC_ClearPendingIRQ(TWIHS0_IRQn);
    NVIC_EnableIRQ(TWIHS0_IRQn);

    /* Setup and enable XDMAC */
    XDMAD_Initialize(&xdma, 0);
    NVIC_ClearPendingIRQ(XDMAC_IRQn);
    NVIC_SetPriority(XDMAC_IRQn, 1);
    NVIC_EnableIRQ(XDMAC_IRQn);

    /* Initialize the hardware interface */
    init_gmac(&gGmacd);

    /* Setup interrupts */
    GMACB_Init(&gGmacb, &gGmacd, BOARD_GMAC_PHY_ADDR);
    GMACB_ResetPhy(&gGmacb);

    /* PHY initialize */
    if (!GMACB_InitPhy(&gGmacb, BOARD_MCK, &gmacResetPin, 1, gmacPins, PIO_LISTSIZE(gmacPins))) {
        printf("PHY Initialize ERROR!\n\r");
        assert(false);
    }

    if(!GMACB_PhySetSpeed100(&gGmacb, 1u)) {
        printf("Set Ethernet PHY Speed ERROR!\n\r");
        assert(false);
    }
#ifdef DEBUG
    //Phy takes a while until ready, do not wait for it in release variant
    Wait(5000);
#endif
}

bool Board_IsButtonPressed(Board_Button_t button)
{
    switch(button)
    {
    case BoardButton_SW0:
        return !PIO_Get(&pushbutton[0]);
    case BoardButton_SW1:
        return !PIO_Get(&pushbutton[1]);
    }
    assert(false);
    return false;
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                            ISR HOOKS                                 */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/** DMA handler **/
void XDMAC_Handler(void)
{
    XDMAD_Handler(&xdma);
}

/** TWI handler **/
void TWIHS0_Handler(void)
{
    TWID_Handler(&twid) ;
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      CALLBACK ERROR HOOKS                            */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void SystemHalt(const char *message)
{
    printf("System halted by '%s'\r\n", message);
    while(1);
}
void NMI_Handler(void)
{
    SystemHalt("NMI_Handler");
}
void HardFault_Handler(void)
{
    SystemHalt("HardFault_Handler");
}
void MemManage_Handler(void)
{
    SystemHalt("MemManage_Handler");
}
void BusFault_Handler(void)
{
    SystemHalt("BusFault_Handler");
}
void UsageFault_Handler(void)
{
    SystemHalt("UsageFault_Handler");
}<file_sep>/audio-source/samv71-ucs/src/gmac/gmac_init.c
#include <assert.h>
#include "gmac_init.h"
#include <string.h>

/** Enable/Disable CopyAllFrame */
#define GMAC_CAF_DISABLE    0
#define GMAC_CAF_ENABLE     1

/** Enable/Disable NoBroadCast */
#define GMAC_NBC_DISABLE    0
#define GMAC_NBC_ENABLE     1


#define PTP_RX_BUFFERS          16    /** Must be a power of 2 */
#define PTP_RX_BUFF_SIZE        256    /** Must be a power of 2 */

#define DUMMY_BUFFERS           4     /** Must be a power of 2 */
#define DUMMY_BUFF_SIZE         128    /** Must be a power of 2 */

#define AVB_RX_BUFFERS          8
#define AVB_TX_BUFFERS          8
#define AVB_BUFF_SIZE           1280

#define ETH_RX_BUFFERS          8
#define ETH_TX_BUFFERS          8

#define TSU_INCR_NS         (6)
#define TSU_INCR_SUBNS      ((uint16_t)(0.66667f * 65536.f))


#define DESCRIPTOR COMPILER_SECTION(".ram_nocache") COMPILER_ALIGNED(8)
#define GMACBUFFER COMPILER_SECTION(".ram_nocache") COMPILER_ALIGNED(DEFAULT_CACHELINE)

DESCRIPTOR sGmacRxDescriptor gPtpRxDs[PTP_RX_BUFFERS];
DESCRIPTOR sGmacTxDescriptor gPtpTxDs[DUMMY_BUFFERS];

DESCRIPTOR sGmacRxDescriptor gAvbRxDs[AVB_RX_BUFFERS];
DESCRIPTOR sGmacTxDescriptor gAvbTxDs[AVB_TX_BUFFERS];

DESCRIPTOR sGmacRxDescriptor gEthRxDs[ETH_RX_BUFFERS];
DESCRIPTOR sGmacTxDescriptor gEthTxDs[ETH_TX_BUFFERS];


GMACBUFFER uint8_t gRxPtpBuffer[PTP_RX_BUFFERS * PTP_RX_BUFF_SIZE];
GMACBUFFER uint8_t gTxPtpBuffer[DUMMY_BUFFERS * DUMMY_BUFF_SIZE];

GMACBUFFER uint8_t gRxAvbBuffer[AVB_RX_BUFFERS * AVB_BUFF_SIZE];
GMACBUFFER uint8_t gTxAvbBuffer[AVB_TX_BUFFERS * AVB_BUFF_SIZE];

GMACBUFFER uint8_t gRxEthBuffer[ETH_RX_BUFFERS * ETH_BUFF_SIZE];
GMACBUFFER uint8_t gTxEthBuffer[ETH_TX_BUFFERS * ETH_BUFF_SIZE];

DESCRIPTOR fGmacdTransferCallback gPtpTxCbs[DUMMY_BUFFERS];
DESCRIPTOR fGmacdTransferCallback gAvbTxCbs[AVB_TX_BUFFERS];
DESCRIPTOR fGmacdTransferCallback gEthTxCbs[ETH_TX_BUFFERS];

DESCRIPTOR void *gPtpTxCbTags[DUMMY_BUFFERS];
DESCRIPTOR void *gAvbTxCbTags[AVB_TX_BUFFERS];
DESCRIPTOR void *gEthTxCbTags[ETH_TX_BUFFERS];

#define PTP_ETHER_TYPE (0x88F7u)
#define AVB_ETHER_TYPE (0x22F0u)
#define ARP_ETHER_TYPE (0x0806u)

const gmacQueList_t PTP_QUEUE = GMAC_QUE_0;

static void PtpDataReceived(uint32_t status, void *pTag);
static void gmac_RxPtpEvtMsgIsrCB (ptpMsgType rxEvtMsg, uint32_t efrsh, uint32_t efrsl, uint32_t eftn);
static void gmac_TxPtpEvtMsgIsrCB (ptpMsgType txEvtMsg, uint32_t eftsh, uint32_t eftsl, uint32_t eftn, uint16_t sequenceId);

static sGmacd *spGmacd;
static sGmacInit QuePTP;
static sGmacInit QueAVB;
static sGmacInit QueETH;

void init_gmac(sGmacd  *pGmacd)
{
  assert(NULL != pGmacd);
  spGmacd = pGmacd;

  memset(&QuePTP, 0, sizeof(QuePTP));
  memset(&QueAVB, 0, sizeof(QueAVB));
  memset(&QueETH, 0, sizeof(QueETH));

  /* Initialize GMAC driver structure */
  QuePTP.bIsGem          = 1;
  QuePTP.bDmaBurstLength = 4;
  QuePTP.pRxBuffer       = gRxPtpBuffer;
  QuePTP.pRxD            = gPtpRxDs;
  QuePTP.wRxBufferSize   = PTP_RX_BUFF_SIZE;
  QuePTP.wRxSize         = PTP_RX_BUFFERS;
  QuePTP.pTxBuffer       = gTxPtpBuffer;
  QuePTP.pTxD            = gPtpTxDs;
  QuePTP.wTxBufferSize   = DUMMY_BUFF_SIZE;
  QuePTP.wTxSize         = DUMMY_BUFFERS;
  QuePTP.pTxCb           = gPtpTxCbs;
  QuePTP.pTxCbTag        = gPtpTxCbTags;

  QueETH.bIsGem          = 1;
  QueETH.bDmaBurstLength = 4;
  QueETH.pRxBuffer       = gRxEthBuffer;
  QueETH.pRxD            = gEthRxDs;
  QueETH.wRxBufferSize   = ETH_BUFF_SIZE;
  QueETH.wRxSize         = ETH_RX_BUFFERS;
  QueETH.pTxBuffer       = gTxEthBuffer;
  QueETH.pTxD            = gEthTxDs;
  QueETH.wTxBufferSize   = ETH_BUFF_SIZE;
  QueETH.wTxSize         = ETH_TX_BUFFERS;
  QueETH.pTxCb           = gEthTxCbs;
  QueETH.pTxCbTag        = gEthTxCbTags;

  QueAVB.bIsGem          = 1;
  QueAVB.bDmaBurstLength = 4;
  QueAVB.pRxBuffer       = gRxAvbBuffer;
  QueAVB.pRxD            = gAvbRxDs;
  QueAVB.wRxBufferSize   = AVB_BUFF_SIZE;
  QueAVB.wRxSize         = AVB_RX_BUFFERS;
  QueAVB.pTxBuffer       = gTxAvbBuffer;
  QueAVB.pTxD            = gAvbTxDs;
  QueAVB.wTxBufferSize   = AVB_BUFF_SIZE;
  QueAVB.wTxSize         = AVB_TX_BUFFERS;
  QueAVB.pTxCb           = gAvbTxCbs;
  QueAVB.pTxCbTag        = gAvbTxCbTags;

  GMACD_Init(pGmacd, GMAC, ID_GMAC, GMAC_CAF_ENABLE, GMAC_NBC_DISABLE);
  GMACD_InitTransfer(pGmacd, &QueETH,  GMAC_QUE_0);
  GMACD_InitTransfer(pGmacd, &QueAVB,  GMAC_QUE_1);
  GMACD_InitTransfer(pGmacd, &QuePTP,  GMAC_QUE_2);

  GMAC_SetTsuTmrIncReg(GMAC, TSU_INCR_NS, TSU_INCR_SUBNS);

  /* PTP events can only be registered to QUEUE0! */
  /* The packets can be rerouted to any queue */
  GMACD_RxPtpEvtMsgCBRegister (pGmacd, gmac_RxPtpEvtMsgIsrCB, PTP_QUEUE);
  GMACD_TxPtpEvtMsgCBRegister (pGmacd, gmac_TxPtpEvtMsgIsrCB, PTP_QUEUE);
  GMAC_EnableIt(GMAC, (GMAC_IER_SFR | GMAC_IER_PDRQFR | GMAC_IER_PDRSFR), PTP_QUEUE);
  GMAC_EnableIt(GMAC, (GMAC_IER_PDRQFT | GMAC_IER_PDRSFT), PTP_QUEUE );

  /* QUE must match screener register configuration! */
  GMACD_SetRxCallback(pGmacd, PtpDataReceived, GMAC_QUE_1);
  GMACD_RxPtpEvtMsgCBRegister(pGmacd, gmac_RxPtpEvtMsgIsrCB, PTP_QUEUE);
  GMACD_TxPtpEvtMsgCBRegister(pGmacd, gmac_TxPtpEvtMsgIsrCB, PTP_QUEUE);

  enum {
    AVB_ETHER_TYPE_REG_IDX = 0,
    PTP_ETHER_TYPE_REG_IDX,
    ARP_ETHER_TYPE_REG_IDX,
    unused,
    ETHER_TYPE_REG_MAX
  };

  // AVB
  GMAC_WriteScreener2Reg(pGmacd->pHw, AVB_ETHER_TYPE_REG_IDX, ( GMAC_ST2RPQ_ETHE | GMAC_ST2RPQ_I2ETH(AVB_ETHER_TYPE_REG_IDX) | GMAC_ST2RPQ_QNB(GMAC_QUE_1) ) );
  GMAC_WriteEthTypeReg(pGmacd->pHw, AVB_ETHER_TYPE_REG_IDX, GMAC_ST2ER_COMPVAL(AVB_ETHER_TYPE));

  // PTP
  GMAC_WriteScreener2Reg(pGmacd->pHw, PTP_ETHER_TYPE_REG_IDX, ( GMAC_ST2RPQ_ETHE | GMAC_ST2RPQ_I2ETH(PTP_ETHER_TYPE_REG_IDX) | GMAC_ST2RPQ_QNB(GMAC_QUE_2) ) );
  GMAC_WriteEthTypeReg(pGmacd->pHw, PTP_ETHER_TYPE_REG_IDX, GMAC_ST2ER_COMPVAL(PTP_ETHER_TYPE));

  // ARP
  GMAC_WriteScreener2Reg(pGmacd->pHw, ARP_ETHER_TYPE_REG_IDX, ( GMAC_ST2RPQ_ETHE | GMAC_ST2RPQ_I2ETH(ARP_ETHER_TYPE_REG_IDX) | GMAC_ST2RPQ_QNB(GMAC_QUE_0) ) );
  GMAC_WriteEthTypeReg(pGmacd->pHw, ARP_ETHER_TYPE_REG_IDX, GMAC_ST2ER_COMPVAL(ARP_ETHER_TYPE));

  NVIC_ClearPendingIRQ(GMAC_IRQn);
  NVIC_EnableIRQ(GMAC_IRQn);
  NVIC_ClearPendingIRQ(GMACQ1_IRQn);
  NVIC_EnableIRQ(GMACQ1_IRQn);
  NVIC_ClearPendingIRQ(GMACQ2_IRQn);
  NVIC_EnableIRQ(GMACQ2_IRQn);

  if((CHIPID->CHIPID_CIDR & CHIPID_CIDR_VERSION_Msk) == 0x01)
  {
    //MRLB
  }
}

/**
 * Gmac interrupt handler
 */
void GMAC_Handler(void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_0);
}

void GMACQ1_Handler (void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_1);
}

void GMACQ2_Handler (void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_2);
}

void GMACQ3_Handler(void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_3);
}

void GMACQ4_Handler(void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_4);
}

void GMACQ5_Handler(void)
{
    assert(NULL != spGmacd);
    GMACD_Handler(spGmacd, GMAC_QUE_5);
}

/* call back routine for PTP Queue */
static void PtpDataReceived(uint32_t status, void *pTag)
{
  uint32_t buffIdx;
  uint32_t frmSize;
  uint8_t *msgPtr;
  ptpMsgType ptpMsg;
  pTag = pTag;

  TRACE_INFO("%u ETH_RXCB(%u)\n\r", (unsigned int)GetTicks(), (unsigned int)status);
  assert(NULL != spGmacd);

  while(GMACD_OK == GMACD_GetRxDIdx(spGmacd, &buffIdx, &frmSize, PTP_QUEUE)) {

    msgPtr = (uint8_t *)&gRxPtpBuffer[buffIdx * PTP_RX_BUFF_SIZE];

    ptpMsg = (ptpMsgType)(msgPtr[14] & 0x0Fu);

    switch(ptpMsg) {
    case SYNC_MSG_TYPE:
      //gPtpRxdSyncMsg(msgPtr);
      break;
    case FOLLOW_UP_MSG_TYPE:
      //gPtpRxdFollowUpMsg(msgPtr);
      break;
    case PDELAY_REQ_TYPE:
      //gPtpRxdPdelayReqMsg(msgPtr);
      break;
    case PDELAY_RESP_TYPE:
      //gPtpRxdPdelayRespMsg(msgPtr);
      break;
    case PDELAY_RESP_FOLLOW_UP_MSG_TYPE:
      //gPtpRxdPdelayRespFollowUpMsg(msgPtr);
      break;
    default:
      break;
    }; /* switch (ptpMsg) */

    GMACD_FreeRxDTail(spGmacd, PTP_QUEUE);

  } /* while () */
}

static void gmac_RxPtpEvtMsgIsrCB(ptpMsgType rxEvtMsg, uint32_t efrsh, uint32_t efrsl, uint32_t efrn)
{
    efrsh = efrsh;
    efrsl = efrsl;
    efrn = efrn;
  switch(rxEvtMsg) {
    case SYNC_MSG_TYPE:
    case PDELAY_REQ_TYPE:
    case PDELAY_RESP_TYPE:
    default:
      break;
  }
}

static void gmac_TxPtpEvtMsgIsrCB(ptpMsgType txEvtMsg, uint32_t eftsh, uint32_t eftsl, uint32_t eftn, uint16_t sequenceId)
{
    eftsh = eftsh;
    eftsl = eftsl;
    eftn = eftn;
    sequenceId = sequenceId;
  switch(txEvtMsg) {
    case PDELAY_REQ_TYPE:
    case PDELAY_RESP_TYPE:
      break;
    case DELAY_REQ_MSG_TYPE:
    case FOLLOW_UP_MSG_TYPE:
    case DELAY_RESP_MSG_TYPE:
    default:
        break;
  }
}

<file_sep>/audio-source/samv71-ucs/libraries/console/Console.c
/*------------------------------------------------------------------------------------------------*/
/* Console Print Component                                                                        */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <assert.h>
#include "timetick.h"
#include "Console.h"

#define SEND_BUFFER         (4096)
#define ETHERNET_MAX_LEN    (1300)
#define SOURCE_PORT         (2033)
#define DESTINATION_PORT    (2033)

#define ETHERNET_HEADER     14u
#define IP_HEADER           20u
#define UDP_HEADER          8u
#define TOTAL_UDP_HEADER    (ETHERNET_HEADER + IP_HEADER + UDP_HEADER)
#define HB(value)           ((uint8_t)((uint16_t)(value) >> 8) & 0xFF)
#define LB(value)           ((uint8_t)(value) & 0xFF)

static bool initialied = false;
static ConsolePrio_t minPrio = PRIO_LOW;
static uint8_t ethBuffer[TOTAL_UDP_HEADER];
static char txBuffer[SEND_BUFFER];
static uint32_t txBufPosIn = 0;
static uint32_t txBufPosOut = 0;
static uint32_t txOverflow = 0;

static void InitUdpHeaders();
static bool SendUdp(uint8_t *pPayload, uint32_t payloadLen);

void ConsoleInit()
{
    InitUdpHeaders();
    initialied = true;
}

void ConsoleDeinit(void)
{
    initialied = false;
}

void ConsoleSetPrio(ConsolePrio_t prio)
{
    if (!initialied)
        return;
    minPrio = prio;
}

void ConsolePrintf(ConsolePrio_t prio, const char *statement, ...)
{
    va_list args;
    if (!initialied) return;
    if (prio < minPrio || NULL == statement) return;
    if (0 == txBufPosIn && 0 != txOverflow)
    {
        snprintf(txBuffer, sizeof(txBuffer), RED "!! UART TX overflowed %lu times, increse 'ETHERNET_MAX_LEN' !!" RESETCOLOR "\r\n", txOverflow);
        txBufPosIn = strlen(txBuffer);
        txOverflow = 0;
    }
    va_start(args, statement);
    vsnprintf(&txBuffer[txBufPosIn], (sizeof(txBuffer) - txBufPosIn), statement, args);
    va_end(args);
    txBufPosIn = strlen(txBuffer);
    assert(txBufPosIn < sizeof(txBuffer));
    if ((sizeof(txBuffer) -1) == txBufPosIn)
    {
        ++txOverflow;
    }
    ConsoleCB_OnServiceNeeded();
}

void ConsoleService( void )
{
    if (!initialied) return;
	if (0 == txBufPosIn) return;
    do
    {
        uint32_t sendLen = txBufPosIn - txBufPosOut;
        if (sendLen > ETHERNET_MAX_LEN)
            sendLen = ETHERNET_MAX_LEN;
        assert(txBufPosIn >= txBufPosOut);
        if (SendUdp((uint8_t *)&txBuffer[txBufPosOut], sendLen))
        {
            txBufPosOut += sendLen;
            assert(txBufPosIn >= txBufPosOut);
            if (txBufPosIn == txBufPosOut)
            {
                txBufPosIn = 0;
                txBufPosOut = 0;
                break;
            }
        } else {
            ConsoleCB_OnServiceNeeded();
            break;
        }
    } while (true);
}

static void InitUdpHeaders()
{
    uint8_t *buff = ethBuffer;

    /* ---- Ethernet_HEADER ---- */
    //Destination MAC:
    /* 00 */ *buff++ = 0xffu; /* 01 */ *buff++ = 0xffu; /* 02 */ *buff++ = 0xffu; /* 03 */ *buff++ = 0xffu;
    /* 04 */ *buff++ = 0xffu; /* 05 */ *buff++ = 0xffu;
    //Source MAC:
    /* 06 */ *buff++ = 0x02u; /* 07 */ *buff++ = 0x00u; /* 08 */ *buff++ = 0x00u; /* 09 */ *buff++ = 0x01u;
    /* 10 */ *buff++ = 0x01u; /* 11 */ *buff++ = 0x01u;
    //Type
    /* 12 */ *buff++ = 0x08u; /* 13 */ *buff++ = 0x00u;

    /* ---- IP_HEADER ---- */
    /* 14 */ *buff++ = 0x45u; //Version
    /* 15 */ *buff++ = 0x00u; //Service Field
    /* 16, 17 will be filled by SendUdp() */ buff++; buff++;
    /* 18 */ *buff++ = 0x00u; /* 19 */ *buff++ = 0x0eu; //Identification
    /* 20 */ *buff++ = 0x00u; /* 21 */ *buff++ = 0x00u; //Flags & Fragment Offset
    /* 22 */ *buff++ = 0x40u; //TTL
    /* 23 */ *buff++ = 0x11u; //Protocol
    /* 24, 25 will be filled by SendUdp() */ buff++; buff++;
    //Source IP
    /* 26 */ *buff++ = 0x00u; /* 27 */ *buff++ = 0x00u; /* 28 */ *buff++ = 0x00u; /* 29 */ *buff++ = 0x00u;
    //Destination IP
    /* 30 */ *buff++ = 0xffu, /* 31 */ *buff++ = 0xffu; /* 32 */ *buff++ = 0xffu; /* 33 */ *buff++ = 0xffu;
    //UDP_HEADER
    /* 34 */ *buff++ = HB(SOURCE_PORT); /* 35 */ *buff++ = LB(SOURCE_PORT); //Source Port
    /* 36 */ *buff++ = HB(DESTINATION_PORT); /* 37*/ *buff++ = LB(DESTINATION_PORT); //Destination Port
    /* 38, 39 will be filled by SendUdp() */ buff++; buff++;
    /* 40 */ *buff++ = 0x00u; /* 41 */ *buff++ = 0x00u; //Checksum (optional)
}

static bool SendUdp(uint8_t *pPayload, uint32_t payloadLen)
{
    uint16_t ipLen = ETHERNET_HEADER + IP_HEADER + UDP_HEADER + payloadLen;
    uint32_t crcSum = 0ul;
    uint8_t crcCount = 0u;
    if (NULL == pPayload || 0 == payloadLen)
        return false;

    ethBuffer[16] = HB(ipLen - ETHERNET_HEADER);
    ethBuffer[17] = LB(ipLen - ETHERNET_HEADER); //Total Length

    //Header Checksum
    while (crcCount < 10u)
    {
        crcSum += (uint16_t)(ethBuffer[ETHERNET_HEADER + crcCount++] << 8u);
        crcSum += ethBuffer[ETHERNET_HEADER + crcCount++];
    }
    crcSum = ~((crcSum & 0xfffful) + (crcSum >> 16u));
    ethBuffer[24] = HB(crcSum);
    ethBuffer[25] = LB(crcSum);
    ethBuffer[38] = HB(UDP_HEADER + payloadLen);
    ethBuffer[39] = LB(UDP_HEADER + payloadLen);

    return ConsoleCB_SendDatagram(ethBuffer, sizeof(ethBuffer), pPayload, payloadLen);
}
<file_sep>/audio-source/samv71-ucs/libraries/console/Console.h
/*------------------------------------------------------------------------------------------------*/
/* Console Print Component                                                                        */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

/*----------------------------------------------------------*/
/*! \file
 *  \brief This file contains C-functions starting with "Console" to provide
 *         process and thread safe access to the console output.
 */
/*----------------------------------------------------------*/
#ifndef _CONSOLE_H_
#define _CONSOLE_H_

#define ENABLE_COLOR

#ifdef ENABLE_COLOR
#define RESETCOLOR "\033[0m"
#define GREEN      "\033[0;32m"
#define RED        "\033[0;31m"
#define YELLOW     "\033[1;33m"
#define BLUE       "\033[0;34m"
#else
#define RESETCOLOR
#define GREEN
#define RED
#define YELLOW
#define BLUE
#endif

#include <stdbool.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

    typedef enum
    {
        PRIO_LOW = 0,
        PRIO_MEDIUM = 1,
        PRIO_HIGH = 2,
        PRIO_ERROR = 0xFF
    } ConsolePrio_t;

    /*----------------------------------------------------------*/
    /*! \brief Initializes the resources needed to synchronize between processes and threads.
     *  \note This function must be called before any other function of this component.
     *
     */
    /*----------------------------------------------------------*/
    void ConsoleInit( void );

    /*----------------------------------------------------------*/
    /*! \brief Destroys the resources needed to synchronize between processes and threads.
     *  \note After this function, any other function (except ConsoleInit) must not be called.
     *
     */
    /*----------------------------------------------------------*/
    void ConsoleDeinit( void );


    /*----------------------------------------------------------*/
    /*! \brief Sets the minimum priority to be displayed. Lower priority messages are discarded
     *  \param prio - The minimum priority to display
     */
    /*----------------------------------------------------------*/
    void ConsoleSetPrio( ConsolePrio_t prio );

    /*----------------------------------------------------------*/
    /*! \brief Uses the board specific PRINT mechanism and provides thread and process safety.
     *
     */
    /*----------------------------------------------------------*/
    void ConsolePrintf( ConsolePrio_t prio, const char *statement, ... ) __attribute__ ((format (gnu_printf, 2, 3)));

    /*----------------------------------------------------------*/
    /*! \brief Call this function in main()-context after ConsoleCB_OnServiceNeeded was raised.
     *
     */
    /*----------------------------------------------------------*/
    void ConsoleService( void );

    /*----------------------------------------------------------*/
    /*! \brief Callback to integrators code whenever this component needs to be serviced.
     *  \note Do not call ConsoleService() inside this function! Set flag, and call in main()-context.
     *
     */
    /*----------------------------------------------------------*/
    extern void ConsoleCB_OnServiceNeeded(void);

    /*----------------------------------------------------------*/
    /*! \brief Callback to integrators code in order to send Ethernet datagram.
     *  \return Integrator shall return true, if packet was enqueued successful. false, otherwise.
     *  \note Buffer is not valid after this call.
     *
     */
    /*----------------------------------------------------------*/
    extern bool ConsoleCB_SendDatagram( uint8_t *pEthHeader, uint32_t ethLen, uint8_t *pPayload, uint32_t payloadLen );
#ifdef __cplusplus
}
#endif

#endif //_CONSOLE_H_
<file_sep>/audio-source/samv71-ucs/src/task-unicens.c
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Daemon Task Implementation                                                             */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "Console.h"
#include "ucsi_api.h"
#include "default_config.h"
#include "timetick.h"
#include "dim2_lld.h"
#include "task-unicens.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                          USER ADJUSTABLE                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

#define ENABLE_PROMISCOUS_MODE     (true)
#define DEBUG_TABLE_PRINT_TIME_MS  (250)

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      DEFINES AND LOCAL VARIABLES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/


typedef struct
{
    DIM2LLD_ChannelType_t cType;
    DIM2LLD_ChannelDirection_t dir;
    uint8_t instance;
    uint16_t channelAddress;
    uint16_t bufferSize;
    uint16_t subSize;
    uint16_t numberOfBuffers;
    uint16_t bufferOffset;
} DIM2_Setup_t;

typedef struct
{
    bool allowRun;
    bool lldTrace;
    bool noRouteTable;
    UCSI_Data_t unicens;
    bool unicensRunning;
    uint32_t unicensTimeout;
    bool unicensTrigger;
    bool promiscuousMode;
    bool amsReceived;
} LocalVar_t;

static LocalVar_t m;

static DIM2_Setup_t mlbConfig[] =
{
    {
        .cType = DIM2LLD_ChannelType_Control,
        .dir = DIM2LLD_ChannelDirection_RX,
        .instance = 0,
        .channelAddress = 2,
        .bufferSize = 72,
        .subSize = 0,
        .numberOfBuffers = 8,
        .bufferOffset = 0
        }, {
        .cType = DIM2LLD_ChannelType_Control,
        .dir = DIM2LLD_ChannelDirection_TX,
        .instance = 0,
        .channelAddress = 4,
        .bufferSize = 72,
        .subSize = 0,
        .numberOfBuffers = 8,
        .bufferOffset = 0
        }, {
        .cType = DIM2LLD_ChannelType_Async,
        .dir = DIM2LLD_ChannelDirection_RX,
        .instance = 0,
        .channelAddress = 6,
        .bufferSize = 1522,
        .subSize = 0,
        .numberOfBuffers = 8,
        .bufferOffset = 0
        }, {
        .cType = DIM2LLD_ChannelType_Async,
        .dir = DIM2LLD_ChannelDirection_TX,
        .instance = 0,
        .channelAddress = 8,
        .bufferSize = 1522,
        .subSize = 0,
        .numberOfBuffers = 8,
        .bufferOffset = 0
        }, {
        .cType = DIM2LLD_ChannelType_Sync,
        .dir = DIM2LLD_ChannelDirection_TX,
        .instance = 0,
        .channelAddress = 10,
        .bufferSize = 512,
        .subSize = 4,
        .numberOfBuffers = 4,
        .bufferOffset = 0
    }
};
static const uint32_t mlbConfigSize = sizeof(mlbConfig) / sizeof(DIM2_Setup_t);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                     PRIVTATE FUNCTION PROTOTYPES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static void ServiceMostCntrlRx(void);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         PUBLIC FUNCTIONS                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

bool TaskUnicens_Init(void)
{
    m.promiscuousMode = ENABLE_PROMISCOUS_MODE;
    // Initialize MOST DIM2 driver
    DIM2LLD_Init();
    Wait(100);
    while (!DIM2LLD_IsMlbLocked())
    {
        ConsolePrintf(PRIO_ERROR, RED "MLB is not locked!" RESETCOLOR "\r\n");
        Wait(1000);
    }
    for (uint32_t i = 0; i < mlbConfigSize; i++)
    {
        if (!DIM2LLD_SetupChannel(mlbConfig[i].cType, mlbConfig[i].dir, mlbConfig[i].instance, mlbConfig[i].channelAddress,
            mlbConfig[i].bufferSize, mlbConfig[i].subSize, mlbConfig[i].numberOfBuffers, mlbConfig[i].bufferOffset))
        {
            ConsolePrintf(PRIO_ERROR, "Failed to allocate MLB channel with address=0x%X\r\n", mlbConfig[i].channelAddress);
            assert(false);
            return false;
        }
    }

    /* Initialize UNICENS */
    UCSI_Init(&m.unicens, &m);
    if (!UCSI_NewConfig(&m.unicens, PacketBandwidth, AllRoutes, RoutesSize, AllNodes, NodeSize))
    {
        ConsolePrintf(PRIO_ERROR, RED "Could not enqueue new UNICENS config" RESETCOLOR "\r\n");
        assert(false);
        return false;
    }
    m.allowRun = true;
    return true;
}

void TaskUnicens_Service(void)
{
    uint32_t now;
    if (!m.allowRun)
        return;
    ServiceMostCntrlRx();
    now = GetTicks();
    /* UNICENS Service */
    if (m.unicensTrigger)
    {
        m.unicensTrigger = false;
        UCSI_Service(&m.unicens);
    }
    if (0 != m.unicensTimeout && now >= m.unicensTimeout)
    {
        m.unicensTimeout = 0;
        UCSI_Timeout(&m.unicens);
    }
    if (m.amsReceived)
    {
        uint16_t amsId = 0xFFFF;
        uint16_t sourceAddress = 0xFFFF;
        uint8_t *pBuf = NULL;
        uint32_t len = 0;
        m.amsReceived = false;
        if (UCSI_GetAmsMessage(&m.unicens, &amsId, &sourceAddress, &pBuf, &len))
        {
            ConsolePrintf(PRIO_HIGH, "Received AMS, id=0x%X, source=0x%X, len=%lu\r\n", amsId, sourceAddress, len);
            UCSI_ReleaseAmsMessage(&m.unicens);
        }
        else assert(false);
    }
}

bool TaskUnicens_SetRouteActive(uint16_t routeId, bool isActive)
{
    return UCSI_SetRouteActive(&m.unicens, routeId, isActive);
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                  PRIVATE FUNCTION IMPLEMENTATIONS                    */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static void ServiceMostCntrlRx(void)
{
    uint16_t bufLen;
    const uint8_t *pBuf;
    DIM2LLD_Service();
    do
    {
        bufLen = DIM2LLD_GetRxData(DIM2LLD_ChannelType_Control, DIM2LLD_ChannelDirection_RX, 0, 0, &pBuf, NULL, NULL);
        if (0 != bufLen)
        {
            if (m.unicensRunning)
            {
                if (m.lldTrace)
                {
                    ConsolePrintf( PRIO_HIGH, BLUE "%08lu MSG_RX(%d): ", GetTicks(), bufLen);
                    for ( int16_t i = 0; i < bufLen; i++ )
                    {
                        ConsolePrintf( PRIO_HIGH, "%02X ", pBuf[i] );
                    }
                    ConsolePrintf( PRIO_HIGH, RESETCOLOR"\n");
                }
                if (!UCSI_ProcessRxData(&m.unicens, pBuf, bufLen))
                {
                    ConsolePrintf(PRIO_ERROR, "RX buffer overflow\r\n");
                    /* UNICENS is busy. Try to reactive it, by calling service routine */
                    m.unicensTrigger = true;
                    break;
                }
            }
            DIM2LLD_ReleaseRxData(DIM2LLD_ChannelType_Control, DIM2LLD_ChannelDirection_RX, 0);
        }
    }
    while (0 != bufLen);
}


/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                  CALLBACK FUNCTIONS FROM UNICENS                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void UCSI_CB_OnCommandResult(void *pTag, UnicensCmd_t command, bool success, uint16_t nodeAddress)
{
    if (!success)
        ConsolePrintf(PRIO_ERROR, RED "OnCommandResult, cmd=0x%X, node=0x%X failed" RESETCOLOR "\r\n", command, nodeAddress);
}

uint16_t UCSI_CB_OnGetTime(void *pTag)
{
    return GetTicks();
}

void UCSI_CB_OnSetServiceTimer(void *pTag, uint16_t timeout)
{
    if (0 == timeout)
        m.unicensTimeout = 0;
    else
        m.unicensTimeout = GetTicks() + timeout;
}

void UCSI_CB_OnNetworkState(void *pTag, bool isAvailable, uint16_t packetBandwidth, uint8_t amountOfNodes)
{
    pTag = pTag;
    ConsolePrintf(PRIO_HIGH, YELLOW "Network isAvailable=%s, packetBW=%d, nodeCount=%d" RESETCOLOR "\r\n",
        isAvailable ? "yes" : "no", packetBandwidth, amountOfNodes);
}

void UCSI_CB_OnUserMessage(void *pTag, bool isError, const char format[], uint16_t vargsCnt, ...)
{
    va_list argptr;
    char outbuf[300];
    pTag = pTag;
    va_start(argptr, vargsCnt);
    vsnprintf(outbuf, sizeof(outbuf), format, argptr);
    va_end(argptr);
    if (isError)
        ConsolePrintf(PRIO_ERROR, RED "%s" RESETCOLOR "\r\n", outbuf);
    else
    ConsolePrintf(PRIO_LOW, "%s\r\n", outbuf);
}

void UCSI_CB_OnPrintRouteTable(void *pTag, const char pString[])
{
    ConsolePrintf(PRIO_HIGH, "%s\r\n", pString);
}

void UCSI_CB_OnServiceRequired(void *pTag)
{
    m.unicensTrigger = true;
}

void UCSI_CB_OnResetInic(void *pTag)
{
}

void UCSI_CB_OnTxRequest(void *pTag,
const uint8_t *pPayload, uint32_t payloadLen)
{
    pTag = pTag;
    assert(pTag == &m);
    uint8_t *pBuf = NULL;
    if (m.lldTrace)
    {
        ConsolePrintf( PRIO_HIGH, BLUE "%08lu MSG_TX(%lu): ", GetTicks(), payloadLen);
        for ( uint32_t i = 0; i < payloadLen; i++ )
        {
            ConsolePrintf( PRIO_HIGH, "%02X ", pPayload[i] );
        }
        ConsolePrintf(PRIO_HIGH, RESETCOLOR "\n");
    }
    uint32_t txMaxLen = 0;
    while (0 == txMaxLen)
    {
        txMaxLen = DIM2LLD_GetTxData(DIM2LLD_ChannelType_Control, DIM2LLD_ChannelDirection_TX, 0, &pBuf);
    }
    if (NULL == pBuf || txMaxLen < payloadLen)
    {
        ConsolePrintf(PRIO_ERROR, RED "UCSI_CB_SendMostMessage buffer is too small! %lu < %lu" RESETCOLOR "\r\n", txMaxLen, payloadLen);
        assert(false);
        return;
    }
    memcpy(pBuf, pPayload, payloadLen);
    DIM2LLD_SendTxData(DIM2LLD_ChannelType_Control, DIM2LLD_ChannelDirection_TX, 0, payloadLen);
}

void UCSI_CB_OnStart(void *pTag)
{
    m.unicensRunning = true;
}

void UCSI_CB_OnStop(void *pTag)
{
    m.unicensRunning = false;
}

void UCSI_CB_OnAmsMessageReceived(void *pTag)
{
    m.amsReceived = true;
}

void UCSI_CB_OnRouteResult(void *pTag, uint16_t routeId, bool isActive, uint16_t connectionLabel)
{
    ConsolePrintf(PRIO_MEDIUM, "Route id=0x%X isActive=%s ConLabel=0x%X\r\n", routeId,
        (isActive ? "true" : "false"), connectionLabel);
    TaskUnicens_CB_OnRouteResult(routeId, isActive, connectionLabel);
}

void UCSI_CB_OnGpioStateChange(void *pTag, uint16_t nodeAddress, uint8_t gpioPinId, bool isHighState)
{
    ConsolePrintf(PRIO_HIGH, "GPIO state changed, nodeAddress=0x%X, gpioPinId=%d, isHighState=%s\r\n",
    nodeAddress, gpioPinId, isHighState ? "yes" : "no");
}

void UCSI_CB_OnI2CRead(void *pTag, bool success, uint16_t targetAddress, uint8_t slaveAddr, const uint8_t *pBuffer, uint32_t bufLen)
{
    if (!success)
        ConsolePrintf(PRIO_ERROR, RED "I2C read failed, node=0x%X" RESETCOLOR "\r\n", targetAddress);
}

void UCSI_CB_OnMgrReport(void *pTag, Ucs_MgrReport_t code, Ucs_Signature_t *signature, Ucs_Rm_Node_t *pNode)
{
    pTag = pTag;
    if (m.promiscuousMode && NULL != signature && UCS_MGR_REP_AVAILABLE == code)
    {
        uint16_t targetAddr = signature->node_address;
        UCSI_EnablePromiscuousMode(&m.unicens, targetAddr, true);
    }
}

void UCSI_CB_OnProgrammingDone(void *pTag, bool changed)
{
    pTag = pTag;
    if (changed)
    ConsolePrintf(PRIO_HIGH, YELLOW "Programming finished, terminating program.." RESETCOLOR "\r\n");
    else
    ConsolePrintf(PRIO_HIGH, YELLOW "No programming needed (no collision), terminating program.." RESETCOLOR "\r\n");
    exit(0);
}
<file_sep>/audio-source/samv71-ucs/src/task-unicens.h
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Daemon Task Implementation                                                             */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

#ifndef TASK_UNICENS_H_
#define TASK_UNICENS_H_

#ifdef __cplusplus
extern "C" {
#endif

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                            Public API                                */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Initializes the UNICENS Task
 * \note Must be called before any other function of this component
 * \return true, if initialization was successful. false, otherwise, do not call any other function in that case
 */
bool TaskUnicens_Init(void);

/**
 * \brief Gives the UNICENS Task time to maintain it's service routines
 */
void TaskUnicens_Service(void);

/**
 * \brief Enables or disables a route by the given routeId
 *
 * \param routeId - identifier as given in XML file along with MOST socket (unique)
 * \param isActive - true, route will become active. false, route will be deallocated
 *
 * \return true, if route was found and the specific command was enqueued to UNICENS.
 */
bool TaskUnicens_SetRouteActive(uint16_t routeId, bool isActive);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                        CALLBACK SECTION                              */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Callback when a route become active / inactive.
 * \note This function must be implemented by the integrator
 * \param routeId - identifier as given in XML file along with MOST socket (unique)
 * \param isActive - true, if the route is now in use. false, the route is not established.
 * \param connectionLabel - The connection label used on the Network. Only valid, if isActive=true
 */
extern void TaskUnicens_CB_OnRouteResult(uint16_t routeId, bool isActive, uint16_t connectionLabel);

#ifdef __cplusplus
}
#endif

#endif /* TASK_UNICENS_H_ */<file_sep>/audio-source/samv71-ucs/utils/utility.h
/* ----------------------------------------------------------------------------
 *         SAM Software Package License
 * ----------------------------------------------------------------------------
 * Copyright (c) 2014, Atmel Corporation
 *
 * All rights reserved.
 *
 * 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 disclaimer below.
 *
 * Atmel's name may not be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
 * DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
 * ----------------------------------------------------------------------------
 */

#ifndef UTILITY_H
#define UTILITY_H

#include "chip.h"
 


#define RESET_CYCLE_COUNTER()  do { \
        CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; \
        __DSB(); DWT->LAR = 0xC5ACCE55; __DSB(); \
        DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; \
        DWT->CYCCNT = 0; \
        DWT->CTRL = DWT_CTRL_CYCCNTENA_Msk; \
    }while(0)

#define GET_CYCLE_COUNTER(x)                x=DWT->CYCCNT;   

#define LockMutex(mut, timeout)             get_lock(&mut, 1, &timeout)
    
#define ReleaseMutex(mut)                   free_lock(&mut)

#define GetResource(mut, max, timeout)      get_lock(&mut, max, &timeout)
    
#define FreeResource(mut)                   free_lock(&mut)


__STATIC_INLINE uint8_t Is_LockFree(volatile uint8_t *Lock_Variable)
{
    /* return Variable value*/
    return __LDREXB(Lock_Variable); 
    
}

__STATIC_INLINE uint8_t get_lock(volatile uint8_t *Lock_Variable, const uint8_t maxValue, volatile uint32_t *pTimeout)
{
    while (*pTimeout)
	{
        if(__LDREXB(Lock_Variable) < maxValue)
        {
          /* Set the Variable */
          while( __STREXB(((*Lock_Variable) + 1), Lock_Variable) )
          {            
            if(!(*pTimeout)--)
            {
              return 1;       // quit if timeout
            }
          }
          /* Memory access barrier */
          __DMB();
          TRACE_DEBUG("Mutex locked ");
          return 0;
        }
        
        ((*pTimeout)--);
	}
    return 1;
}



__STATIC_INLINE uint8_t free_lock(volatile uint8_t *Lock_Variable)
{
    /* Memory access barrier Ensure memory operations completed before releasing lock  */
    __DSB();
    if(__LDREXB(Lock_Variable))
    {
      __STREXB( ((*Lock_Variable) - 1), Lock_Variable);
      TRACE_DEBUG("Mutex freed ");
      __DSB();
      __DMB(); // Ensure memory operations completed before
      return 0;
    }
    else
    {
      return 1;
    }
    
    
}


#endif /* UTILITY_H */
<file_sep>/audio-source/samv71-ucs/src/driver/dim2/dim2_lld.c
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#include <assert.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>

#include "ringbuffer.h"
#include "dim2_hal.h"
#include "dim2_lld.h"
#include "dim2_hardware.h"

//USE CASE SPECIFIC:
//Depending from this value, different buffer sizes must be used for synchronous streaming (ask for helper tool):
#define FCNT_VAL                        (5)

//How many RX and TX pairs available for sync / isoc use case
#define MAX_CHANNEL_INSTANCES           (4)

//Enable to debug
/* #define LLD_TRACE */

#ifdef LLD_TRACE
/* #define LLD_TRACE_IGNORE_RX */
/* #define LLD_TRACE_IGNORE_TX */
#define LLD_TRACE_IGNORE_CONTROL
#define LLD_TRACE_IGNORE_SYNC
/* #define LLD_TRACE_IGNORE_ASYNC */
#define LLD_TRACE_IGNORE_ISOC

#include "Console.h"
#endif

//Fixed values:
#define DMA_CHANNELS (32 - 1)  /* channel 0 is a system channel */

typedef struct {
    bool hwEnqueued;
    int16_t payloadLen;
    int16_t maxPayloadLen;
    uint16_t offset;
    uint8_t *buffer;
    uint8_t packetCounter;
} QueueEntry_t;

typedef struct {
    bool channelUsed;
    RingBuffer_t *ringBuffer;
    struct dim_channel *dimChannel;
    uint16_t amountOfEntries;
    QueueEntry_t *workingStruct;
    DIM2LLD_ChannelType_t cType;
    DIM2LLD_ChannelDirection_t dir;
    uint8_t lastPacketCount;
} ChannelContext_t;

typedef struct {
    bool initialized;
    ChannelContext_t controlLookupTable[DIM2LLD_ChannelDirection_BOUNDARY];
    ChannelContext_t asyncLookupTable[DIM2LLD_ChannelDirection_BOUNDARY];
    ChannelContext_t syncLookupTable[DIM2LLD_ChannelDirection_BOUNDARY][MAX_CHANNEL_INSTANCES];
    ChannelContext_t isocLookupTable[DIM2LLD_ChannelDirection_BOUNDARY][MAX_CHANNEL_INSTANCES];
    ///Zero terminated list of all dim channels. This used by the ISR routine.
    struct dim_channel *allChannels[DMA_CHANNELS];
} LocalVar_t;

static LocalVar_t lc = { 0 };


static void ExecuteLLDTrace(DIM2LLD_ChannelType_t cType, DIM2LLD_ChannelDirection_t dir, const uint8_t *buffer, uint16_t payloadLen)
{
#ifdef LLD_TRACE
    do
    {
        const char *pTypeStr = "Unknown";
        const char *pDirStr = "Unknown";
        int16_t l;
        #ifdef LLD_TRACE_IGNORE_TX
        if (DIM2LLD_ChannelDirection_TX == dir)
            break;
        #endif
        #ifdef LLD_TRACE_IGNORE_RX
        if (DIM2LLD_ChannelDirection_RX == dir)
            break;
        #endif
        #ifdef LLD_TRACE_IGNORE_CONTROL
        if (DIM2LLD_ChannelType_Control == cType)
            break;
        #endif
        #ifdef LLD_TRACE_IGNORE_SYNC
        if (DIM2LLD_ChannelType_Sync == cType)
            break;
        #endif
        #ifdef LLD_TRACE_IGNORE_ASYNC
        if (DIM2LLD_ChannelType_Async == cType)
            break;
        #endif
        #ifdef LLD_TRACE_IGNORE_ISOC
        if (DIM2LLD_ChannelType_Isoc == cType)
            break;
        #endif
        switch(dir)
        {
            case DIM2LLD_ChannelDirection_TX: pDirStr = YELLOW "TX" RESETCOLOR; break;
            case DIM2LLD_ChannelDirection_RX: pDirStr = GREEN "RX" RESETCOLOR; break;
            case DIM2LLD_ChannelDirection_BOUNDARY:
            default:
            assert(false);
        }
        switch(cType)
        {
            case DIM2LLD_ChannelType_Control:  pTypeStr = "Control"; break;
            case DIM2LLD_ChannelType_Async: pTypeStr = "Async"; break;
            case DIM2LLD_ChannelType_Sync: pTypeStr = "Sync"; break;
            case DIM2LLD_ChannelType_Isoc: pTypeStr = "Isoc"; break;
            case DIM2LLD_ChannelType_BOUNDARY:
            default:
            assert(false);
        }
        ConsolePrintf(PRIO_HIGH, "DIM2LLD_%s (%s): [", pDirStr, pTypeStr);
        for (l = 0; l < payloadLen; l++) {
            ConsolePrintf(PRIO_HIGH, " %02X", buffer[l]);
        }
        ConsolePrintf(PRIO_HIGH, " ]\r\n");
    }
    while(0);
#endif
}

//This must be adapted use case specific
static ChannelContext_t *GetDimContext(DIM2LLD_ChannelType_t cType,
                                       DIM2LLD_ChannelDirection_t dir,
                                       uint8_t instance)
{
    assert(cType < DIM2LLD_ChannelType_BOUNDARY);
    assert(dir < DIM2LLD_ChannelDirection_BOUNDARY);
    assert(instance < MAX_CHANNEL_INSTANCES);
    if (cType >= DIM2LLD_ChannelType_BOUNDARY
        || dir >= DIM2LLD_ChannelDirection_BOUNDARY
        || instance >= MAX_CHANNEL_INSTANCES)
        return NULL;

    switch (cType) {
    case DIM2LLD_ChannelType_Control:
        if (0 != instance)
            return NULL;
        return &lc.controlLookupTable[dir];
    case DIM2LLD_ChannelType_Async:
        if (0 != instance)
            return NULL;
        return &lc.asyncLookupTable[dir];
    case DIM2LLD_ChannelType_Sync:
        return &lc.syncLookupTable[dir][instance];
    case DIM2LLD_ChannelType_Isoc:
        return &lc.isocLookupTable[dir][instance];
    default:
        break;
    }
    return NULL;
}

static void CleanUpContext(ChannelContext_t *context)
{
    uint16_t i;
    assert(NULL != context);
    if (!context->channelUsed)
        return;
    context->channelUsed = false;
    context->cType = DIM2LLD_ChannelType_BOUNDARY;
    context->dir = DIM2LLD_ChannelDirection_BOUNDARY;
    if (NULL != context->ringBuffer)
        free(context->ringBuffer);
    if (NULL != context->dimChannel)
        free(context->dimChannel);
    if (NULL != context->ringBuffer)
        RingBuffer_Deinit(context->ringBuffer);
    if (NULL != context->workingStruct) {
        for (i = 0; i < context->amountOfEntries; i++)
            if (NULL != context->workingStruct[i].buffer)
                free(context->workingStruct[i].buffer);
        free(context->workingStruct);
    }
}

static bool AddDimChannelToIsrList(struct dim_channel *ch)
{
    uint8_t i;
    bool added = false;
    assert(NULL != ch);
    for (i = 0; i < DMA_CHANNELS; i++) {
        if (lc.allChannels[i] != NULL)
            continue;
        lc.allChannels[i] = ch;
        added = true;
        break;
    }
    assert(added);
    return added;
}

bool DIM2LLD_Init(void)
{
    assert(!lc.initialized);
    memset(&lc, 0, sizeof(lc));
    lc.initialized = true;
    enable_mlb_clock();
    initialize_mlb_pins();
    disable_mlb_interrupt();
    if (DIM_NO_ERROR != dim_startup(DIM2_BASE_ADDRESS, DIM2_MLB_SPEED, FCNT_VAL))
        return false;
    enable_mlb_interrupt();

    return true;
}

bool DIM2LLD_SetupChannel(DIM2LLD_ChannelType_t cType,
                          DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint16_t channelAddress,
                          uint16_t bufferSize, uint16_t subSize, uint16_t numberOfBuffers, uint16_t bufferOffset)
{
    uint8_t result;
    uint16_t i;
    ChannelContext_t *context;
    assert(lc.initialized);
    if (!lc.initialized)
        return false;
    if (DIM2LLD_ChannelDirection_TX == dir)
        bufferOffset = 0;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context)
        return false;
    CleanUpContext(context);
    context->channelUsed = true;
    context->amountOfEntries = numberOfBuffers;
    switch (cType) {
    case DIM2LLD_ChannelType_Control:
    case DIM2LLD_ChannelType_Async:
        bufferSize = dim_norm_ctrl_async_buffer_size(bufferSize);
        break;
    case DIM2LLD_ChannelType_Sync:
        bufferSize = dim_norm_sync_buffer_size(bufferSize, subSize);
        break;
    case DIM2LLD_ChannelType_Isoc:
        bufferSize = dim_norm_isoc_buffer_size(bufferSize, subSize);
        break;
    default:
        assert(false);
        return false;
    }
    if (0 == bufferSize)
        return false;
    context->cType = cType;
    context->dir = dir;
    context->workingStruct = (QueueEntry_t *)calloc(numberOfBuffers,
                             sizeof(QueueEntry_t));
    for (i = 0; i < numberOfBuffers; i++) {
        context->workingStruct[i].offset = bufferOffset;
        context->workingStruct[i].maxPayloadLen = bufferSize;
        context->workingStruct[i].buffer = (uint8_t *)calloc(bufferSize + bufferOffset,
                                           sizeof(uint8_t));
        assert(NULL != context->workingStruct[i].buffer);
    }
    context->ringBuffer = (RingBuffer_t *)calloc(1, sizeof(RingBuffer_t));
    RingBuffer_Init(context->ringBuffer, numberOfBuffers, sizeof(QueueEntry_t),
                    context->workingStruct);
    context->dimChannel = calloc(1, sizeof(struct dim_channel));
    assert(NULL != context->workingStruct &&
           NULL != context->ringBuffer &&
           NULL != context->dimChannel);
    AddDimChannelToIsrList(context->dimChannel);
    disable_mlb_interrupt();
    switch (cType) {
    case DIM2LLD_ChannelType_Control:
        result = dim_init_control(context->dimChannel,
                                  (DIM2LLD_ChannelDirection_TX == dir), channelAddress, bufferSize);
        enable_mlb_interrupt();
        return (DIM_NO_ERROR == result);
    case DIM2LLD_ChannelType_Async:
        result = dim_init_async(context->dimChannel,
                                (DIM2LLD_ChannelDirection_TX == dir), channelAddress, bufferSize);
        enable_mlb_interrupt();
        return (DIM_NO_ERROR == result);
    case DIM2LLD_ChannelType_Sync:
        result = dim_init_sync(context->dimChannel,
                               (DIM2LLD_ChannelDirection_TX == dir), channelAddress, subSize);
        enable_mlb_interrupt();
        return (DIM_NO_ERROR == result);
    case DIM2LLD_ChannelType_Isoc:
        result = dim_init_isoc(context->dimChannel,
                               (DIM2LLD_ChannelDirection_TX == dir), channelAddress, subSize);
        enable_mlb_interrupt();
        return (DIM_NO_ERROR == result);
    default:
        enable_mlb_interrupt();
        assert(false);
        return false;
    }
}

void DIM2LLD_Deinit(void)
{
    uint16_t i;
    assert(lc.initialized);
    if (!lc.initialized)
        return;
    for (i = 0; i < (sizeof(lc.controlLookupTable) / sizeof(ChannelContext_t)); i++)
        CleanUpContext(&lc.controlLookupTable[i]);
    for (i = 0; i < (sizeof(lc.asyncLookupTable) / sizeof(ChannelContext_t)); i++)
        CleanUpContext(&lc.asyncLookupTable[i]);
    for (i = 0; i < (sizeof(lc.syncLookupTable) / sizeof(ChannelContext_t)); i++)
        CleanUpContext((ChannelContext_t *)&lc.syncLookupTable[i]);
    for (i = 0; i < (sizeof(lc.isocLookupTable) / sizeof(ChannelContext_t)); i++)
        CleanUpContext((ChannelContext_t *)&lc.isocLookupTable[i]);
    disable_mlb_interrupt();
    dim_shutdown();
    lc.initialized = false;
}

static void ServiceTxChannel(ChannelContext_t *context)
{
    uint32_t amountTx, i;
    uint16_t done_buffers;
    struct dim_ch_state_t st = { 0 };
    QueueEntry_t *entry;
    assert(lc.initialized);
    if (!lc.initialized)
        return;
    if (NULL == context || !context->channelUsed)
        return;
    assert(NULL != context->ringBuffer);
    assert(NULL != context->dimChannel);
    assert(DIM2LLD_ChannelDirection_TX == context->dir);
    disable_mlb_interrupt();
    dim_service_channel(context->dimChannel);
    enable_mlb_interrupt();

    //Try to release elements from hardware buffer:
    done_buffers = dim_get_channel_state(context->dimChannel, &st)->done_buffers;
    if (0 != done_buffers) {
        disable_mlb_interrupt();
        dim_detach_buffers(context->dimChannel, done_buffers);
        enable_mlb_interrupt();
    }
    for (i = 0; i < done_buffers; i++)
        RingBuffer_PopReadPtr(context->ringBuffer);

    //Try to enqueue new elements into hardware buffer:
    amountTx = RingBuffer_GetReadElementCount(context->ringBuffer);
    for (i = 0; i < amountTx; i++) {
        if (!dim_get_channel_state(context->dimChannel, &st)->ready)
            break;
        entry = (QueueEntry_t *)RingBuffer_GetReadPtrPos(context->ringBuffer, i);
        assert(NULL != entry);
        if (NULL == entry || 0 == entry->payloadLen || entry->hwEnqueued)
            continue;
        disable_mlb_interrupt();
        if (dim_dbr_space(context->dimChannel) < entry->payloadLen) {
            enable_mlb_interrupt();
            break;
        }
        if (dim_enqueue_buffer(context->dimChannel, (uint32_t)entry->buffer,
                               entry->payloadLen)) {
            enable_mlb_interrupt();
            entry->hwEnqueued = true;
            ExecuteLLDTrace(context->cType, context->dir, entry->buffer, entry->payloadLen);
        } else {
            enable_mlb_interrupt();
            break;
        }
    }
}

static void ServiceRxChannel(ChannelContext_t *context)
{
    int32_t amountRx, i;
    uint16_t done_buffers;
    struct dim_ch_state_t st = { 0 };
    QueueEntry_t *entry;
    assert(lc.initialized);
    if (!lc.initialized)
        return;
    if (NULL == context || !context->channelUsed)
        return;
    assert(DIM2LLD_ChannelDirection_RX == context->dir);

    disable_mlb_interrupt();
    dim_service_channel(context->dimChannel);
    enable_mlb_interrupt();

    //Enqueue empty buffers into hardware
    while (NULL != (entry = (QueueEntry_t *)RingBuffer_GetWritePtr(
                                context->ringBuffer))) {
        if (!dim_get_channel_state(context->dimChannel, &st)->ready)
            break;

        disable_mlb_interrupt();
        if (dim_enqueue_buffer(context->dimChannel, (uint32_t)&entry->buffer[entry->offset],
                               entry->maxPayloadLen)) {
            enable_mlb_interrupt();
            entry->hwEnqueued = true;
            entry->packetCounter = context->lastPacketCount++;
            RingBuffer_PopWritePtr(context->ringBuffer);
        } else {
            enable_mlb_interrupt();
            break;
        }
    }

    //Handle filled RX buffers
    done_buffers = dim_get_channel_state(context->dimChannel, &st)->done_buffers;
    if (0 != done_buffers) {
        amountRx = RingBuffer_GetReadElementCount(context->ringBuffer);
        assert(done_buffers <= amountRx);
        for (i = 0; i < done_buffers && i < amountRx; i++) {
            entry = (QueueEntry_t *)RingBuffer_GetReadPtrPos(context->ringBuffer, i);
            assert(NULL != entry);
            if (NULL == entry || !entry->hwEnqueued)
                continue;
            if (DIM2LLD_ChannelType_Control == context->cType ||
                DIM2LLD_ChannelType_Async == context->cType)
                entry->payloadLen = (uint16_t)entry->buffer[entry->offset] * 256 + entry->buffer[entry->offset + 1] + 2;
            else
                entry->payloadLen = entry->maxPayloadLen;
            assert(entry->payloadLen <= entry->maxPayloadLen);
            ExecuteLLDTrace(context->cType, context->dir, entry->buffer, entry->payloadLen);
            entry->hwEnqueued = false;
            disable_mlb_interrupt();
            dim_detach_buffers(context->dimChannel, 1);
            enable_mlb_interrupt();
        }
    }
}

void DIM2LLD_Service(void)
{
    uint16_t i;
    assert(lc.initialized);
    if (!lc.initialized)
        return;

    //Handle TX channels
    ServiceTxChannel(&lc.controlLookupTable[DIM2LLD_ChannelDirection_TX]);
    ServiceTxChannel(&lc.asyncLookupTable[DIM2LLD_ChannelDirection_TX]);
    for (i = 0; i < MAX_CHANNEL_INSTANCES; i++) {
        ServiceTxChannel(&lc.syncLookupTable[DIM2LLD_ChannelDirection_TX][i]);
        ServiceTxChannel(&lc.isocLookupTable[DIM2LLD_ChannelDirection_TX][i]);
    }

    //Handle RX channels
    ServiceRxChannel(&lc.controlLookupTable[DIM2LLD_ChannelDirection_RX]);
    ServiceRxChannel(&lc.asyncLookupTable[DIM2LLD_ChannelDirection_RX]);
    for (i = 0; i < MAX_CHANNEL_INSTANCES; i++) {
        ServiceRxChannel(&lc.syncLookupTable[DIM2LLD_ChannelDirection_RX][i]);
        ServiceRxChannel(&lc.isocLookupTable[DIM2LLD_ChannelDirection_RX][i]);
    }
}

bool DIM2LLD_IsMlbLocked(void)
{
    assert(lc.initialized);
    if (!lc.initialized)
        return false;
    return dim_get_lock_state();
}

uint32_t DIM2LLD_GetQueueElementCount(DIM2LLD_ChannelType_t cType, DIM2LLD_ChannelDirection_t dir, uint8_t instance)
{
    ChannelContext_t *context;
    if (!lc.initialized)
        return 0;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context || !context->channelUsed)
        return 0;
    return RingBuffer_GetReadElementCount(context->ringBuffer);
}

uint16_t DIM2LLD_GetRxData(DIM2LLD_ChannelType_t cType, DIM2LLD_ChannelDirection_t dir,
                           uint8_t instance, uint32_t pos, const uint8_t **pBuffer, uint16_t *pOffset, uint8_t *pPacketCounter)
{
    ChannelContext_t *context;
    QueueEntry_t *entry;
    if (!lc.initialized)
        return 0;
    if (NULL == pBuffer)
        return 0;
    *pBuffer = NULL;
    if (NULL != pOffset)
        *pOffset = 0;
    if (NULL != pPacketCounter)
        *pPacketCounter = 0;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context || !context->channelUsed)
        return 0;
    assert(context->cType == cType && context->dir == dir && NULL != context->ringBuffer);
    entry = (QueueEntry_t *)RingBuffer_GetReadPtrPos(context->ringBuffer, pos);
    if (NULL == entry || entry->hwEnqueued)
        return 0;
    *pBuffer = entry->buffer;
    if (NULL != pOffset)
        *pOffset = entry->offset;
    if (NULL != pPacketCounter)
        *pPacketCounter = entry->packetCounter;
    return entry->payloadLen;
}

void DIM2LLD_ReleaseRxData(DIM2LLD_ChannelType_t cType,
                           DIM2LLD_ChannelDirection_t dir, uint8_t instance)
{
    ChannelContext_t *context;
    assert(lc.initialized);
    if (!lc.initialized)
        return;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context)
    {
        assert(false);
        return;
    }
    RingBuffer_PopReadPtr(context->ringBuffer);
}

uint16_t DIM2LLD_GetTxData(DIM2LLD_ChannelType_t cType,
                           DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint8_t **pBuffer)
{
    ChannelContext_t *context;
    QueueEntry_t *entry;
    if (!lc.initialized)
        return 0;
    if (NULL == pBuffer)
        return 0;
    *pBuffer = NULL;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context || !context->channelUsed)
        return 0;
    assert(context->cType == cType && context->dir == dir && NULL != context->ringBuffer);
    entry = (QueueEntry_t *)RingBuffer_GetWritePtr(context->ringBuffer);
    if (NULL == entry)
        return 0;
    *pBuffer = entry->buffer;
    return entry->maxPayloadLen;
}

void DIM2LLD_SendTxData(DIM2LLD_ChannelType_t cType,
                        DIM2LLD_ChannelDirection_t dir, uint8_t instance, uint32_t payloadLength)
{
    ChannelContext_t *context;
    QueueEntry_t *entry;
    assert(lc.initialized);
    assert(0 != payloadLength);
    if (!lc.initialized || 0 == payloadLength)
        return;
    context = GetDimContext(cType, dir, instance);
    if (NULL == context)
        return;
    assert(DIM2LLD_ChannelDirection_TX == context->dir) ;
    entry = (QueueEntry_t *)RingBuffer_GetWritePtr(context->ringBuffer);
    assert(NULL != entry);
    if (NULL == entry)
        return;
    entry->payloadLen = payloadLength;
    entry->hwEnqueued = false;
    RingBuffer_PopWritePtr(context->ringBuffer);
}

void on_mlb_int_isr(void)
{
    assert(lc.initialized);
    if (!lc.initialized)
        return;

    dim_service_mlb_int_irq();
}

void on_ahb0_int_isr(void)
{
    assert(lc.initialized);
    if (!lc.initialized)
        return;

    dim_service_ahb_int_irq(lc.allChannels);
}
<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_collision.h
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Node and MAC Address Collision Solver Component                                        */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#ifndef UCSI_COLLISION_H_
#define UCSI_COLLISION_H_

#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "ucs_api.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                            Public API                                */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Initializes the collision resolver module
 * \note Do not use any other function, before calling this method.
 *
 * \param pPriv - private data section of this instance
 */
void UCSICollision_Init(void);

/**
 * \brief Sets any pointer as parameter of the callback function UCSICollision_CB_OnProgramIdentString.
 *
 * \param userPtr - Any pointer allowed
 */
void UCSICollision_SetUserPtr(void *userPtr);

/**
 * \brief Sets the expected amount of network nodes in the ring (MPR). 
 *        Programming will only take place, if expected node count is like the found node count.
 * \note This value is given by the user
 * \note Values over 64 will be silently ignored
 *
 * \param nodeCount - private data section of this instance
 */
void UCSICollision_SetExpectedNodeCount(uint8_t nodeCount);

/**
 * \brief Sets the found amount of network nodes in the ring (MPR). 
 *        Programming will only take place, if expected node count is like the found node count.
 * \note This value is given by the network
 * \note Values over 64 will be silently ignored
 *
 * \param nodeCount - private data section of this instance
 */
void UCSICollision_SetFoundNodeCount(uint8_t nodeCount);

/**
 * \brief Stores a found network node (by the UNICENS manager) into a lookup table.
 *
 * \param signature - The signature of the node (containing at least valid node address and MAC address)
 * \param collisionDetected - true, if UNICENS manager detected state which is not normal. false, node is valid
 */
void UCSICollision_StoreSignature(const Ucs_Signature_t *signature, bool collisionDetected);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                        CALLBACK SECTION                              */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Callback when the implementer needs to program the INIC
 *
 * \param signature - The signature of the node to be programmed
 * \param newIdentString - The data to be programmed
 * \param userPtr - The pointer given by UCSICollision_SetUserPtr function, otherwise NULL.
 */
extern void UCSICollision_CB_OnProgramIdentString(const Ucs_Signature_t *signature, 
    const Ucs_IdentString_t *newIdentString, void *userPtr);

/**
 * \brief Callback when the implementer needs to do final cleanup after flashing
 *
 * \param userPtr - The pointer given by UCSICollision_SetUserPtr function, otherwise NULL.
 */
extern void UCSICollision_CB_OnProgramDone(void *userPtr);

/**
 * \brief Callback to inform the implementer that there was no flashing required. The collision resolving finished without any changes.
 *
 * \param userPtr - The pointer given by UCSICollision_SetUserPtr function, otherwise NULL.
 */
extern void UCSICollision_CB_FinishedWithoutChanges(void *userPtr);

#endif /* UCSI_COLLISION_H_ */<file_sep>/audio-source/samv71-ucs/src/driver/dim2/board/dim2_hardware.c
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include "samv71.h"
#include "board.h"
#include "dim2_hardware.h"
#include "Console.h"

void enable_mlb_clock(void)
{
    volatile Pmc *pmc = PMC;
    pmc->PMC_PCR = PMC_PCR_EN |
                   PMC_PCR_CMD |
                   PMC_PCR_DIV_PERIPH_DIV_MCK |
                   PMC_PCR_PID(ID_MLB);
    pmc->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD | PMC_WPMR_WPEN;
    pmc->PMC_PCER1 = PMC_PCER1_PID53;
    pmc->PMC_WPMR = PMC_WPMR_WPKEY_PASSWD;
}

//Warning: Using the MLB pins will disable the virtual UART over USB :-(
void initialize_mlb_pins(void)
{
#define PIN_MLBCLK  {PIO_PB4, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
#define PIN_MLBDAT  {PIO_PB5, PIOB, ID_PIOB, PIO_PERIPH_C, PIO_DEFAULT}
#define PIN_MLBSIG  {PIO_PD10, PIOD, ID_PIOD, PIO_PERIPH_D, PIO_DEFAULT}

    static const Pin pinsMlb[] = {PIN_MLBCLK, PIN_MLBDAT, PIN_MLBSIG};
    PIO_Configure(pinsMlb, 3);

    MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO4;
    MATRIX->CCFG_SYSIO |= CCFG_SYSIO_SYSIO5;
}

void enable_mlb_interrupt(void)
{
    NVIC_EnableIRQ(AHB0_INT_IRQn);
    NVIC_EnableIRQ(MLB_INT_IRQn);
}

void disable_mlb_interrupt(void)
{
    NVIC_DisableIRQ(MLB_INT_IRQn);
    NVIC_DisableIRQ(AHB0_INT_IRQn);
}

uint32_t dimcb_io_read(uint32_t  *ptr32)
{
    assert(NULL != ptr32);
    return *ptr32; //No MMU, so it's easy
}

void dimcb_io_write(uint32_t  *ptr32, uint32_t value)
{
    assert(NULL != ptr32);
    *ptr32 = value; //No MMU, so it's easy
}

void dimcb_on_error(uint8_t error_id, const char *error_message)
{
    ConsolePrintf(PRIO_ERROR, RED "dim2-hal error:%d, '%s'" RESETCOLOR"\r\n", error_id, error_message);
}

void mlb_int_handler(void)
{
    irqflags_t flags = cpu_irq_save();

    on_mlb_int_isr();
    cpu_irq_restore(flags);
}

void ahb0_int_handler(void)
{
    irqflags_t flags = cpu_irq_save();

    on_ahb0_int_isr();
    cpu_irq_restore(flags);
}
<file_sep>/audio-source/samv71-ucs/src/driver/dim2/hal/dim2_hal.h
/*
 * dim2_hal.h - DIM2 HAL interface
 * (MediaLB, Device Interface Macro IP, OS62420)
 *
 * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This file is licensed under GPLv2.
 */

#ifndef _DIM2_HAL_H
#define _DIM2_HAL_H

#include <stdint.h>
#include <stdbool.h>
#include "dim2_reg.h"
#include "dim2_errors.h"

#ifdef __cplusplus
extern "C" {
#endif

/*
 * The values below are specified in the hardware specification.
 * So, they should not be changed until the hardware specification changes.
 */
enum mlb_clk_speed {
	CLK_256FS = 0,
	CLK_512FS = 1,
	CLK_1024FS = 2,
	CLK_2048FS = 3,
	CLK_3072FS = 4,
	CLK_4096FS = 5,
	CLK_6144FS = 6,
	CLK_8192FS = 7,
};

struct dim_ch_state_t {
	bool ready; /* Shows readiness to enqueue next buffer */
	uint16_t done_buffers; /* Number of completed buffers */
};

struct int_ch_state {
	/* changed only in interrupt context */
	volatile int request_counter;

	/* changed only in task context */
	volatile int service_counter;

	uint8_t idx1;
	uint8_t idx2;
	uint8_t level; /* [0..2], buffering level */
};

struct dim_channel {
	struct int_ch_state state;
	uint8_t addr;
	uint16_t dbr_addr;
	uint16_t dbr_size;
	uint16_t packet_length; /*< Isochronous packet length in bytes. */
	uint16_t bytes_per_frame; /*< Synchronous bytes per frame. */
	uint16_t done_sw_buffers_number; /*< Done software buffers number. */
};

uint8_t dim_startup(struct dim2_regs *dim_base_address, uint32_t mlb_clock, uint32_t fcnt);

void dim_shutdown(void);

bool dim_get_lock_state(void);

uint16_t dim_norm_ctrl_async_buffer_size(uint16_t buf_size);

uint16_t dim_norm_isoc_buffer_size(uint16_t buf_size, uint16_t packet_length);

uint16_t dim_norm_sync_buffer_size(uint16_t buf_size, uint16_t bytes_per_frame);

uint8_t dim_init_control(struct dim_channel *ch, uint8_t is_tx, uint16_t ch_address,
		    uint16_t max_buffer_size);

uint8_t dim_init_async(struct dim_channel *ch, uint8_t is_tx, uint16_t ch_address,
		  uint16_t max_buffer_size);

uint8_t dim_init_isoc(struct dim_channel *ch, uint8_t is_tx, uint16_t ch_address,
		 uint16_t packet_length);

uint8_t dim_init_sync(struct dim_channel *ch, uint8_t is_tx, uint16_t ch_address,
		 uint16_t bytes_per_frame);

uint8_t dim_destroy_channel(struct dim_channel *ch);

void dim_service_mlb_int_irq(void);

void dim_service_ahb_int_irq(struct dim_channel *const *channels);

uint8_t dim_service_channel(struct dim_channel *ch);

struct dim_ch_state_t *dim_get_channel_state(struct dim_channel *ch,
					     struct dim_ch_state_t *state_ptr);

uint16_t dim_dbr_space(struct dim_channel *ch);

bool dim_enqueue_buffer(struct dim_channel *ch, uint32_t buffer_addr,
			uint16_t buffer_size);

bool dim_detach_buffers(struct dim_channel *ch, uint16_t buffers_number);

uint32_t dimcb_io_read(uint32_t *ptr32);

void dimcb_io_write(uint32_t *ptr32, uint32_t value);

void dimcb_on_error(uint8_t error_id, const char *error_message);

#ifdef __cplusplus
}
#endif

#endif /* _DIM2_HAL_H */
<file_sep>/audio-source/samv71-ucs/src/driver/dim2/internal/ringbuffer.h
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_

#include <stdint.h>
#include <stdbool.h>

typedef struct {
    volatile uint32_t dataQueue;
    volatile uint32_t pRx;
    volatile uint32_t pTx;
    volatile uint32_t amountOfEntries;
    volatile uint32_t sizeOfEntry;
    volatile uint32_t rxPos;
    volatile uint32_t txPos;
} RingBuffer_t;

/*----------------------------------------------------------*/
/*! \brief Initializes the given RingBuffer structure
* \note This function must be called before any other functions of this component.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
* \param amountOfEntries - How many entries can be stored in the ring buffer.
* \param workingBuffer - Memory area which is exactly (amountOfEntries * sizeOfEntry) bytes.
*/
/*----------------------------------------------------------*/
void RingBuffer_Init(RingBuffer_t *rb, uint16_t amountOfEntries,
                     uint32_t sizeOfEntry, void *workingBuffer);

/*----------------------------------------------------------*/
/*! \brief Deinitializes the given RingBuffer structure
* \note After this function, all functions, except of RingBuffer_Init, must not be called.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
*/
/*----------------------------------------------------------*/
void RingBuffer_Deinit(RingBuffer_t *rb);

/*----------------------------------------------------------*/
/*! \brief Gets the amount of entries stored.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
* \return The amount of filled RX entries, which may be accessed via RingBuffer_GetReadPtrPos.
*/
/*----------------------------------------------------------*/
uint32_t RingBuffer_GetReadElementCount(RingBuffer_t *rb);

/*----------------------------------------------------------*/
/*! \brief Gets the head data from the ring buffer in order to read, if available.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
* \return Pointer to the oldest enqueued void structure, if data is available, NULL otherwise.
*/
/*----------------------------------------------------------*/
void *RingBuffer_GetReadPtr(RingBuffer_t *rb);

/*----------------------------------------------------------*/
/*! \brief Gets the head data from the ring buffer in order to read, if available.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
* \param pos - The position to read, starting with 0 for the oldest entry. Use RingBuffer_GetReadElementCount to get maximum pos count (max -1).
* \return Pointer to the enqueued void structure on the given position, if data is available, NULL otherwise.
*/
/*----------------------------------------------------------*/
void *RingBuffer_GetReadPtrPos(RingBuffer_t *rb, uint32_t pos);

/*----------------------------------------------------------*/
/*! \brief Marks the oldest available entry as invalid for reading, so it can be reused by TX functions.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
*/
/*----------------------------------------------------------*/
void RingBuffer_PopReadPtr(RingBuffer_t *rb);

/*----------------------------------------------------------*/
/*! \brief Gets the head data from the ring buffer in order to write, if available.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
* \return Pointer to the a free void structure, so user can fill data into.
*/
/*----------------------------------------------------------*/
void *RingBuffer_GetWritePtr(RingBuffer_t *rb);

/*----------------------------------------------------------*/
/*! \brief Marks the packet filled by RingBuffer_GetWritePtr as ready to read.
* \note After this call, the structure, got from RingBuffer_GetWritePtr, must not be written anymore.
* \param rb - Pointer to the RingBuffer_t structure, must not be NULL.
*/
/*----------------------------------------------------------*/
void RingBuffer_PopWritePtr(RingBuffer_t *rb);

#endif /* RINGBUFFER_H_ */<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_cfg.h
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Integration Helper Component                                                           */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#ifndef UNICENSINTEGRATION_H_
#define UNICENSINTEGRATION_H_

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                  USER ADJUSTABLE VALUES                              */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
#ifdef DEBUG
#define ENABLE_INIC_WATCHDOG    (false)
#else
#define ENABLE_INIC_WATCHDOG    (true)
#endif
#define ENABLE_AMS_LIB          (true)
#define DEBUG_XRM
#define ENABLE_RESOURCE_PRINT
#define BOARD_PMS_TX_SIZE       (72)
#define CMD_QUEUE_LEN           (8)
#define I2C_WRITE_MAX_LEN       (32)
#define AMS_MSG_MAX_LEN         (45)
#define MAX_NODES               (8)

#include <string.h>
#include <stdarg.h>

#include "ucs_cfg.h"
#include "ucs_api.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                          PRIVATE SECTION                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Internal enum for UNICENS Integration
 */
typedef enum
{
    /**Result is OK and the processing is finished. Safe to dequeue this command.*/
    UniCmdResult_OK_ProcessFinished,
    /**Result is OK but the processing is ongoing. Must wait for callback.*/
    UniCmdResult_OK_NeedToWaitForCB,
    /**Result is error and the processing is finished. Safe to dequeue this command.*/
    UniCmdResult_ERROR_ProcessFinished
} UnicensCmdResult_t;

/**
 * \brief Internal enum for UNICENS Integration
 */
typedef enum
{
    UnicensCmd_Unknown,
    UnicensCmd_Init,
    UnicensCmd_Stop,
    UnicensCmd_RmSetRoute,
    UnicensCmd_NsRun,
    UnicensCmd_GpioCreatePort,
    UnicensCmd_GpioWritePort,
    UnicensCmd_I2CWrite,
    UnicensCmd_I2CRead,
    UnicensCmd_SendAmsMessage,
    UnicensCmd_NDStart,
    UnicensCmd_NDStop,
    UnicensCmd_NwStartup,
    UnicensCmd_NwShutdown,
    UnicensCmd_ProgIsRam,
    UnicensCmd_ProgIsRom,
    UnicensCmd_ProgInitAll,
    UnicensCmd_PacketFilterMode
} UnicensCmd_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    const Ucs_InitData_t *init_ptr;
} UnicensCmdInit_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    Ucs_Rm_Route_t *routePtr;
    bool isActive;
} UnicensCmdRmSetRoute_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t nodeAddress;
    Ucs_Ns_Script_t *scriptPtr;
    uint8_t scriptSize;
} UnicensCmdNsRun_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t destination;
    uint16_t debounceTime;
} UnicensCmdGpioCreatePort_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t destination;
    uint16_t mask;
    uint16_t data;
} UnicensCmdGpioWritePort_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t destination;
    bool isBurst;
    uint8_t blockCount;
    uint8_t slaveAddr;
    uint16_t timeout;
    uint8_t dataLen;
    uint8_t data[I2C_WRITE_MAX_LEN];
} UnicensCmdI2CWrite_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t destination;
    uint8_t slaveAddr;
    uint16_t timeout;
    uint8_t dataLen;
} UnicensCmdI2CRead_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    uint16_t msgId;
    uint16_t targetAddress;
    uint8_t pPayload[AMS_MSG_MAX_LEN];
    uint32_t payloadLen;
} UnicensCmdSendAmsMessage_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    Ucs_Signature_t signature;
    Ucs_IdentString_t ident_string;
} UnicensCmdProgIsRam_t;

/**
 * \brief Internal struct for UNICENS Integration
 * \note: currently identical to UnicensCmdProgIsRam_t, but maybe different in future
 */
typedef struct
{
    Ucs_Signature_t signature;
    Ucs_IdentString_t ident_string;
} UnicensCmdProgIsRom_t;

/**
 * \brief Internal struct for UNICENS Integration
 * \note: currently identical to UnicensCmdProgIsRam_t, but maybe different in future
 */
typedef struct
{
    uint16_t destination_address;
    uint16_t mode;
} UnicensCmdPacketFilterMode_t;

/**
 * \brief Internal struct for UNICENS Integration
 */
typedef struct
{
    UnicensCmd_t cmd;
    union
    {
        UnicensCmdInit_t Init;
        UnicensCmdRmSetRoute_t RmSetRoute;
        UnicensCmdNsRun_t NsRun;
        UnicensCmdGpioCreatePort_t GpioCreatePort;
        UnicensCmdGpioWritePort_t GpioWritePort;
        UnicensCmdI2CWrite_t I2CWrite;
        UnicensCmdI2CRead_t I2CRead;
        UnicensCmdProgIsRam_t ProgIsRam;
        UnicensCmdProgIsRom_t ProgIsRom;
        UnicensCmdPacketFilterMode_t PacketFilterMode;
#if (ENABLE_AMS_LIB)
        UnicensCmdSendAmsMessage_t SendAms;
#endif
    } val;
} UnicensCmdEntry_t;

/**
 * \brief Internal variables for one instance of UNICENS Integration
 * \note Never touch any of this fields!
 */
typedef struct {
    volatile uint8_t *dataQueue;
    volatile uint8_t *pRx;
    volatile uint8_t *pTx;
    volatile uint32_t amountOfEntries;
    volatile uint32_t sizeOfEntry;
    volatile uint32_t rxPos;
    volatile uint32_t txPos;
} RB_t;

/**
 * \brief Internal variables for one instance of UNICENS Integration
 * \note Allocate this structure for each instance (static or malloc)
 *        and pass it to UCSI_Init()
 * \note Never touch any of this fields!
 */
typedef struct
{
    uint32_t magic;
    void *tag;
    bool initialized;
    bool ndRunning;
    bool programmingMode;
    bool programmingJobsTotal;
    bool programmingJobsFinished;
    Ucs_Rm_Route_t *pendingRoutePtr;
    RB_t rb;
    uint8_t rbBuf[(CMD_QUEUE_LEN * sizeof(UnicensCmdEntry_t))];
    Ucs_Inst_t *unicens;
    Ucs_InitData_t uniInitData;
    bool triggerService;
    Ucs_Lld_Api_t *uniLld;
    void *uniLldHPtr;
    UnicensCmdEntry_t *currentCmd;
    bool printTrigger;
} UCSI_Data_t;

#endif /* UNICENSINTEGRATION_H_ */<file_sep>/audio-source/samv71-ucs/src/board_init.h
/*------------------------------------------------------------------------------------------------*/
/* Board Init Component                                                                           */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

/*----------------------------------------------------------*/
/*! \file
 *  \brief This file contains board initialization code.
 *         It was introduced to reduce the complexity of the main.cpp file.
 */
/*----------------------------------------------------------*/
#ifndef _BOARDINIT_H_
#define _BOARDINIT_H_
#ifdef __cplusplus
extern "C"
{
#endif

#include "board.h"
#include "gmacd.h"
#include "gmac_init.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*       Public available driver, initialized by this component         */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/** TWI driver instance */
extern Twid twid;

/** The GMAC driver instance */
extern sGmacd gGmacd;

/** The MACB driver instance */
extern GMacb gGmacb; ///

/** The DMA driver instance */
extern sXdmad xdma;

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         Public typedefs                              */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

typedef enum
{
    BoardButton_SW0,
    BoardButton_SW1
} Board_Button_t;

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         Public functions                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/**
 * \brief Initializes the Board Support Component
 * \note Must be called before any other function of this component
 */
void Board_Init(void);

/**
 * \brief Checks if the given button is pressed
 * \param button - Enumeration specifying the button to check
 * \return true, if the button is currently pressed. false, otherwise
 */
bool Board_IsButtonPressed(Board_Button_t button);

#ifdef __cplusplus
}
#endif
#endif /* _BOARDINIT_H_ */<file_sep>/audio-source/samv71-ucs/src/gmac/gmii.h
/* ---------------------------------------------------------------------------- */
/*                  Atmel Microcontroller Software Support                      */
/*                       SAM Software Package License                           */
/* ---------------------------------------------------------------------------- */
/* Copyright (c) 2015, Atmel Corporation                                        */
/*                                                                              */
/* All rights reserved.                                                         */
/*                                                                              */
/* Redistribution and use in source and binary forms, with or without           */
/* modification, are permitted provided that the following condition is met:    */
/*                                                                              */
/* - Redistributions of source code must retain the above copyright notice,     */
/* this list of conditions and the disclaimer below.                            */
/*                                                                              */
/* Atmel's name may not be used to endorse or promote products derived from     */
/* this software without specific prior written permission.                     */
/*                                                                              */
/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
/* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.                           */
/* ---------------------------------------------------------------------------- */

#ifndef _GMII_DEFINE_H
#define _GMII_DEFINE_H


/*---------------------------------------------------------------------------
 *         Definitions
 *---------------------------------------------------------------------------*/

//IEEE defined Registers
#define GMII_BMCR        0x0   // Basic Mode Control Register
#define GMII_BMSR        0x1   // Basic Mode Status Register
#define GMII_PHYID1R     0x2   // PHY Identifier Register 1
#define GMII_PHYID2R     0x3   // PHY Identifier Register 2
#define GMII_ANAR        0x4   // Auto_Negotiation Advertisement Register
#define GMII_ANLPAR      0x5   // Auto_negotiation Link Partner Ability Register
#define GMII_ANER        0x6   // Auto-negotiation Expansion Register
#define GMII_ANNPR       0x7   // Auto-negotiation Next Page Register
#define GMII_ANLPNPAR    0x8   // Auto_negotiation Link Partner Next Page Ability Register
#define GMII_AFEC0R      0x11  // AFE Control 0 Register
#define GMII_AFEC3R      0x14  // AFE Control 3 Register
#define GMII_RXERCR      0x15  // RXER Counter Register
#define GMII_OMSSR       0x17  // Operation Mode Strap Status Register
#define GMII_ECR         0x18  // Expanded Control Register
#define GMII_ICSR        0x1B  // Interrupt Control/Status Register
#define GMII_FC          0x1C  // Function Control
#define GMII_LCSR        0x1D  // LinkMDŽ Control/Status Register
#define GMII_PC1R        0x1E  // PHY Control 1 Register
#define GMII_PC2R        0x1F  // PHY Control 2 Register

// PHY ID Identifier Register
#define GMII_LSB_MASK           0x0U
// definitions: MII_PHYID1
#define GMII_OUI_MSB            0x0022
// definitions: MII_PHYID2
#define GMII_OUI_LSB            0x1572          // KSZ8061 PHY Id2

// Basic Mode Control Register (BMCR)
// Bit definitions: MII_BMCR
#define GMII_RESET             (1u << 15) // 1= Software Reset; 0=Normal Operation
#define GMII_LOOPBACK          (1u << 14) // 1=loopback Enabled; 0=Normal Operation
#define GMII_SPEED_SELECT_LSB  (1u << 13) // 1,0=1000Mbps 0,1=100Mbps; 0,0=10Mbps
#define GMII_AUTONEG           (1u << 12) // Auto-negotiation Enable
#define GMII_POWER_DOWN        (1u << 11) // 1=Power down 0=Normal operation
#define GMII_ISOLATE           (1u << 10) // 1 = Isolates 0 = Normal operation
#define GMII_RESTART_AUTONEG   (1u << 9)  // 1 = Restart auto-negotiation 0 = Normal operation
#define GMII_DUPLEX_MODE       (1u << 8)  // 1 = Full duplex operation 0 = Normal operation
//      Reserved                7        // Read as 0, ignore on write
#define GMII_SPEED_SELECT_MSB  (1u << 6)  // 
//      Reserved                5 to 0   // Read as 0, ignore on write


// Basic Mode Status Register (BMSR)
// Bit definitions: MII_BMSR
#define GMII_100BASE_T4        (1 << 15) // 100BASE-T4 Capable
#define GMII_100BASE_TX_FD     (1 << 14) // 100BASE-TX Full Duplex Capable
#define GMII_100BASE_T4_HD     (1 << 13) // 100BASE-TX Half Duplex Capable
#define GMII_10BASE_T_FD       (1 << 12) // 10BASE-T Full Duplex Capable
#define GMII_10BASE_T_HD       (1 << 11) // 10BASE-T Half Duplex Capable
//      Reserved                10 to 9  // Read as 0, ignore on write
#define GMII_EXTEND_STATUS     (1 << 8)  // 1 = Extend Status Information In Reg 15
//      Reserved                7
#define GMII_MF_PREAMB_SUPPR   (1 << 6)  // MII Frame Preamble Suppression
#define GMII_AUTONEG_COMP      (1 << 5)  // Auto-negotiation Complete
#define GMII_REMOTE_FAULT      (1 << 4)  // Remote Fault
#define GMII_AUTONEG_ABILITY   (1 << 3)  // Auto Configuration Ability
#define GMII_LINK_STATUS       (1 << 2)  // Link Status
#define GMII_JABBER_DETECT     (1 << 1)  // Jabber Detect
#define GMII_EXTEND_CAPAB      (1 << 0)  // Extended Capability

// Auto-negotiation Advertisement Register (ANAR)
// Auto-negotiation Link Partner Ability Register (ANLPAR)
// Bit definitions: MII_ANAR, MII_ANLPAR
#define GMII_NP               (1 << 15) // Next page Indication
//      Reserved               7
#define GMII_RF               (1 << 13) // Remote Fault
//      Reserved               12       // Write as 0, ignore on read
#define GMII_PAUSE_MASK       (3 << 11) // 0,0 = No Pause 1,0 = Asymmetric Pause(link partner)
										// 0,1 = Symmetric Pause 1,1 = Symmetric&Asymmetric Pause(local device)
#define GMII_T4               (1 << 9)  // 100BASE-T4 Support
#define GMII_TX_FDX           (1 << 8)  // 100BASE-TX Full Duplex Support
#define GMII_TX_HDX           (1 << 7)  // 100BASE-TX Support
#define GMII_10_FDX           (1 << 6)  // 10BASE-T Full Duplex Support
#define GMII_10_HDX           (1 << 5)  // 10BASE-T Support
//      Selector                 4 to 0   // Protocol Selection Bits
#define GMII_AN_IEEE_802_3      0x00001

#endif // #ifndef _MII_DEFINE_H
<file_sep>/audio-source/samv71-ucs/src/driver/dim2/internal/ringbuffer.c
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#include <stdlib.h>
#include <assert.h>
#include "ringbuffer.h"

void RingBuffer_Init(RingBuffer_t *rb, uint16_t amountOfEntries,
                     uint32_t sizeOfEntry, void *workingBuffer)
{
    assert(NULL != rb);
    assert(NULL != workingBuffer);
    rb->dataQueue = (uint32_t)workingBuffer;
    rb->pRx = (uint32_t)rb->dataQueue;
    rb->pTx = (uint32_t)rb->dataQueue;
    rb->amountOfEntries = amountOfEntries;
    rb->sizeOfEntry = sizeOfEntry;
    rb->rxPos = 0;
    rb->txPos = 0;
}

void RingBuffer_Deinit(RingBuffer_t *rb)
{
    assert(NULL != rb);
    rb->dataQueue = rb->amountOfEntries = rb->rxPos = rb->txPos = rb->pRx = rb->pTx = 0;
}

uint32_t RingBuffer_GetReadElementCount(RingBuffer_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    return (uint32_t)(rb->txPos - rb->rxPos);
}

void *RingBuffer_GetReadPtr(RingBuffer_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    if (rb->txPos - rb->rxPos > 0)
        return (void *)rb->pRx;
    return NULL;
}

void *RingBuffer_GetReadPtrPos(RingBuffer_t *rb, uint32_t pos)
{
    uint32_t i, t;
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    if (rb->txPos - rb->rxPos <= pos)
        return NULL;
    t = rb->pRx;
    for (i = 0; i < pos; i++) {
        t += rb->sizeOfEntry;
        if (t >= (uint32_t)rb->dataQueue + (rb->amountOfEntries * rb->sizeOfEntry))
            t = rb->dataQueue;
    }
    return (void *)t;
}

void RingBuffer_PopReadPtr(RingBuffer_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    
    rb->pRx += rb->sizeOfEntry;
    if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
        rb->pRx = rb->dataQueue;
    ++rb->rxPos;
    assert(rb->txPos >= rb->rxPos);
}

void *RingBuffer_GetWritePtr(RingBuffer_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    if (rb->txPos - rb->rxPos < rb->amountOfEntries)
        return (void *)rb->pTx;
    return NULL;
}

void RingBuffer_PopWritePtr(RingBuffer_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    rb->pTx += rb->sizeOfEntry;
    if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
        rb->pTx = rb->dataQueue;
    ++rb->txPos;
    assert(rb->txPos >= rb->rxPos);
}<file_sep>/audio-source/samv71-ucs/libraries/libchip/include/qspi.h
/* ---------------------------------------------------------------------------- */
/*                  Atmel Microcontroller Software Support                      */
/*                       SAM Software Package License                           */
/* ---------------------------------------------------------------------------- */
/* Copyright (c) 2015, Atmel Corporation                                        */
/*                                                                              */
/* All rights reserved.                                                         */
/*                                                                              */
/* Redistribution and use in source and binary forms, with or without           */
/* modification, are permitted provided that the following condition is met:    */
/*                                                                              */
/* - Redistributions of source code must retain the above copyright notice,     */
/* this list of conditions and the disclaimer below.                            */
/*                                                                              */
/* Atmel's name may not be used to endorse or promote products derived from     */
/* this software without specific prior written permission.                     */
/*                                                                              */
/* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
/* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
/* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.                           */
/* ---------------------------------------------------------------------------- */


/**
 * \file
 *
 * Interface for Serial Peripheral Interface (SPI) controller.
 *
 */

#ifndef _QSPI_
#define _QSPI_
/*----------------------------------------------------------------------------
 *        Macros
 *----------------------------------------------------------------------------*/

/**
 *
 * Here are several macros which should be used when configuring a SPI
 * peripheral.
 *
 * \section qspi_configuration_macros SPI Configuration Macros
 * - \ref QSPI_PCS
 * - \ref QSPI_SCBR
 * - \ref QSPI_DLYBS
 * - \ref QSPI_DLYBCT
 */

/** Calculates the value of the CSR SCBR field given the baudrate and MCK. */
#define QSPI_SCBR(baudrate, masterClock) \
	((uint32_t) (masterClock / baudrate) << 8)

/** Calculates the value of the CSR DLYBS field given the desired delay (in ns) */
#define QSPI_DLYBS(delay, masterClock) \
	((uint32_t) (((masterClock / 1000000) * delay) / 1000) << 16)

/** Calculates the value of the CSR DLYBCT field given the desired delay (in ns) */
#define QSPI_DLYBCT(delay, masterClock) \
	((uint32_t) (((masterClock / 1000000) * delay) / 32000) << 24)

/*--------------------------------------------------------------------------- */

#ifdef __cplusplus
extern "C" {
#endif

/*----------------------------------------------------------------------------
 *        Exported functions
 *----------------------------------------------------------------------------*/

/** \brief qspi access modes
 */
typedef enum {
	CmdAccess = 0,
	ReadAccess,
	WriteAccess
} Access_t;

/** \brief qspi modes SPI or QSPI
 */
typedef enum {
	SpiMode = QSPI_MR_SMM_SPI,
	QspiMemMode = QSPI_MR_SMM_MEMORY
} QspiMode_t;


/** \brief qspi clock modes , regarding clock phase and clock polarity
 */
typedef enum {
	ClockMode_00 = 0,
	ClockMode_10,
	ClockMode_01,
	ClockMode_11
} QspiClockMode_t;


/** \brief qspi status codes
 */
typedef enum {
	QSPI_SUCCESS = 0,
	QSPI_BUSY,
	QSPI_BUSY_SENDING,
	QSPI_READ_ERROR,
	QSPI_WRITE_ERROR,
	QSPI_UNKNOWN_ERROR,
	QSPI_INIT_ERROR,
	QSPI_INPUT_ERROR,
	QSPI_TOTAL_ERROR
} QspidStatus_t;


/** \brief qspi status regiter bits
 */
typedef enum {
	IsReceived    = QSPI_SR_RDRF,
	IsTxSent      = QSPI_SR_TDRE,
	IsTxEmpty     = QSPI_SR_TXEMPTY,
	IsOverrun     = QSPI_SR_OVRES,
	IsCsRise      = QSPI_SR_CSR,
	IsCsAsserted  = QSPI_SR_CSS,
	IsEofInst     = QSPI_SR_INSTRE,
	IsEnabled     = QSPI_SR_QSPIENS
} QspiStatus_t;

/** \brief qspi command structure
 */
typedef struct {
	uint8_t       Instruction;
	uint8_t       Option;
} QspiMemCmd_t;

/** \brief qspi buffer structure
 */
typedef struct {
	uint32_t      TxDataSize;     /* Tx buffer size */
	uint32_t      RxDataSize;     /* Rx buffer size */
	uint32_t      *pDataTx;       /* Tx buffer */
	uint32_t      *pDataRx;       /* Rx buffer */
} QspiBuffer_t;


/** \brief qspi frame structure for QSPI mode
 */
typedef struct {
	union _QspiInstFrame {
		uint32_t val;
		struct _QspiInstFrameBM {
			uint32_t bwidth: 3,         /** Width of QSPI Addr , inst data */
					 reserved0: 1,       /** Reserved*/
					 bInstEn: 1,        /** Enable Inst */
					 bAddrEn: 1,        /** Enable Address */
					 bOptEn: 1,         /** Enable Option */
					 bDataEn: 1,        /** Enable Data */
					 bOptLen: 2,        /** Option Length*/
					 bAddrLen: 1,       /** Addrs Length*/
					 reserved1: 1,       /** Option Length*/
					 bXfrType: 2,       /** Transfer type*/
					 bContinuesRead: 1, /** Continoues read mode*/
					 reserved2: 1,       /** Reserved*/
					 bDummyCycles: 5,   /**< Unicast hash match */
					 reserved3: 11;      /** Reserved*/
		} bm;
	} InstFrame;
	uint32_t       Addr;
} QspiInstFrame_t;

/** \brief qspi driver structure
 */
typedef struct {
	uint8_t           qspiId;         /* QSPI ID */
	Qspi              *pQspiHw;       /* QSPI Hw instance */
	QspiMode_t        qspiMode;       /* Qspi mode: SPI or QSPI */
	QspiMemCmd_t      qspiCommand;    /* Qspi command structure*/
	QspiBuffer_t      qspiBuffer;     /* Qspi buffer*/
	QspiInstFrame_t   *pQspiFrame;    /* Qspi QSPI mode Fram register informations*/
} Qspid_t;


void QSPI_SwReset(Qspi *pQspi);

void QSPI_Disable(Qspi *pQspi);

void QSPI_Enable(Qspi *pQspi);

QspidStatus_t QSPI_EndTransfer(Qspi *pQspi);

uint32_t QSPI_GetStatus(Qspi *pQspi, const QspiStatus_t rStatus);

void QSPI_ConfigureClock(Qspi *pQspi, QspiClockMode_t ClockMode,
						  uint32_t dwClockCfg);

QspidStatus_t QSPI_SingleReadSPI(Qspid_t *pQspid, uint16_t *const pData);

QspidStatus_t QSPI_MultiReadSPI(Qspid_t *pQspid, uint16_t *
								 const pData, uint32_t NumOfBytes);

QspidStatus_t QSPI_SingleWriteSPI(Qspid_t *pQspid, uint16_t const *pData);

QspidStatus_t QSPI_MultiWriteSPI(Qspid_t *pQspid, uint16_t const *pData ,
								  uint32_t NumOfBytes);

QspidStatus_t QSPI_EnableIt(Qspi *pQspi, uint32_t dwSources);

QspidStatus_t QSPI_DisableIt(Qspi *pQspi, uint32_t dwSources);

uint32_t QSPI_GetItMask(Qspi *pQspi);

uint32_t QSPI_GetEnabledItStatus(Qspi *pQspi);

QspidStatus_t QSPI_ConfigureInterface(Qspid_t *pQspid, QspiMode_t Mode,
									   uint32_t dwConfiguration);

QspidStatus_t QSPI_SendCommand(Qspid_t *pQspi, uint8_t const KeepCfg);

QspidStatus_t QSPI_SendCommandWithData(Qspid_t *pQspi, uint8_t const KeepCfg);

QspidStatus_t QSPI_ReadCommand(Qspid_t *pQspi,  uint8_t const KeepCfg);

QspidStatus_t QSPI_EnableMemAccess(Qspid_t *pQspi, uint8_t const KeepCfg,
									uint8_t ScrambleFlag);

QspidStatus_t QSPI_ReadWriteMem(Qspid_t *pQspid, Access_t const ReadWrite);

#ifdef __cplusplus
}
#endif

#endif /* #ifndef _QSPI_ */

<file_sep>/audio-source/samv71-ucs/src/driver/dim2/board/dim2_hardware.h
/*------------------------------------------------------------------------------------------------*/
/* DIM2 LOW LEVEL DRIVER                                                                          */
/* (c) 2017 Microchip Technology Inc. and its subsidiaries.                                       */
/*                                                                                                */
/* You may use this software and any derivatives exclusively with Microchip products.             */
/*                                                                                                */
/* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR    */
/* STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT,       */
/* MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE, OR ITS INTERACTION WITH MICROCHIP       */
/* PRODUCTS, COMBINATION WITH ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.                      */
/*                                                                                                */
/* IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR        */
/* CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,    */
/* HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE       */
/* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS   */
/* IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE  */
/* PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.                                                  */
/*                                                                                                */
/* MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.            */
/*------------------------------------------------------------------------------------------------*/

#ifndef DIM2_HARDWARE_H_
#define DIM2_HARDWARE_H_

#include "dim2_hal.h"

//HARDWARE DEPENDEND:
#define DIM2_BASE_ADDRESS               ((struct dim2_regs *)0x40068000)
#define DIM2_MLB_SPEED                  (CLK_512FS)

void enable_mlb_clock(void);

void initialize_mlb_pins(void);

void enable_mlb_interrupt(void);

void disable_mlb_interrupt(void);

// to be implemented in LLD

void on_mlb_int_isr(void);

void on_ahb0_int_isr(void);

#endif /* DIM2_HARDWARE_H_ */
<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_impl.c
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Integration Helper Component                                                           */
/* Copyright 2017, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#include <assert.h>
#include <stdio.h>
#include "ucsi_api.h"
#include "ucsi_collision.h"
#include "ucsi_print.h"

/************************************************************************/
/* Private Definitions and variables                                    */
/************************************************************************/

#define TRACE_BUFFER_SZ 100
#define MAGIC (0xA144BEAF)
#define LOCAL_NODE_ADDR (0x1)
#define UNKNOWN_NODE_ADDR (0xFFFF)

#define LIB_VERSION_MAJOR   (2)
#define LIB_VERSION_MINOR   (2)
#define LIB_VERSION_RELEASE (0)
#define LIB_VERSION_BUILD   (4073)

static char m_traceBuffer[TRACE_BUFFER_SZ];
static Ucs_Signature_t PrgSignature = { 0x200 };
static Ucs_Rm_Node_t PrgNodes[] = {
{
    &PrgSignature,
    NULL,
    0
} };

/************************************************************************/
/* Throw error if UNICENS Library is not existent or wrong version      */
/************************************************************************/

#if !defined(UCS_VERSION_MAJOR) || !defined(UCS_VERSION_MINOR) || !defined(UCS_VERSION_RELEASE) || !defined(UCS_VERSION_BUILD)
#error UNICENS library is missing. Perform command 'git submodule update --init --recursive'
#endif
#if (UCS_VERSION_MAJOR != LIB_VERSION_MAJOR) ||  (UCS_VERSION_MINOR != LIB_VERSION_MINOR) || (UCS_VERSION_RELEASE != LIB_VERSION_RELEASE) || (UCS_VERSION_BUILD != LIB_VERSION_BUILD)
#error UNICENS library is outdated. Perform command 'git submodule update --init --recursive'
#endif

/************************************************************************/
/* Private Function Prototypes                                          */
/************************************************************************/
static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd);
static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd, bool success);
static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer);
static void *RB_GetReadPtr(RB_t *rb);
static void RB_PopReadPtr(RB_t *rb);
static void *RB_GetWritePtr(RB_t *rb);
static void RB_PopWritePtr(RB_t *rb);
static uint16_t OnUnicensGetTime(void *user_ptr);
static void OnUnicensService( void *user_ptr );
static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr );
static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr );
static void OnUnicensDebugErrorMsg(Ucs_Message_t *m, void *user_ptr);
static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr );
static void OnLldCtrlStop( void *lld_user_ptr );
static void OnLldResetInic(void *lld_user_ptr);
static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr );
static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr );
static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr);
static void OnUnicensNetworkStatus(uint16_t change_mask, uint16_t events, Ucs_Network_Availability_t availability,
    Ucs_Network_AvailInfo_t avail_info,Ucs_Network_AvailTransCause_t avail_trans_cause, uint16_t node_address,
    uint8_t max_position, uint16_t packet_bw, void *user_ptr);
static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
    Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
    Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr);
static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr);
static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr);
static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr);
static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr);
static void OnUcsMgrReport(Ucs_MgrReport_t code, Ucs_Signature_t *signature_ptr, Ucs_Rm_Node_t *node_ptr, void *user_ptr);
static void OnUcsNsRun(uint16_t node_address, Ucs_Ns_ResultCode_t result, Ucs_Ns_ErrorInfo_t error_info, void *ucs_user_ptr);
static void OnUcsAmsRxMsgReceived(void *user_ptr);
static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle,
    uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr);
static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle,
    uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr);
static void OnUcsI2CRead(uint16_t node_address, uint16_t i2c_port_handle,
            uint8_t i2c_slave_address, uint8_t data_len, uint8_t data_ptr[], Ucs_I2c_Result_t result, void *user_ptr);
static void OnUcsProgRam(Ucs_Prg_ResCode_t code, Ucs_Prg_Func_t function,
    uint8_t ret_len, uint8_t parm[], void *user_ptr);
static void OnUcsProgRom(Ucs_Prg_ResCode_t code, Ucs_Prg_Func_t function,
    uint8_t ret_len, uint8_t parm[], void *user_ptr);
static void OnUcsPacketFilterMode(uint16_t node_address, Ucs_StdResult_t result, void *user_ptr);
static void OnUcsNetworkStartup(Ucs_StdResult_t result, void *user_ptr);
static void OnUcsNetworkShutdown(Ucs_StdResult_t result, void *user_ptr);
#if ENABLE_AMS_LIB
static void OnUcsAmsWrite(Ucs_AmsTx_Msg_t* msg_ptr, Ucs_AmsTx_Result_t result, Ucs_AmsTx_Info_t info, void *user_ptr);
#endif

/************************************************************************/
/* Public Function Implementations                                      */
/************************************************************************/

void UCSI_Init(UCSI_Data_t *my, void *pTag)
{
    Ucs_Return_t result;
    assert(NULL != my);
    memset(my, 0, sizeof(UCSI_Data_t));
    my->magic = MAGIC;
    my->tag = pTag;
    my->unicens = Ucs_CreateInstance();
    if (NULL == my->unicens)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "Can not instance a new version of UNICENS, "\
            "increase UCS_NUM_INSTANCES define", 0);
        assert(false);
        return;
    }
    result = Ucs_SetDefaultConfig(&my->uniInitData);
    if(UCS_RET_SUCCESS != result)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "Can not set default values to UNICENS config (result=0x%X)", 1, result);
        assert(false);
        return;
    }
    my->uniInitData.user_ptr = my;
    my->uniInitData.mgr.report_fptr = OnUcsMgrReport;

    my->uniInitData.general.inic_watchdog_enabled = ENABLE_INIC_WATCHDOG;
    my->uniInitData.general.get_tick_count_fptr = &OnUnicensGetTime;
    my->uniInitData.general.request_service_fptr = &OnUnicensService;
    my->uniInitData.general.error_fptr = &OnUnicensError;
    my->uniInitData.general.set_application_timer_fptr = &OnUnicensAppTimer;
    my->uniInitData.general.debug_error_msg_fptr = &OnUnicensDebugErrorMsg;
    my->uniInitData.ams.enabled = ENABLE_AMS_LIB;
    my->uniInitData.ams.rx.message_received_fptr = &OnUcsAmsRxMsgReceived;
    my->uniInitData.network.status.notification_mask = 0xC2;
    my->uniInitData.network.status.cb_fptr = &OnUnicensNetworkStatus;

    my->uniInitData.lld.lld_user_ptr = my;
    my->uniInitData.lld.start_fptr =  &OnLldCtrlStart;
    my->uniInitData.lld.stop_fptr = &OnLldCtrlStop;
    my->uniInitData.lld.reset_fptr = &OnLldResetInic;
    my->uniInitData.lld.rx_available_fptr = &OnLldCtrlRxMsgAvailable;
    my->uniInitData.lld.tx_transmit_fptr = &OnLldCtrlTxTransmitC;

    my->uniInitData.rm.report_fptr = &OnUnicensRoutingResult;
    my->uniInitData.rm.debug_resource_status_fptr = &OnUnicensDebugXrmResources;

    my->uniInitData.gpio.trigger_event_status_fptr = &OnUcsGpioTriggerEventStatus;

    RB_Init(&my->rb, CMD_QUEUE_LEN, sizeof(UnicensCmdEntry_t), my->rbBuf);
    UCSICollision_Init();
    UCSICollision_SetUserPtr(my);
}

bool UCSI_RunInProgrammingMode(UCSI_Data_t *my, uint8_t amountOfNodes)
{
    UnicensCmdEntry_t *e;
    assert(MAGIC == my->magic);
    if (NULL == my) return false;
    my->programmingMode  = true;
    UCSICollision_SetExpectedNodeCount(amountOfNodes);
    if (my->initialized)
    {
        e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
        if (NULL == e) return false;
        e->cmd = UnicensCmd_Stop;
        RB_PopWritePtr(&my->rb);
    }
    my->uniInitData.mgr.packet_bw = 0;
    my->uniInitData.mgr.routes_list_ptr = NULL;
    my->uniInitData.mgr.routes_list_size = 0;
    my->uniInitData.mgr.nodes_list_ptr = PrgNodes;
    my->uniInitData.mgr.nodes_list_size = 1;
    my->uniInitData.mgr.enabled = false;
    e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
    if (NULL == e) return false;
    e->cmd =  UnicensCmd_Init;
    e->val.Init.init_ptr = &my->uniInitData;
    RB_PopWritePtr(&my->rb);
    e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
    if (NULL == e) return false;
    e->cmd =  UnicensCmd_NwStartup;
    RB_PopWritePtr(&my->rb);
    e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
    if (NULL == e) return false;
    e->cmd =  UnicensCmd_ProgInitAll;
    RB_PopWritePtr(&my->rb);
    e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
    if (NULL == e) return false;
    e->cmd =  UnicensCmd_NDStart;
    RB_PopWritePtr(&my->rb);
    UCSI_CB_OnServiceRequired(my->tag);
    return true;
}

bool UCSI_NewConfig(UCSI_Data_t *my,
    uint16_t packetBw, Ucs_Rm_Route_t *pRoutesList, uint16_t routesListSize,
    Ucs_Rm_Node_t *pNodesList, uint16_t nodesListSize)
{
    UnicensCmdEntry_t *e;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode) return false;
    if (my->initialized)
    {
        e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
        if (NULL == e) return false;
        e->cmd = UnicensCmd_Stop;
        RB_PopWritePtr(&my->rb);
    }
    my->uniInitData.mgr.packet_bw = packetBw;
    my->uniInitData.mgr.routes_list_ptr = pRoutesList;
    my->uniInitData.mgr.routes_list_size = routesListSize;
    my->uniInitData.mgr.nodes_list_ptr = pNodesList;
    my->uniInitData.mgr.nodes_list_size = nodesListSize;
    my->uniInitData.mgr.enabled = true;
    e = (UnicensCmdEntry_t *)RB_GetWritePtr(&my->rb);
    if (NULL == e) return false;
    e->cmd =  UnicensCmd_Init;
    e->val.Init.init_ptr = &my->uniInitData;
    RB_PopWritePtr(&my->rb);
    UCSI_CB_OnServiceRequired(my->tag);
    UCSIPrint_Init(pRoutesList, routesListSize, my);
    return true;
}

bool UCSI_ExecuteScript(UCSI_Data_t *my, uint16_t targetAddress, Ucs_Ns_Script_t *pScriptList, uint8_t scriptListLength)
{
    uint8_t i = 0;
    Ucs_Rm_Node_t *pNode = NULL;
    UnicensCmdEntry_t e;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode) return false;
    if (!my->initialized || !my->uniInitData.mgr.enabled
        || NULL == my->uniInitData.mgr.nodes_list_ptr || 0 == my->uniInitData.mgr.nodes_list_size
        || NULL == pScriptList || 0 == scriptListLength)
    {
        return false;
    }
    for (i = 0; i < my->uniInitData.mgr.nodes_list_size; i++)
    {
        Ucs_Rm_Node_t *pTempNode = &my->uniInitData.mgr.nodes_list_ptr[i];
        if (NULL == pTempNode)
            break;
        if (pTempNode->signature_ptr && targetAddress == pTempNode->signature_ptr->node_address)
        {
            /* Found correct node in List */
            pNode = pTempNode;
            break;
        }
    }
    if (NULL == pNode)
        return false;
    e.cmd = UnicensCmd_NsRun;
    e.val.NsRun.nodeAddress = targetAddress;
    e.val.NsRun.scriptPtr = pScriptList;
    e.val.NsRun.scriptSize = scriptListLength;
    return EnqueueCommand(my, &e);
}

bool UCSI_ProcessRxData(UCSI_Data_t *my,
    const uint8_t *pBuffer, uint32_t len)
{
    Ucs_Lld_RxMsg_t *msg = NULL;
    assert(MAGIC == my->magic);
    if (NULL == my->uniLld || NULL == my->uniLldHPtr) return false;
    msg = my->uniLld->rx_allocate_fptr(my->uniLldHPtr, len);
    if (NULL == msg)
    {
        /*This may happen by definition, OnLldCtrlRxMsgAvailable()
          will be called, once buffers are available again*/
        return false;
    }
    msg->data_size = len;
    memcpy(msg->data_ptr, pBuffer, len);
    my->uniLld->rx_receive_fptr(my->uniLldHPtr, msg);
    return true;
}

void UCSI_Service(UCSI_Data_t *my)
{
    UnicensCmdEntry_t *e;
    bool popEntry = true; /*Set to false in specific case, where function will callback asynchrony.*/
    assert(MAGIC == my->magic);
    if (NULL != my->unicens && my->triggerService) {
        my->triggerService = false;
        Ucs_Service(my->unicens);
    }
    if (my->printTrigger)
    {
        my->printTrigger = false;
        UCSIPrint_Service(UCSI_CB_OnGetTime(my->tag));
    }
    if (NULL != my->currentCmd) return;
    my->currentCmd = e = (UnicensCmdEntry_t *)RB_GetReadPtr(&my->rb);
    if (NULL == e) return;
    switch (e->cmd) {
        case UnicensCmd_Init:
            if (UCS_RET_SUCCESS == Ucs_Init(my->unicens, e->val.Init.init_ptr, OnUcsInitResult))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Init failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_Init, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_Stop:
            if (UCS_RET_SUCCESS == Ucs_Stop(my->unicens, OnUcsStopResult))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Stop failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_Stop, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_RmSetRoute:
            if (UCS_RET_SUCCESS == Ucs_Rm_SetRouteActive(my->unicens, e->val.RmSetRoute.routePtr, e->val.RmSetRoute.isActive))
            {
                my->pendingRoutePtr = e->val.RmSetRoute.routePtr;
                popEntry = false;
            } else  {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Rm_SetRouteActive failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_RmSetRoute, false, e->val.RmSetRoute.routePtr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address);
            }
            break;
        case UnicensCmd_NsRun:
            if (UCS_RET_SUCCESS != Ucs_Ns_Run(my->unicens, e->val.NsRun.nodeAddress, e->val.NsRun.scriptPtr, e->val.NsRun.scriptSize, OnUcsNsRun))
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Ns_Run failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NsRun, false, e->val.NsRun.nodeAddress);
            }
            break;
        case UnicensCmd_GpioCreatePort:
            if (UCS_RET_SUCCESS == Ucs_Gpio_CreatePort(my->unicens, e->val.GpioCreatePort.destination, 0, e->val.GpioCreatePort.debounceTime, OnUcsGpioPortCreate))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_CreatePort failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_GpioCreatePort, false, e->val.GpioCreatePort.destination);
            }
            break;
        case UnicensCmd_GpioWritePort:
            if (UCS_RET_SUCCESS == Ucs_Gpio_WritePort(my->unicens, e->val.GpioWritePort.destination, 0x1D00, e->val.GpioWritePort.mask, e->val.GpioWritePort.data, OnUcsGpioPortWrite))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Gpio_WritePort failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_GpioWritePort, false, e->val.GpioWritePort.destination);
            }
            break;
        case UnicensCmd_I2CWrite:
            if (UCS_RET_SUCCESS == Ucs_I2c_WritePort(my->unicens, e->val.I2CWrite.destination, 0x0F00,
                (e->val.I2CWrite.isBurst ? UCS_I2C_BURST_MODE : UCS_I2C_DEFAULT_MODE), e->val.I2CWrite.blockCount,
                e->val.I2CWrite.slaveAddr, e->val.I2CWrite.timeout, e->val.I2CWrite.dataLen, e->val.I2CWrite.data, OnUcsI2CWrite))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_I2c_WritePort failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_I2CWrite, false, e->val.I2CWrite.destination);
            }
            break;
        case UnicensCmd_I2CRead:
            if (UCS_RET_SUCCESS == Ucs_I2c_ReadPort(my->unicens, e->val.I2CRead.destination, 0x0F00,
                e->val.I2CRead.slaveAddr, e->val.I2CRead.dataLen, e->val.I2CRead.timeout, OnUcsI2CRead))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_I2c_ReadPort failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_I2CRead, false, e->val.I2CRead.destination);
            }
            break;
#if ENABLE_AMS_LIB
        case UnicensCmd_SendAmsMessage:
        {
            Ucs_AmsTx_Msg_t *msg;
            msg = Ucs_AmsTx_AllocMsg(my->unicens, e->val.SendAms.payloadLen);
            if (NULL == msg)
            {
                /* Try again later */
                popEntry = false;
                break;
            }
            if (0 != e->val.SendAms.payloadLen)
            {
                assert(NULL != msg->data_ptr);
                memcpy(msg->data_ptr, e->val.SendAms.pPayload, e->val.SendAms.payloadLen);
            }
            msg->custom_info_ptr = NULL;
            msg->data_size = e->val.SendAms.payloadLen;
            msg->destination_address = e->val.SendAms.targetAddress;
            msg->llrbc = 10;
            msg->msg_id = e->val.SendAms.msgId;
            if (UCS_RET_SUCCESS == Ucs_AmsTx_SendMsg(my->unicens, msg, OnUcsAmsWrite))
            {
                popEntry = false;
            }
            else
            {
                Ucs_AmsTx_FreeUnusedMsg(my->unicens, msg);
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_AmsTx_SendMsg failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_SendAmsMessage, false, e->val.SendAms.targetAddress);
            }
            break;
        }
#endif
        case UnicensCmd_ProgIsRam:
            if (UCS_RET_SUCCESS == Ucs_Prog_IS_RAM(my->unicens, &e->val.ProgIsRam.signature, &e->val.ProgIsRam.ident_string, OnUcsProgRam))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Prog_IS_RAM failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_ProgIsRam, false, e->val.ProgIsRam.signature.node_address);
            }
            break;
        case UnicensCmd_ProgIsRom:
            if (UCS_RET_SUCCESS == Ucs_Prog_IS_ROM(my->unicens, &e->val.ProgIsRom.signature, &e->val.ProgIsRom.ident_string, OnUcsProgRom))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Prog_IS_ROM failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_ProgIsRom, false, e->val.ProgIsRom.signature.node_address);
            }
            break;
        case UnicensCmd_NDStart:
            if (UCS_RET_SUCCESS == Ucs_Nd_Start(my->unicens))
            {
                my->ndRunning = true;
            } else  {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Nd_Start failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NDStart, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_NDStop:
            if (UCS_RET_SUCCESS == Ucs_Nd_Stop(my->unicens))
            {
                my->ndRunning = false;
            } else  {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Nd_Stop failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NDStop, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_NwStartup:
            if (UCS_RET_SUCCESS == Ucs_Network_Startup(my->unicens, 0, 0xFFFFU, OnUcsNetworkStartup))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Network_Startup failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NwStartup, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_NwShutdown:
            if (UCS_RET_SUCCESS == Ucs_Network_Shutdown(my->unicens, OnUcsNetworkShutdown))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Network_Shutdown failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NwShutdown, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_ProgInitAll:
            if (UCS_RET_SUCCESS == Ucs_Nd_InitAll(my->unicens))
            {
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_ProgInitAll, true, LOCAL_NODE_ADDR);
            } else {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Nd_InitAll failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_ProgInitAll, false, LOCAL_NODE_ADDR);
            }
            break;
        case UnicensCmd_PacketFilterMode:
            if (UCS_RET_SUCCESS == Ucs_Network_SetPacketFilterMode(my->unicens, e->val.PacketFilterMode.destination_address, e->val.PacketFilterMode.mode, OnUcsPacketFilterMode))
                popEntry = false;
            else
            {
                UCSI_CB_OnUserMessage(my->tag, true, "Ucs_Network_SetPacketFilterMode failed", 0);
                UCSI_CB_OnCommandResult(my->tag, UnicensCmd_PacketFilterMode, false, e->val.PacketFilterMode.destination_address);
            }
            break;
        default:
            assert(false);
            break;
    }
    if (popEntry)
    {
        my->currentCmd = NULL;
        RB_PopReadPtr(&my->rb);
    }
}

void UCSI_Timeout(UCSI_Data_t *my)
{
    assert(MAGIC == my->magic);
    if (NULL == my->unicens) return;
    Ucs_ReportTimeout(my->unicens);
    if (my->printTrigger)
    {
        my->printTrigger = false;
        UCSIPrint_Service(UCSI_CB_OnGetTime(my->tag));
    }
}

bool UCSI_SendAmsMessage(UCSI_Data_t *my, uint16_t msgId, uint16_t targetAddress, uint8_t *pPayload, uint32_t payloadLen)
{
#if ENABLE_AMS_LIB
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode) return false;
    if (payloadLen > AMS_MSG_MAX_LEN)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "SendAms was called with payload length=%d, allowed is=%d", 2, payloadLen, AMS_MSG_MAX_LEN);
        return false;
    }
    entry.cmd = UnicensCmd_SendAmsMessage;
    entry.val.SendAms.msgId = msgId;
    entry.val.SendAms.targetAddress = targetAddress;
    entry.val.SendAms.payloadLen = payloadLen;
    memcpy(entry.val.SendAms.pPayload, pPayload, payloadLen);
    return EnqueueCommand(my, &entry);
#else
    return false;
#endif
}

bool UCSI_GetAmsMessage(UCSI_Data_t *my, uint16_t *pMsgId, uint16_t *pSourceAddress, uint8_t **pPayload, uint32_t *pPayloadLen)
{
    Ucs_AmsRx_Msg_t *msg;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode || NULL == my->unicens || NULL == pPayload || NULL == pPayloadLen) return false;
    msg = Ucs_AmsRx_PeekMsg(my->unicens);
    if (NULL == msg) return false;
    *pMsgId = msg->msg_id;
    *pSourceAddress = msg->source_address;
    *pPayload = msg->data_ptr;
    *pPayloadLen = msg->data_size;
    return true;
}

void UCSI_ReleaseAmsMessage(UCSI_Data_t *my)
{
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode || NULL == my->unicens) return;
    Ucs_AmsRx_ReleaseMsg(my->unicens);
}

bool UCSI_SetRouteActive(UCSI_Data_t *my, uint16_t routeId, bool isActive)
{
    uint16_t i;
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode || NULL == my->uniInitData.mgr.routes_list_ptr) return false;
    for (i = 0; i < my->uniInitData.mgr.routes_list_size; i++)
    {
        Ucs_Rm_Route_t *route = &my->uniInitData.mgr.routes_list_ptr[i];
        if (route->route_id != routeId)
            continue;
        entry.cmd = UnicensCmd_RmSetRoute;
        entry.val.RmSetRoute.routePtr = route;
        entry.val.RmSetRoute.isActive = isActive;
        return EnqueueCommand(my, &entry);
    }
    return false;
}

bool UCSI_I2CWrite(UCSI_Data_t *my, uint16_t targetAddress, bool isBurst, uint8_t blockCount,
    uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen, const uint8_t *pData)
{
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode || NULL == pData || 0 == dataLen) return false;
    if (dataLen > I2C_WRITE_MAX_LEN)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "I2CWrite was called with payload length=%d, allowed is=%d", 2, dataLen, I2C_WRITE_MAX_LEN);
        return false;
    }
    entry.cmd = UnicensCmd_I2CWrite;
    entry.val.I2CWrite.destination = targetAddress;
    entry.val.I2CWrite.isBurst = isBurst;
    entry.val.I2CWrite.blockCount = blockCount;
    entry.val.I2CWrite.slaveAddr = slaveAddr;
    entry.val.I2CWrite.timeout = timeout;
    entry.val.I2CWrite.dataLen = dataLen;
    memcpy(entry.val.I2CWrite.data, pData, dataLen);
    return EnqueueCommand(my, &entry);
}

bool UCSI_I2CRead(UCSI_Data_t *my, uint16_t targetAddress, uint8_t slaveAddr, uint16_t timeout, uint8_t dataLen)
{
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode || 0 == dataLen) return false;
    entry.cmd = UnicensCmd_I2CRead;
    entry.val.I2CRead.destination = targetAddress;
    entry.val.I2CRead.slaveAddr = slaveAddr;
    entry.val.I2CRead.timeout = timeout;
    entry.val.I2CRead.dataLen = dataLen;
    return EnqueueCommand(my, &entry);
}

bool UCSI_SetGpioState(UCSI_Data_t *my, uint16_t targetAddress, uint8_t gpioPinId, bool isHighState)
{
    uint16_t mask;
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || my->programmingMode) return false;
    mask = 1 << gpioPinId;
    entry.cmd = UnicensCmd_GpioWritePort;
    entry.val.GpioWritePort.destination = targetAddress;
    entry.val.GpioWritePort.mask = mask;
    entry.val.GpioWritePort.data = isHighState ? mask : 0;
    return EnqueueCommand(my, &entry);
}

bool UCSI_ProgramIdentStringRam(UCSI_Data_t *my, const Ucs_Signature_t *signature, const Ucs_IdentString_t *newIdentString)
{
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my || !my->programmingMode || NULL == signature || NULL == newIdentString) return false;
    entry.cmd = UnicensCmd_ProgIsRam;
    memcpy(&entry.val.ProgIsRam.signature, signature, sizeof(Ucs_Signature_t));
    memcpy(&entry.val.ProgIsRam.ident_string, newIdentString, sizeof(Ucs_IdentString_t));
    return EnqueueCommand(my, &entry);
}

bool UCSI_ProgramIdentStringRom(UCSI_Data_t *my, const Ucs_Signature_t *signature, const Ucs_IdentString_t *newIdentString)
{
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my  || !my->programmingMode || NULL == signature || NULL == newIdentString) return false;
    entry.cmd = UnicensCmd_ProgIsRom;
    memcpy(&entry.val.ProgIsRom.signature, signature, sizeof(Ucs_Signature_t));
    memcpy(&entry.val.ProgIsRom.ident_string, newIdentString, sizeof(Ucs_IdentString_t));
    return EnqueueCommand(my, &entry);
}

bool UCSI_EnablePromiscuousMode(UCSI_Data_t *my, uint16_t targetAddress, bool enablePromiscuous)
{
    UnicensCmdEntry_t entry;
    assert(MAGIC == my->magic);
    if (NULL == my  || my->programmingMode) return false;
    entry.cmd = UnicensCmd_PacketFilterMode;
    entry.val.PacketFilterMode.destination_address = targetAddress;
    entry.val.PacketFilterMode.mode = enablePromiscuous ? 0xA : 0x0;
    return EnqueueCommand(my, &entry);
}

/************************************************************************/
/* Private Functions                                                    */
/************************************************************************/

static bool EnqueueCommand(UCSI_Data_t *my, UnicensCmdEntry_t *cmd)
{
    UnicensCmdEntry_t *e;
    if (NULL == my || NULL == cmd)
    {
        assert(false);
        return false;
    }
    e = RB_GetWritePtr(&my->rb);
    if (NULL == e)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "Could not enqueue command. Increase CMD_QUEUE_LEN define", 0);
        return false;
    }
    memcpy(e, cmd, sizeof(UnicensCmdEntry_t));
    RB_PopWritePtr(&my->rb);
    UCSI_CB_OnServiceRequired(my->tag);
    UCSIPrint_UnicensActivity();
    return true;
}

static void OnCommandExecuted(UCSI_Data_t *my, UnicensCmd_t cmd, bool success)
{
    UnicensCmdEntry_t *e;
    if (NULL == my)
    {
        assert(false);
        return;
    }
    e = my->currentCmd;
    if (NULL == e)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called, but no "\
            "command is in queue", 0);
        assert(false);
        return;
    }
    if (e->cmd != cmd)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "OnUniCommandExecuted was called with "\
            "wrong command (Expected=0x%X, Got=0x%X", 2, e->cmd, cmd);
        assert(false);
        return;
    }
    UCSIPrint_UnicensActivity();
    switch (e->cmd) {
        case UnicensCmd_Init:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, LOCAL_NODE_ADDR);
            break;
        case UnicensCmd_Stop:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, LOCAL_NODE_ADDR);
            break;
        case UnicensCmd_GpioCreatePort:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.GpioCreatePort.destination);
            break;
        case UnicensCmd_GpioWritePort:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.GpioWritePort.destination);
            break;
        case UnicensCmd_I2CWrite:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.I2CWrite.destination);
            break;
        case UnicensCmd_I2CRead:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.I2CRead.destination);
            break;
#if ENABLE_AMS_LIB
        case UnicensCmd_SendAmsMessage:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.SendAms.targetAddress);
            break;
#endif
        case UnicensCmd_ProgIsRam:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.ProgIsRam.signature.node_address);
            break;
        case UnicensCmd_ProgIsRom:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.ProgIsRom.signature.node_address);
            break;
        case UnicensCmd_PacketFilterMode:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.PacketFilterMode.destination_address);
            break;
        case UnicensCmd_RmSetRoute:
                UCSI_CB_OnCommandResult(my->tag, cmd, success, e->val.RmSetRoute.routePtr->sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address);
            break;
        default:
            UCSI_CB_OnCommandResult(my->tag, cmd, success, UNKNOWN_NODE_ADDR);
            break;
    }
    my->currentCmd = NULL;
    RB_PopReadPtr(&my->rb);
}

static void RB_Init(RB_t *rb, uint16_t amountOfEntries, uint32_t sizeOfEntry, uint8_t *workingBuffer)
{
    assert(NULL != rb);
    assert(NULL != workingBuffer);
    rb->dataQueue = workingBuffer;
    rb->pRx = rb->dataQueue;
    rb->pTx = rb->dataQueue;
    rb->amountOfEntries = amountOfEntries;
    rb->sizeOfEntry = sizeOfEntry;
    rb->rxPos = 0;
    rb->txPos = 0;
}

static void *RB_GetReadPtr(RB_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    if (rb->txPos - rb->rxPos > 0)
    return (void *)rb->pRx;
    return NULL;
}

static void RB_PopReadPtr(RB_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);

    rb->pRx += rb->sizeOfEntry;
    if (rb->pRx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
    rb->pRx = rb->dataQueue;
    ++rb->rxPos;
    assert(rb->txPos >= rb->rxPos);
}

static void *RB_GetWritePtr(RB_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    if (rb->txPos - rb->rxPos < rb->amountOfEntries)
    return (void *)rb->pTx;
    return NULL;
}

static void RB_PopWritePtr(RB_t *rb)
{
    assert(NULL != rb);
    assert(0 != rb->dataQueue);
    rb->pTx += rb->sizeOfEntry;
    if (rb->pTx >= rb->dataQueue + ( rb->amountOfEntries * rb->sizeOfEntry))
    rb->pTx = rb->dataQueue;
    ++rb->txPos;
    assert(rb->txPos >= rb->rxPos);
}

static uint16_t OnUnicensGetTime(void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    return UCSI_CB_OnGetTime(my->tag);
}

static void OnUnicensService( void *user_ptr )
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    my->triggerService = true;
    UCSI_CB_OnServiceRequired(my->tag);
}

static void OnUnicensError( Ucs_Error_t error_code, void *user_ptr )
{
    UnicensCmdEntry_t e;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    error_code = error_code;
    assert(MAGIC == my->magic);
    UCSI_CB_OnUserMessage(my->tag, true, "UNICENS general error, code=0x%X, restarting", 1, error_code);
    e.cmd = UnicensCmd_Init;
    e.val.Init.init_ptr = &my->uniInitData;
    EnqueueCommand(my, &e);
}

static void OnUnicensAppTimer( uint16_t timeout, void *user_ptr )
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnSetServiceTimer(my->tag, timeout);
}

static void OnUnicensDebugErrorMsg(Ucs_Message_t *m, void *user_ptr)
{
    char val[5];
    uint8_t i;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    m_traceBuffer[0] = '\0';
    for (i = 0; NULL != m->tel.tel_data_ptr && i < m->tel.tel_len; i++)
    {
        snprintf(val, sizeof(val), "%02X ", m->tel.tel_data_ptr[i]);
        strcat(m_traceBuffer, val);
    }
    UCSI_CB_OnUserMessage(my->tag, true, "Received error message, source=%x, %X.%X.%X.%X, [ %s ]",
        6, m->source_addr, m->id.fblock_id, m->id.instance_id,
        m->id.function_id, m->id.op_type, m_traceBuffer);
}

static void OnLldCtrlStart( Ucs_Lld_Api_t* api_ptr, void *inst_ptr, void *lld_user_ptr )
{
    UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
    assert(MAGIC == my->magic);
    my->uniLld = api_ptr;
    my->uniLldHPtr = inst_ptr;
    UCSI_CB_OnStart(my->tag);
}

static void OnLldCtrlStop( void *lld_user_ptr )
{
    UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
    assert(MAGIC == my->magic);
    my->uniLld = NULL;
    my->uniLldHPtr = NULL;
    UCSI_CB_OnStop(my->tag);
}

static void OnLldResetInic(void *lld_user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnResetInic(my->tag);
}

static void OnLldCtrlRxMsgAvailable( void *lld_user_ptr )
{
    UCSI_Data_t *my = (UCSI_Data_t *)lld_user_ptr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnServiceRequired(my->tag);
}

static void OnLldCtrlTxTransmitC( Ucs_Lld_TxMsg_t *msg_ptr, void *lld_user_ptr )
{
    UCSI_Data_t *my;
    Ucs_Mem_Buffer_t * buf_ptr;
    uint8_t buffer[BOARD_PMS_TX_SIZE];
    uint32_t bufferPos = 0;
    my = (UCSI_Data_t *)lld_user_ptr;
    assert(MAGIC == my->magic);
    if (NULL == msg_ptr || NULL == my || NULL == my->uniLld || NULL == my->uniLldHPtr)
    {
        assert(false);
        return;
    }
    for (buf_ptr = msg_ptr->memory_ptr; buf_ptr != NULL; buf_ptr = buf_ptr->next_buffer_ptr)
    {
        if (buf_ptr->data_size + bufferPos > sizeof(buffer))
        {
            UCSI_CB_OnUserMessage(my->tag, true, "TX buffer is too small, increase " \
                "BOARD_PMS_TX_SIZE define (%lu > %lu)", 2, buf_ptr->data_size + bufferPos, sizeof(buffer));
            my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
            return;
        }
        memcpy(&buffer[bufferPos], buf_ptr->data_ptr, buf_ptr->data_size);
        bufferPos += buf_ptr->data_size;
    }
    assert(bufferPos == msg_ptr->memory_ptr->total_size);
    my->uniLld->tx_release_fptr(my->uniLldHPtr, msg_ptr);
    UCSI_CB_OnTxRequest(my->tag, buffer, bufferPos);
}

static void OnUnicensRoutingResult(Ucs_Rm_Route_t* route_ptr, Ucs_Rm_RouteInfos_t route_infos, void *user_ptr)
{
    bool available;
    uint16_t conLabel;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    if (route_ptr == my->pendingRoutePtr)
    {
        OnCommandExecuted(my, UnicensCmd_RmSetRoute, (UCS_RM_ROUTE_INFOS_BUILT == route_infos));
        my->pendingRoutePtr = NULL;
    }
    if (NULL == route_ptr ||
        UCS_RM_ROUTE_INFOS_ATD_UPDATE == route_infos ||
        UCS_RM_ROUTE_INFOS_ATD_ERROR == route_infos)
        return;
    available = UCS_RM_ROUTE_INFOS_BUILT == route_infos;
    conLabel = Ucs_Rm_GetConnectionLabel(my->unicens, route_ptr);
    UCSIPrint_SetRouteState(route_ptr->route_id, available, conLabel);
    UCSI_CB_OnRouteResult(my->tag, route_ptr->route_id, available, conLabel);
    if (UCS_RM_ROUTE_INFOS_SUSPENDED == route_infos)
    {
        /* Route has been permanently disabled due to a crucial error, enable it again */
        UnicensCmdEntry_t entry;
        entry.cmd = UnicensCmd_RmSetRoute;
        entry.val.RmSetRoute.routePtr = route_ptr;
        entry.val.RmSetRoute.isActive = false;
        EnqueueCommand(my, &entry);
        entry.val.RmSetRoute.isActive = true;
        EnqueueCommand(my, &entry);
        UCSI_CB_OnServiceRequired(my->tag);
    }
}

static void OnUnicensNetworkStatus(uint16_t change_mask, uint16_t events, Ucs_Network_Availability_t availability,
    Ucs_Network_AvailInfo_t avail_info,Ucs_Network_AvailTransCause_t avail_trans_cause, uint16_t node_address,
    uint8_t max_position, uint16_t packet_bw, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    if (my->programmingMode)
    {
        if (UCS_NW_AVAILABLE == availability)
            UCSICollision_SetFoundNodeCount(max_position);
        else
            UCSICollision_Init();
    }
    UCSIPrint_SetNetworkAvailable(UCS_NW_AVAILABLE == availability, max_position);
    UCSI_CB_OnNetworkState(my->tag, UCS_NW_AVAILABLE == availability, packet_bw, max_position);
}

static void OnUnicensDebugXrmResources(Ucs_Xrm_ResourceType_t resource_type,
    Ucs_Xrm_ResObject_t *resource_ptr, Ucs_Xrm_ResourceInfos_t resource_infos,
    Ucs_Rm_EndPoint_t *endpoint_inst_ptr, void *user_ptr)
{
    char *msg = NULL;
    UCSI_Data_t *my;
    uint16_t adr = 0xFFFF;
#ifndef DEBUG_XRM
    resource_type = resource_type;
    resource_ptr = resource_ptr;
    resource_infos = resource_infos;
    endpoint_inst_ptr = endpoint_inst_ptr;
    user_ptr = user_ptr;
#else
    endpoint_inst_ptr = endpoint_inst_ptr;
    my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    if (NULL == resource_ptr) return;
    if (endpoint_inst_ptr && endpoint_inst_ptr->node_obj_ptr &&
            endpoint_inst_ptr->node_obj_ptr->signature_ptr)
        adr = endpoint_inst_ptr->node_obj_ptr->signature_ptr->node_address;
    switch (resource_infos)
    {
    case UCS_XRM_INFOS_BUILT:
        msg = (char *)"has been built";
        UCSIPrint_SetObjectState(resource_ptr, ObjState_Build);
        break;
    case UCS_XRM_INFOS_DESTROYED:
        msg = (char *)"has been destroyed";
        UCSIPrint_SetObjectState(resource_ptr, ObjState_Unused);
        break;
    case UCS_XRM_INFOS_ERR_BUILT:
        msg = (char *)"cannot be built";
        UCSIPrint_SetObjectState(resource_ptr, ObjState_Failed);
        break;
    case UCS_XRM_INFOS_ERR_DESTROYED:
        msg = (char *)"cannot be destroyed";
        UCSIPrint_SetObjectState(resource_ptr, ObjState_Failed);
        break;
    default:
        msg = (char *)"has unknown state";
        break;
    }
    switch(resource_type)
    {
        case UCS_XRM_RC_TYPE_NW_SOCKET:
        {
            Ucs_Xrm_NetworkSocket_t *ms = (Ucs_Xrm_NetworkSocket_t *)resource_ptr;
            assert(ms->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): NW socket %s, handle=%04X, "\
                "direction=%d, type=%d, bandwidth=%d", 6, adr, msg, ms->nw_port_handle,
                ms->direction, ms->data_type, ms->bandwidth);
            break;
        }
        case UCS_XRM_RC_TYPE_MLB_PORT:
        {
            Ucs_Xrm_MlbPort_t *m = (Ucs_Xrm_MlbPort_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB port %s, index=%d, clock=%d", 4,
                adr, msg, m->index, m->clock_config);
            break;
        }
        case UCS_XRM_RC_TYPE_MLB_SOCKET:
        {
            Ucs_Xrm_MlbSocket_t *m = (Ucs_Xrm_MlbSocket_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): MLB socket %s, direction=%d, type=%d,"\
                " bandwidth=%d, channel=%d", 6, adr, msg, m->direction, m->data_type,
                m->bandwidth, m->channel_address);
            break;
        }
        case UCS_XRM_RC_TYPE_USB_PORT:
        {
            Ucs_Xrm_UsbPort_t *m = (Ucs_Xrm_UsbPort_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB port %s, in-cnt=%d, out-cnt=%d", 4,
                adr, msg, m->streaming_if_ep_in_count, m->streaming_if_ep_out_count);
            break;
        }
        case UCS_XRM_RC_TYPE_USB_SOCKET:
        {
            Ucs_Xrm_UsbSocket_t *m = (Ucs_Xrm_UsbSocket_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): USB socket %s, direction=%d, type=%d," \
                " ep-addr=%02X, frames=%d", 6, adr, msg, m->direction, m->data_type,
                m->end_point_addr, m->frames_per_transfer);
            break;
        }
        case UCS_XRM_RC_TYPE_STRM_PORT:
        {
            Ucs_Xrm_StrmPort_t *m = (Ucs_Xrm_StrmPort_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S port %s, index=%d, clock=%d, "\
                "align=%d", 5, adr, msg, m->index, m->clock_config, m->data_alignment);
            break;
        }
        case UCS_XRM_RC_TYPE_STRM_SOCKET:
        {
            Ucs_Xrm_StrmSocket_t *m = (Ucs_Xrm_StrmSocket_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): I2S socket %s, direction=%d, type=%d"\
                ", bandwidth=%d, pin=%d", 6, adr, msg, m->direction, m->data_type,
                m->bandwidth, m->stream_pin_id);
            break;
        }
        case UCS_XRM_RC_TYPE_SYNC_CON:
        {
            Ucs_Xrm_SyncCon_t *m = (Ucs_Xrm_SyncCon_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Sync connection %s, mute=%d, "\
                "offset=%d", 4, adr, msg, m->mute_mode, m->offset);
            break;
        }
        case UCS_XRM_RC_TYPE_COMBINER:
        {
            Ucs_Xrm_Combiner_t *m = (Ucs_Xrm_Combiner_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Combiner %s, bytes per frame=%d",
                3, adr, msg, m->bytes_per_frame);
            break;
        }
        case UCS_XRM_RC_TYPE_SPLITTER:
        {
            Ucs_Xrm_Splitter_t *m = (Ucs_Xrm_Splitter_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Splitter %s, bytes per frame=%d",
                3, adr, msg, m->bytes_per_frame);
            break;
        }
        case UCS_XRM_RC_TYPE_AVP_CON:
        {
            Ucs_Xrm_AvpCon_t *m = (Ucs_Xrm_AvpCon_t *)resource_ptr;
            assert(m->resource_type == resource_type);
            UCSI_CB_OnUserMessage(my->tag, false, "Xrm-Debug (0x%03X): Isoc-AVP connection %s, packetSize=%d",
                3, adr, msg, m->isoc_packet_size);
            break;
        }
        default:
        UCSI_CB_OnUserMessage(my->tag, true, "Xrm-Debug (0x%03X): Unknown type=%d %s", 3 , adr, resource_type, msg);
    }
#endif
}

static void OnUcsInitResult(Ucs_InitResult_t result, void *user_ptr)
{
    UnicensCmdEntry_t e;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    my->initialized = (UCS_INIT_RES_SUCCESS == result);
    OnCommandExecuted(my, UnicensCmd_Init, (UCS_INIT_RES_SUCCESS == result));
    if (!my->initialized)
    {
        UCSI_CB_OnUserMessage(my->tag, true, "UcsInitResult reported error (0x%X), restarting...", 1, result);
        e.cmd = UnicensCmd_Init;
        e.val.Init.init_ptr = &my->uniInitData;
        EnqueueCommand(my, &e);
    }
}

static void OnUcsStopResult(Ucs_StdResult_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    result = result; /*TODO: check error case*/
    assert(MAGIC == my->magic);
    my->initialized = false;
    OnCommandExecuted(my, UnicensCmd_Stop, (UCS_RES_SUCCESS == result.code));
    UCSI_CB_OnStop(my->tag);
}

static void OnUcsGpioPortCreate(uint16_t node_address, uint16_t gpio_port_handle, Ucs_Gpio_Result_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_GpioCreatePort, (UCS_GPIO_RES_SUCCESS == result.code));
}

static void OnUcsGpioPortWrite(uint16_t node_address, uint16_t gpio_port_handle, uint16_t current_state, uint16_t sticky_state, Ucs_Gpio_Result_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_GpioWritePort, (UCS_GPIO_RES_SUCCESS == result.code));
}

static void OnUcsMgrReport(Ucs_MgrReport_t code, Ucs_Signature_t *signature_ptr, Ucs_Rm_Node_t *node_ptr, void *user_ptr)
{
    uint16_t node_address;
    uint16_t node_pos_addr;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    assert(NULL != signature_ptr);
    node_address = signature_ptr->node_address;
    node_pos_addr = signature_ptr->node_pos_addr;
    UCSI_CB_OnMgrReport(my->tag, code, signature_ptr, node_ptr);
    switch (code)
    {
    case UCS_MGR_REP_IGNORED_UNKNOWN:
        UCSIPrint_SetNodeAvailable(node_address, node_pos_addr, NodeState_Ignored);
        UCSI_CB_OnUserMessage(my->tag, false, "Node=%X(%X): Ignored, because unknown", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_IGNORED_DUPLICATE:
        UCSIPrint_SetNodeAvailable(node_address, node_pos_addr, NodeState_Ignored);
        UCSI_CB_OnUserMessage(my->tag, true, "Node=%X(%X): Ignored, because duplicated", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_NOT_AVAILABLE:
        UCSIPrint_SetNodeAvailable(node_address, node_pos_addr, NodeState_NotAvailable);
        UCSI_CB_OnUserMessage(my->tag, false, "Node=%X(%X): Not available", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_WELCOMED:
        UCSI_CB_OnUserMessage(my->tag, false, "Node=%X(%X): Welcomed", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_SCRIPT_FAILURE:
        UCSI_CB_OnUserMessage(my->tag, true, "Node=%X(%X): Script failure", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_IRRECOVERABLE:
        UCSI_CB_OnUserMessage(my->tag, true, "Node=%X(%X): IRRECOVERABLE ERROR!!", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_SCRIPT_SUCCESS:
        UCSI_CB_OnUserMessage(my->tag, false, "Node=%X(%X): Script ok", 2, node_address, node_pos_addr);
        break;
    case UCS_MGR_REP_AVAILABLE:
        UCSIPrint_SetNodeAvailable(node_address, node_pos_addr, NodeState_Available);
        UCSI_CB_OnUserMessage(my->tag, false, "Node=%X(%X): Available", 2, node_address, node_pos_addr);
        break;
    default:
        UCSI_CB_OnUserMessage(my->tag, true, "Node=%X(%X): unknown code", 2, node_address, node_pos_addr);
        break;
    }
}

static void OnUcsNsRun(uint16_t node_address, Ucs_Ns_ResultCode_t result, Ucs_Ns_ErrorInfo_t error_info, void *ucs_user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnCommandResult(my->tag, UnicensCmd_NsRun, (UCS_NS_RES_SUCCESS == result), node_address);
#ifdef DEBUG_XRM
    UCSI_CB_OnUserMessage(my->tag, (UCS_NS_RES_SUCCESS != result), "OnUcsNsRun (%03X): script executed %s",
        2, node_address, (UCS_NS_RES_SUCCESS == result ? "succeeded" : "false"));
#endif
}

static void OnUcsAmsRxMsgReceived(void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnAmsMessageReceived(my->tag);
}

static void OnUcsGpioTriggerEventStatus(uint16_t node_address, uint16_t gpio_port_handle,
    uint16_t rising_edges, uint16_t falling_edges, uint16_t levels, void * user_ptr)
{
    uint8_t i;
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    for (i = 0; i < 16; i++)
    {
        if (0 != ((rising_edges >> i) & 0x1))
            UCSI_CB_OnGpioStateChange(my->tag, node_address, i, true);
        if (0 != ((falling_edges >> i) & 0x1))
            UCSI_CB_OnGpioStateChange(my->tag, node_address, i, false);
    }
}

static void OnUcsI2CWrite(uint16_t node_address, uint16_t i2c_port_handle,
    uint8_t i2c_slave_address, uint8_t data_len, Ucs_I2c_Result_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_I2CWrite, (UCS_I2C_RES_SUCCESS == result.code));
    if (UCS_I2C_RES_SUCCESS != result.code)
        UCSI_CB_OnUserMessage(my->tag, true, "Remote I2C Write to node=0x%X failed", 1, node_address);
}

static void OnUcsI2CRead(uint16_t node_address, uint16_t i2c_port_handle,
            uint8_t i2c_slave_address, uint8_t data_len, uint8_t data_ptr[], Ucs_I2c_Result_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_I2CRead, (UCS_I2C_RES_SUCCESS == result.code));
    UCSI_CB_OnI2CRead(my->tag, (UCS_I2C_RES_SUCCESS == result.code), node_address, i2c_slave_address, data_ptr, data_len);
}

#if ENABLE_AMS_LIB
static void OnUcsAmsWrite(Ucs_AmsTx_Msg_t* msg_ptr, Ucs_AmsTx_Result_t result, Ucs_AmsTx_Info_t info, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_SendAmsMessage, (UCS_AMSTX_RES_SUCCESS == result));
    if (UCS_AMSTX_RES_SUCCESS != result)
        UCSI_CB_OnUserMessage(my->tag, true, "SendAms failed with result=0x%x, info=0x%X", 2, result, info);
}
#endif

static void OnUcsProgRam(Ucs_Prg_ResCode_t code, Ucs_Prg_Func_t function,
    uint8_t ret_len, uint8_t parm[], void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    if (my->currentCmd->cmd != UnicensCmd_ProgIsRam)
    {
        /* Workaround for issue found in UCS Lib V2.2.0-3942 */
        return;
    }
    OnCommandExecuted(my, UnicensCmd_ProgIsRam, (UCS_PRG_RES_SUCCESS == code));
    if (UCS_PRG_RES_SUCCESS == code)
        UCSI_CB_OnUserMessage(my->tag, false, "Write to RAM was successful", 0);
    else
        UCSI_CB_OnUserMessage(my->tag, true, "Write to RAM failed with error code %d", 1, code);
    if (my->programmingJobsTotal == ++my->programmingJobsFinished)
    {
         UnicensCmdEntry_t entry;
         entry.cmd = UnicensCmd_NwShutdown;
         EnqueueCommand(my, &entry);
         UCSI_CB_OnServiceRequired(my->tag);
    }
}

static void OnUcsProgRom(Ucs_Prg_ResCode_t code, Ucs_Prg_Func_t function,
    uint8_t ret_len, uint8_t parm[], void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    if (my->currentCmd->cmd != UnicensCmd_ProgIsRom)
    {
        /* Workaround for issue found in UCS Lib V2.2.0-3942 */
        return;
    }
    OnCommandExecuted(my, UnicensCmd_ProgIsRom, (UCS_PRG_RES_SUCCESS == code));
    if (UCS_PRG_RES_SUCCESS == code)
        UCSI_CB_OnUserMessage(my->tag, false, "Write to ROM was successful", 0);
    else
        UCSI_CB_OnUserMessage(my->tag, true, "Write to ROM failed with error code %d", 1, code);
    if (my->programmingJobsTotal == ++my->programmingJobsFinished)
    {
         UnicensCmdEntry_t entry;
         entry.cmd = UnicensCmd_NwShutdown;
         EnqueueCommand(my, &entry);
         UCSI_CB_OnServiceRequired(my->tag);
    }
}

static void OnUcsPacketFilterMode(uint16_t node_address, Ucs_StdResult_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_PacketFilterMode, (UCS_RES_SUCCESS == result.code));
    if (UCS_RES_SUCCESS != result.code)
        UCSI_CB_OnUserMessage(my->tag, true, "Set promiscuous mode failed with error code %d", 1, result.code);
}

static void OnUcsNetworkStartup(Ucs_StdResult_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_NwStartup, (UCS_RES_SUCCESS == result.code));
    if (UCS_RES_SUCCESS != result.code)
        UCSI_CB_OnUserMessage(my->tag, true, "NetworkStartup failed with error code %d", 1, result.code);
}

static void OnUcsNetworkShutdown(Ucs_StdResult_t result, void *user_ptr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)user_ptr;
    assert(MAGIC == my->magic);
    OnCommandExecuted(my, UnicensCmd_NwShutdown, (UCS_RES_SUCCESS == result.code));
    if (0 != my->programmingJobsTotal)
    {
        UCSI_CB_OnProgrammingDone(my->tag, true);
    }
}


/************************************************************************/
/* Callback from Collision Resolver Component                           */
/************************************************************************/

void UCSICollision_CB_OnProgramIdentString(const Ucs_Signature_t *signature, const Ucs_IdentString_t *newIdentString, void *userPtr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)userPtr;
    assert(MAGIC == my->magic);
    assert(NULL != signature);
    assert(NULL != newIdentString);
    if (my->programmingMode)
    {
        UCSI_CB_OnUserMessage(my->tag, false,
               "Programming INIC on position=0x%X, old address=0x%X, new address=0x%X, old MAC=%04X%04X%04X new MAC=%04X%04X%04X", 9,
               signature->node_pos_addr, signature->node_address, newIdentString->node_address,
               signature->mac_47_32, signature->mac_31_16, signature->mac_15_0,
               newIdentString->mac_47_32, newIdentString->mac_31_16, newIdentString->mac_15_0);
        if (my->ndRunning)
        {
             UnicensCmdEntry_t e;
             my->ndRunning = false;
             e.cmd = UnicensCmd_NDStop;
             EnqueueCommand(my, &e);
        }
        switch(signature->chip_id)
        {
            case 0x18:
            case 0x19:
                UCSI_ProgramIdentStringRom(my, signature, newIdentString);
                my->programmingJobsTotal++;
                break;
            case 0x30:
            case 0x32:
            case 0x34:
                UCSI_ProgramIdentStringRam(my, signature, newIdentString);
                my->programmingJobsTotal++;
                break;
            default:
                UCSI_CB_OnUserMessage(my->tag, true, "Programming canceled because of unknown chip id=%d", 1, signature->chip_id);
                break;
        }
    } else {
        UCSI_CB_OnUserMessage(my->tag, false,
               "Need to program INIC on position=0x%X, old address=0x%X, new address=0x%X, old MAC=%04X%04X%04X new MAC=%04X%04X%04X, enable programming mode!", 9,
               signature->node_pos_addr, signature->node_address, newIdentString->node_address,
               signature->mac_47_32, signature->mac_31_16, signature->mac_15_0,
               newIdentString->mac_47_32, newIdentString->mac_31_16, newIdentString->mac_15_0);
    }
}

void UCSICollision_CB_OnProgramDone(void *userPtr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)userPtr;
    assert(MAGIC == my->magic);
    if (0 == my->programmingJobsTotal)
        UCSI_CB_OnProgrammingDone(my, false);
}

void UCSICollision_CB_FinishedWithoutChanges(void *userPtr)
{
    UCSI_Data_t *my = (UCSI_Data_t *)userPtr;
    assert(MAGIC == my->magic);
    UCSI_CB_OnProgrammingDone(my, false);
}

/************************************************************************/
/* Callback from UCSI Print component:                                  */
/************************************************************************/

void UCSIPrint_CB_NeedService(void *tag)
{
    UCSI_Data_t *my = (UCSI_Data_t *)tag;
    assert(MAGIC == my->magic);
    my->printTrigger = true;
}

void UCSIPrint_CB_OnUserMessage(void *usr, const char pMsg[])
{
    void *tag = NULL;
    UCSI_Data_t *my = (UCSI_Data_t *)usr;
    if (my)
    {
        assert(MAGIC == my->magic);
        tag = my->tag;
    }
    UCSI_CB_OnPrintRouteTable(tag, pMsg);
}

/************************************************************************/
/* Debug Message output from UNICENS stack:                             */
/************************************************************************/
#if defined(UCS_TR_ERROR) || defined(UCS_TR_INFO)
#include <stdio.h>
void App_TraceError(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
{
    va_list argptr;
    void *tag = NULL;
    UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
    if (my)
    {
        assert(MAGIC == my->magic);
        tag = my->tag;
    }
    va_start(argptr, vargs_cnt);
    vsnprintf(m_traceBuffer, sizeof(m_traceBuffer), entry_str, argptr);
    va_end(argptr);
    UCSIPrint_UnicensActivity();
    UCSI_CB_OnUserMessage(tag, true, "Error | %s | %s", 2, module_str, m_traceBuffer);
}

void App_TraceInfo(void *ucs_user_ptr, const char module_str[], const char entry_str[], uint16_t vargs_cnt, ...)
{
    va_list argptr;
    void *tag = NULL;
    UCSI_Data_t *my = (UCSI_Data_t *)ucs_user_ptr;
    if (my)
    {
        assert(MAGIC == my->magic);
        tag = my->tag;
    }
    va_start(argptr, vargs_cnt);
    vsnprintf(m_traceBuffer, sizeof(m_traceBuffer), entry_str, argptr);
    va_end(argptr);
    UCSI_CB_OnUserMessage(tag, false, "Info | %s | %s", 2, module_str, m_traceBuffer);
}
#endif

<file_sep>/audio-source/samv71-ucs/libraries/ucsi/ucsi_print.c
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Stucture Printing module                                                               */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "ucsi_cfg.h"
#include "ucsi_print.h"

#ifdef ENABLE_RESOURCE_PRINT

#define SERVICE_TIME (1000)
#define MAX_TIMEOUT  (30000)
#define MPR_RETRIES  (5)
#define INVALID_CON_LABEL (0xDEAD)

#define RESETCOLOR "\033[0m"
#define GREEN      "\033[0;32m"
#define RED        "\033[0;31m"
#define YELLOW     "\033[1;33m"
#define BLUE       "\033[0;34m"

#define STR_BUF_LEN (200)
#define STR_RES_LEN (60)

struct ResourceList
{
    Ucs_Xrm_ResObject_t *element;
    UCSIPrint_ObjectState_t state;
};

struct ConnectionList
{
    bool isValid;
    bool isActive;
    uint16_t routeId;
    uint16_t connectionLabel;
};

struct NodeList
{
    bool isValid;
    UCSIPrint_NodeState_t nodeState;
    uint16_t node;
    uint16_t pos;
};

struct LocalVar
{
    bool initialized;
    bool triggerService;
    uint32_t nextService;
    uint32_t timeOut;
    void *tag;
    Ucs_Rm_Route_t *pRoutes;
    uint16_t routesSize;
    bool networkAvailable;
    uint8_t mpr;
    uint8_t waitForMprRetries;
    struct ResourceList rList[UCSI_PRINT_MAX_RESOURCES];
    struct ConnectionList cList[UCSI_PRINT_MAX_RESOURCES];
    struct NodeList nList[UCSI_PRINT_MAX_NODES];
};

static struct LocalVar m = { 0 };
static char strBuf[STR_BUF_LEN];
static void PrintTable(void);
static void ParseResources(Ucs_Xrm_ResObject_t **ppJobList, char *pBuf, uint32_t bufLen);
static bool GetIgnoredNodeString(char *pBuf, uint32_t bufLen);
static UCSIPrint_NodeState_t GetNodeState(uint16_t nodeAddress);
static uint8_t GetNodeCount(void);
static bool GetRouteState(uint16_t routeId, bool *pIsActive, uint16_t *pConLabel);
static void RequestTrigger(void);

void UCSIPrint_Init(Ucs_Rm_Route_t *pRoutes, uint16_t routesSize, void *tag)
{
    memset(&m, 0, sizeof(struct LocalVar));
    if (NULL == pRoutes || 0 == routesSize)
        return;
    m.tag = tag;
    m.pRoutes = pRoutes;
    m.routesSize = routesSize;
    m.initialized = true;
}

void UCSIPrint_Service(uint32_t timestamp)
{
    bool exec = false;
    if (!m.networkAvailable)
        return;
    if (m.triggerService)
    {
        m.triggerService = false;
        m.nextService = timestamp + SERVICE_TIME;
        if (0 == m.timeOut)
            m.timeOut = timestamp + MAX_TIMEOUT;
        UCSIPrint_CB_NeedService(m.tag);
        return;
    }
    if (0 == m.nextService || 0 == m.timeOut)
        return;
    if (timestamp >= m.timeOut)
    {
        UCSIPrint_CB_OnUserMessage(m.tag, RED "UCSI-Watchdog:Max timeout reached" RESETCOLOR);
        exec = true;
    }
    else if (timestamp >= m.nextService)
    {
        if (m.mpr != GetNodeCount() && ++m.waitForMprRetries <= MPR_RETRIES)
        {
            m.nextService = timestamp + SERVICE_TIME;
            return;
        }
        exec = true;
    }
    if (exec)
    {
        m.nextService = 0;
        m.timeOut = 0;
        PrintTable();
    }
    else
    {
        UCSIPrint_CB_NeedService(m.tag);
    }
}

void UCSIPrint_SetNetworkAvailable(bool available, uint8_t maxPos)
{
    if (!m.initialized)
        return;
    m.networkAvailable = available;
    m.mpr = maxPos;
    m.waitForMprRetries = 0;
    if (available)
    {
        RequestTrigger();
    } else {
       m.triggerService = false;
       m.nextService = 0;
    }
}

void UCSIPrint_SetNodeAvailable(uint16_t nodeAddress, uint16_t nodePosAddr, UCSIPrint_NodeState_t nodeState)
{
    uint16_t i;
    if (!m.initialized)
        return;
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (m.nList[i].isValid && nodePosAddr == m.nList[i].pos)
        {
            if (m.nList[i].nodeState != nodeState || m.nList[i].node != nodeAddress)
            {
                m.nList[i].node = nodeAddress;
                m.nList[i].nodeState = nodeState;
                RequestTrigger();
            }
            return;
        }
    }
    /* Find empty entry and store it there */
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (!m.nList[i].isValid)
        {
            m.nList[i].node = nodeAddress;
            m.nList[i].pos = nodePosAddr;
            m.nList[i].nodeState = nodeState;
            m.nList[i].isValid = true;
            RequestTrigger();
            return;
        }
    }
    UCSIPrint_CB_OnUserMessage(m.tag, RED "UCSI-Watchdog:Could not store node availability, increase UCSI_PRINT_MAX_NODES" RESETCOLOR);
}

void UCSIPrint_SetRouteState(uint16_t routeId, bool isActive, uint16_t connectionLabel)
{
    uint16_t i;
    if (!m.initialized)
        return;
    RequestTrigger();
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_RESOURCES; i++)
    {
        if (m.cList[i].isValid && routeId == m.cList[i].routeId)
        {
            m.cList[i].connectionLabel = connectionLabel;
            m.cList[i].isActive = isActive;
            return;
        }
    }
    /* Find empty entry and store it there */
    for (i = 0; i < UCSI_PRINT_MAX_RESOURCES; i++)
    {
        if (!m.cList[i].isValid)
        {
            m.cList[i].routeId = routeId;
            m.cList[i].isActive = isActive;
            m.cList[i].connectionLabel = connectionLabel;
            m.cList[i].isValid = true;
            return;
        }
    }
    UCSIPrint_CB_OnUserMessage(m.tag, RED "UCSI-Watchdog:Could not store connection label, increase UCSI_PRINT_MAX_RESOURCES" RESETCOLOR);
}

void UCSIPrint_SetObjectState(Ucs_Xrm_ResObject_t *element, UCSIPrint_ObjectState_t state)
{
    uint16_t i;
    if (!m.initialized)
        return;
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_RESOURCES; i++)
    {
        if (element == m.rList[i].element)
        {
            if (m.rList[i].state != state)
            {
                m.rList[i].state = state;
                RequestTrigger();
            }
            return;
        }
    }
    /* Find empty entry and store it there */
    for (i = 0; i < UCSI_PRINT_MAX_RESOURCES; i++)
    {
        if (NULL == m.rList[i].element)
        {
            m.rList[i].element = element;
            m.rList[i].state = state;
            RequestTrigger();
            return;
        }
    }
    UCSIPrint_CB_OnUserMessage(m.tag, RED "UCSI-Watchdog:Could not store object state, increase UCSI_PRINT_MAX_RESOURCES" RESETCOLOR);
}

void UCSIPrint_UnicensActivity(void)
{
    if (!m.initialized)
        return;
    if (0 != m.nextService)
        RequestTrigger();
    else
        UCSIPrint_CB_NeedService(m.tag);
}

static void PrintTable(void)
{
    uint16_t i;
    static char inRes[STR_RES_LEN];
    static char outRes[STR_RES_LEN];
    if (!m.initialized)
        return;
    if (!m.networkAvailable)
        return;
    UCSIPrint_CB_OnUserMessage(m.tag, "---------------------------------------------------------------------------------------");
    UCSIPrint_CB_OnUserMessage(m.tag, " Source | Sink   | Active   | ID     | Label  | Resources");
    for (i = 0; i < m.routesSize; i++)
    {
        const char *sourceAvail = " ";
        const char *sourceReset = "";
        const char *sinkAvail = " ";
        const char *sinkReset = "";
        const char *routeAvail = " ";
        const char *routeReset = "";
        uint16_t srcAddr = m.pRoutes[i].source_endpoint_ptr->node_obj_ptr->signature_ptr->node_address;
        uint16_t snkAddr = m.pRoutes[i].sink_endpoint_ptr->node_obj_ptr->signature_ptr->node_address;
        uint8_t shallActive = m.pRoutes[i].active;
        uint16_t id = m.pRoutes[i].route_id;
        bool isActive = false;
        uint16_t label = INVALID_CON_LABEL;
        UCSIPrint_NodeState_t srcState = GetNodeState(srcAddr);
        UCSIPrint_NodeState_t snkState = GetNodeState(snkAddr);
        GetRouteState(id, &isActive, &label);
        ParseResources(m.pRoutes[i].source_endpoint_ptr->jobs_list_ptr, inRes, sizeof(inRes));
        ParseResources(m.pRoutes[i].sink_endpoint_ptr->jobs_list_ptr, outRes, sizeof(outRes));
        if (NodeState_Available == srcState)
        {
            sourceAvail = GREEN "^";
            sourceReset = RESETCOLOR;
        }
        else if (NodeState_Ignored == srcState)
        {
            sourceAvail = RED "^";
            sourceReset = RESETCOLOR;
        }
        if (NodeState_Available == snkState)
        {
            sinkAvail = GREEN "^";
            sinkReset = RESETCOLOR;
        }
        else if (NodeState_Ignored == snkState)
        {
            sinkAvail = RED "!";
            sinkReset = RESETCOLOR;
        }
        if (NodeState_Available == srcState && NodeState_Available == snkState)
        {
            if (shallActive == isActive)
                routeAvail = GREEN "^";
            else
                routeAvail = RED "!";
            routeReset = RESETCOLOR;
        }
        snprintf(strBuf, STR_BUF_LEN, "%s0x%03X%s  | %s0x%03X%s | S:%d I:%s%d%s | 0x%04X | 0x%04X | Src:%s  Snk:%s",
            sourceAvail, srcAddr, sourceReset, sinkAvail, snkAddr, sinkReset, 
            shallActive, routeAvail, isActive, routeReset, id, label, inRes, outRes);
        UCSIPrint_CB_OnUserMessage(m.tag, strBuf);
    }
    UCSIPrint_CB_OnUserMessage(m.tag, "---------------------------------------------------------------------------------------");
    if (GetIgnoredNodeString(inRes, sizeof(inRes)))
    {
        snprintf(strBuf, STR_BUF_LEN, RED "Ignored nodes = { %s }" RESETCOLOR, inRes);
        UCSIPrint_CB_OnUserMessage(m.tag, strBuf);
        UCSIPrint_CB_OnUserMessage(m.tag, "---------------------------------------------------------------------------------------");
    }
}

static void ParseResources(Ucs_Xrm_ResObject_t **ppJobList, char *pBuf, uint32_t bufLen)
{
    uint16_t i, j;
    Ucs_Xrm_ResObject_t *job;
    UCSIPrint_ObjectState_t oldState = ObjState_Unused;
    UCSIPrint_ObjectState_t newState = ObjState_Unused;
    assert(NULL != pBuf && 0 != bufLen);
    pBuf[0] = '\0';
    if (NULL == ppJobList)
        return;
    for (i = 0; NULL != (job = ppJobList[i]); i++)
    {
        Ucs_Xrm_ResourceType_t typ = *((Ucs_Xrm_ResourceType_t *)job);
        assert(UCS_XRM_RC_TYPE_QOS_CON >= typ);
        /* Silently ignore default created port */
        if (UCS_XRM_RC_TYPE_DC_PORT == typ)
            continue;
        for (j = 0; j < UCSI_PRINT_MAX_RESOURCES; j++)
        {
            if (NULL == m.rList[j].element)
                break;
            newState = ObjState_Unused;
            if (job == m.rList[j].element)
            {
                newState = m.rList[j].state;
                break;
            }
        }
        if (oldState != newState)
        {
            oldState = newState;
            if (ObjState_Build == newState)
                strcat(pBuf, GREEN);
            else if (ObjState_Failed == newState)
                strcat(pBuf, RED);
            else
                strcat(pBuf, RESETCOLOR);
        }
        if (ObjState_Build == newState)
            strcat(pBuf, "^");
        else if (ObjState_Failed == newState)
            strcat(pBuf, "!");
        else
            strcat(pBuf, " ");
        switch(typ)
        {
        case UCS_XRM_RC_TYPE_NW_SOCKET:
            strcat(pBuf, "NS");
            break;
        case UCS_XRM_RC_TYPE_MLB_PORT:
            strcat(pBuf, "MP");
            break;
        case UCS_XRM_RC_TYPE_MLB_SOCKET:
            strcat(pBuf, "MS");
            break;
        case UCS_XRM_RC_TYPE_USB_PORT:
            strcat(pBuf, "UP");
            break;
        case UCS_XRM_RC_TYPE_USB_SOCKET:
            strcat(pBuf, "US");
            break;
        case UCS_XRM_RC_TYPE_STRM_PORT:
            strcat(pBuf, "SP");
            break;
        case UCS_XRM_RC_TYPE_STRM_SOCKET:
            strcat(pBuf, "SS");
            break;
        case UCS_XRM_RC_TYPE_SYNC_CON:
            strcat(pBuf, "SC");
            break;
        case UCS_XRM_RC_TYPE_COMBINER:
            strcat(pBuf, "C");
            break;
        case UCS_XRM_RC_TYPE_SPLITTER:
            strcat(pBuf, "S");
            break;
        case UCS_XRM_RC_TYPE_AVP_CON:
            strcat(pBuf, "AC");
            break;
        default:
            strcat(pBuf, "E");
            break;
        }
    }
    if (ObjState_Unused != newState)
        strcat(pBuf, RESETCOLOR);
    assert(strlen(pBuf) < bufLen);
}

static bool GetIgnoredNodeString(char *pBuf, uint32_t bufLen)
{
    uint16_t i;
    char pTmp[8];
    bool foundNodes = false;
    assert(NULL != pBuf && 0 != bufLen);
    pBuf[0] = '\0';
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (m.nList[i].isValid && NodeState_Ignored == m.nList[i].nodeState)
        {
            foundNodes = true;
            snprintf(pTmp, sizeof(pTmp), "0x%X ", m.nList[i].node);
            strcat(pBuf, pTmp);
        }
    }
    assert(strlen(pBuf) < bufLen);
    return foundNodes;
}

static UCSIPrint_NodeState_t GetNodeState(uint16_t nodeAddress)
{
    uint16_t i;
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (m.nList[i].isValid && nodeAddress == m.nList[i].node)
        {
            return m.nList[i].nodeState;
        }
    }
    return NodeState_NotAvailable;
}

static uint8_t GetNodeCount(void)
{
    uint16_t i;
    uint8_t cnt = 0;
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (m.nList[i].isValid && NodeState_NotAvailable != m.nList[i].nodeState)
            ++cnt;
    }
    return cnt;
}

static bool GetRouteState(uint16_t routeId, bool *pIsActive, uint16_t *pConLabel)
{
    uint16_t i;
    assert(NULL != pIsActive);
    assert(NULL != pConLabel);
    /* Find existing entry */
    for (i = 0; i < UCSI_PRINT_MAX_NODES; i++)
    {
        if (m.cList[i].isValid && routeId == m.cList[i].routeId)
        {
            *pIsActive = m.cList[i].isActive;
            *pConLabel = m.cList[i].connectionLabel;
            return true;
        }
    }
    return false;
}

static void RequestTrigger(void)
{
    m.triggerService = true;
    UCSIPrint_CB_NeedService(m.tag);
}
#else /* ENABLE_RESOURCE_PRINT */
void UCSIPrint_Init(Ucs_Rm_Route_t *pRoutes, uint16_t routesSize, void *tag) {}
void UCSIPrint_Service(uint32_t timestamp) {}
void UCSIPrint_SetNetworkAvailable(bool available, uint8_t maxPos) {}
void UCSIPrint_SetNodeAvailable(uint16_t nodeAddress, UCSIPrint_NodeState_t nodeState) {}
void UCSIPrint_SetRouteState(uint16_t routeId, bool isActive, uint16_t connectionLabel) {}
void UCSIPrint_SetObjectState(Ucs_Xrm_ResObject_t *element, UCSIPrint_ObjectState_t state) {}
void UCSIPrint_UnicensActivity(void) {}
#endif
<file_sep>/audio-source/samv71-ucs/src/task-audio.c
/*------------------------------------------------------------------------------------------------*/
/* Audio Processing Task Implementation                                                           */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/

#include <string.h>
#include <assert.h>
#include "Console.h"
#include "dim2_lld.h"
#include "task-audio.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      DEFINES AND LOCAL VARIABLES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/* #define ENABLE_AUDIO_RX */

struct TaskAudioVars
{
    bool initialized;
    uint32_t audioPos;
};
static struct TaskAudioVars m = { 0 };
static const uint8_t audioData[] =
{
    #include "beat_be.h"
};

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      PRIVATE FUNCTION PROTOTYPES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static bool ProcessStreamingData(const uint8_t *pRxBuf, uint32_t rxLen, uint8_t *pTxBuf, uint32_t txLen);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         PUBLIC FUNCTIONS                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

bool TaskAudio_Init(void)
{
    memset(&m, 0, sizeof(m));
    assert(0 == sizeof(audioData) % 4);
    m.initialized = true;
    return true;
}

void TaskAudio_Service(void)
{
    while(true)
    {
        uint8_t *pTxBuf = NULL;
        const uint8_t *pRxBuf = NULL;
        uint16_t rxLen = 0;
        uint16_t txLen = 0;
#if ENABLE_AUDIO_RX
        rxLen = DIM2LLD_GetRxData(DIM2LLD_ChannelType_Sync, DIM2LLD_ChannelDirection_RX, 0, 0, &pRxBuf, NULL, NULL);
        if (0 == rxLen)
            break;
#endif
        txLen = DIM2LLD_GetTxData(DIM2LLD_ChannelType_Sync, DIM2LLD_ChannelDirection_TX, 0, &pTxBuf);
        if (0 == txLen)
            break;
        if (ProcessStreamingData(pRxBuf, rxLen, pTxBuf, txLen))
        {
#if ENABLE_AUDIO_RX
            DIM2LLD_ReleaseRxData(DIM2LLD_ChannelType_Sync, DIM2LLD_ChannelDirection_RX, 0);
#endif
            DIM2LLD_SendTxData(DIM2LLD_ChannelType_Sync, DIM2LLD_ChannelDirection_TX, 0, txLen);
        }
        else break;
    }
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                   PRIVATE FUNCTION IMPLEMENTATIONS                   */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static bool ProcessStreamingData(const uint8_t *pRxBuf, uint32_t rxLen, uint8_t *pTxBuf, uint32_t txLen)
{
    uint32_t i;
    if (!m.initialized)
        return false;
    for (i = 0; i < txLen; i++)
    {
        pTxBuf[i] = audioData[m.audioPos++];
        if (sizeof(audioData) <= m.audioPos)
            m.audioPos = 0;
    }
    return true;
}<file_sep>/audio-source/samv71-ucs/src/driver/dim2/hal/dim2_reg.h
/*
 * dim2_reg.h - Definitions for registers of DIM2
 * (MediaLB, Device Interface Macro IP, OS62420)
 *
 * Copyright (C) 2015, Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * This file is licensed under GPLv2.
 */

#ifndef DIM2_OS62420_H
#define	DIM2_OS62420_H

#include <stdint.h>

#ifdef	__cplusplus
extern "C" {
#endif

struct dim2_regs {
	/* 0x00 */ uint32_t MLBC0;
	/* 0x01 */ uint32_t rsvd0[1];
	/* 0x02 */ uint32_t MLBPC0;
	/* 0x03 */ uint32_t MS0;
	/* 0x04 */ uint32_t rsvd1[1];
	/* 0x05 */ uint32_t MS1;
	/* 0x06 */ uint32_t rsvd2[2];
	/* 0x08 */ uint32_t MSS;
	/* 0x09 */ uint32_t MSD;
	/* 0x0A */ uint32_t rsvd3[1];
	/* 0x0B */ uint32_t MIEN;
	/* 0x0C */ uint32_t rsvd4[1];
	/* 0x0D */ uint32_t MLBPC2;
	/* 0x0E */ uint32_t MLBPC1;
	/* 0x0F */ uint32_t MLBC1;
	/* 0x10 */ uint32_t rsvd5[0x10];
	/* 0x20 */ uint32_t HCTL;
	/* 0x21 */ uint32_t rsvd6[1];
	/* 0x22 */ uint32_t HCMR0;
	/* 0x23 */ uint32_t HCMR1;
	/* 0x24 */ uint32_t HCER0;
	/* 0x25 */ uint32_t HCER1;
	/* 0x26 */ uint32_t HCBR0;
	/* 0x27 */ uint32_t HCBR1;
	/* 0x28 */ uint32_t rsvd7[8];
	/* 0x30 */ uint32_t MDAT0;
	/* 0x31 */ uint32_t MDAT1;
	/* 0x32 */ uint32_t MDAT2;
	/* 0x33 */ uint32_t MDAT3;
	/* 0x34 */ uint32_t MDWE0;
	/* 0x35 */ uint32_t MDWE1;
	/* 0x36 */ uint32_t MDWE2;
	/* 0x37 */ uint32_t MDWE3;
	/* 0x38 */ uint32_t MCTL;
	/* 0x39 */ uint32_t MADR;
	/* 0x3A */ uint32_t rsvd8[0xB6];
	/* 0xF0 */ uint32_t ACTL;
	/* 0xF1 */ uint32_t rsvd9[3];
	/* 0xF4 */ uint32_t ACSR0;
	/* 0xF5 */ uint32_t ACSR1;
	/* 0xF6 */ uint32_t ACMR0;
	/* 0xF7 */ uint32_t ACMR1;
};

#define DIM2_MASK(n)  (~((~(uint32_t)0) << (n)))

enum {
	MLBC0_MLBLK_BIT = 7,

	MLBC0_MLBPEN_BIT = 5,

	MLBC0_MLBCLK_SHIFT = 2,
	MLBC0_MLBCLK_VAL_256FS = 0,
	MLBC0_MLBCLK_VAL_512FS = 1,
	MLBC0_MLBCLK_VAL_1024FS = 2,
	MLBC0_MLBCLK_VAL_2048FS = 3,

	MLBC0_FCNT_SHIFT = 15,
	MLBC0_FCNT_MASK = 7,
	MLBC0_FCNT_MAX_VAL = 6,

	MLBC0_MLBEN_BIT = 0,

	MIEN_CTX_BREAK_BIT = 29,
	MIEN_CTX_PE_BIT = 28,
	MIEN_CTX_DONE_BIT = 27,

	MIEN_CRX_BREAK_BIT = 26,
	MIEN_CRX_PE_BIT = 25,
	MIEN_CRX_DONE_BIT = 24,

	MIEN_ATX_BREAK_BIT = 22,
	MIEN_ATX_PE_BIT = 21,
	MIEN_ATX_DONE_BIT = 20,

	MIEN_ARX_BREAK_BIT = 19,
	MIEN_ARX_PE_BIT = 18,
	MIEN_ARX_DONE_BIT = 17,

	MIEN_SYNC_PE_BIT = 16,

	MIEN_ISOC_BUFO_BIT = 1,
	MIEN_ISOC_PE_BIT = 0,

	MLBC1_NDA_SHIFT = 8,
	MLBC1_NDA_MASK = 0xFF,

	MLBC1_CLKMERR_BIT = 7,
	MLBC1_LOCKERR_BIT = 6,

	ACTL_DMA_MODE_BIT = 2,
	ACTL_DMA_MODE_VAL_DMA_MODE_0 = 0,
	ACTL_DMA_MODE_VAL_DMA_MODE_1 = 1,
	ACTL_SCE_BIT = 0,

	HCTL_EN_BIT = 15
};

enum {
	CDT0_RPC_SHIFT = 16 + 11,
	CDT0_RPC_MASK = DIM2_MASK(5),

	CDT1_BS_ISOC_SHIFT = 0,
	CDT1_BS_ISOC_MASK = DIM2_MASK(9),

	CDT3_BD_SHIFT = 0,
	CDT3_BD_MASK = DIM2_MASK(12),
	CDT3_BD_ISOC_MASK = DIM2_MASK(13),
	CDT3_BA_SHIFT = 16,

	ADT0_CE_BIT = 15,
	ADT0_LE_BIT = 14,
	ADT0_PG_BIT = 13,

	ADT1_RDY_BIT = 15,
	ADT1_DNE_BIT = 14,
	ADT1_ERR_BIT = 13,
	ADT1_PS_BIT = 12,
	ADT1_MEP_BIT = 11,
	ADT1_BD_SHIFT = 0,
	ADT1_CTRL_ASYNC_BD_MASK = DIM2_MASK(11),
	ADT1_ISOC_SYNC_BD_MASK = DIM2_MASK(13),

	CAT_MFE_BIT = 14,

	CAT_MT_BIT = 13,

	CAT_RNW_BIT = 12,

	CAT_CE_BIT = 11,

	CAT_CT_SHIFT = 8,
	CAT_CT_VAL_SYNC = 0,
	CAT_CT_VAL_CONTROL = 1,
	CAT_CT_VAL_ASYNC = 2,
	CAT_CT_VAL_ISOC = 3,

	CAT_CL_SHIFT = 0,
	CAT_CL_MASK = DIM2_MASK(6)
};

#ifdef	__cplusplus
}
#endif

#endif	/* DIM2_OS62420_H */
<file_sep>/audio-source/samv71-ucs/src/main.cpp
/*------------------------------------------------------------------------------------------------*/
/* UNICENS Daemon (unicensd) main-loop                                                            */
/* Copyright 2018, Microchip Technology Inc. and its subsidiaries.                                */
/*                                                                                                */
/* Redistribution and use in source and binary forms, with or without                             */
/* modification, are permitted provided that the following conditions are met:                    */
/*                                                                                                */
/* 1. Redistributions of source code must retain the above copyright notice, this                 */
/*    list of conditions and the following disclaimer.                                            */
/*                                                                                                */
/* 2. 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.                                      */
/*                                                                                                */
/* 3. Neither the name of the copyright holder nor the names of its                               */
/*    contributors may be used to endorse or promote products derived from                        */
/*    this software without specific prior written permission.                                    */
/*                                                                                                */
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.                           */
/*------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include "board_init.h"
#include "Console.h"
#include "task-unicens.h"
#include "task-audio.h"

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                          USER ADJUSTABLE                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

/* UNICENS daemon version number */
#define UNICENSD_VERSION    ("V4.3.0")

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      DEFINES AND LOCAL VARIABLES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

typedef struct
{
    uint32_t lastToggle;
    bool consoleTrigger;
    bool gmacSendInProgress;
} LocalVar_t;

static LocalVar_t m;

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                      PRIVATE FUNCTION PROTOTYPES                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static void GmacTransferCallback(uint32_t status, void *pTag);

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                         PUBLIC FUNCTIONS                             */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

int main()
{
    Board_Init();
    memset(&m, 0, sizeof(LocalVar_t));
    ConsoleInit();
    ConsoleSetPrio(PRIO_HIGH);
    ConsolePrintf(PRIO_HIGH, BLUE "------|V71 UNICENS sample start %s (BUILD %s %s)|------" RESETCOLOR "\r\n", UNICENSD_VERSION, __DATE__, __TIME__);
    if (!TaskUnicens_Init())
        ConsolePrintf(PRIO_ERROR, RED "Init of Task UNICENS Init Failed" RESETCOLOR "\r\n");
    if (!TaskAudio_Init())
        ConsolePrintf(PRIO_ERROR, RED "Init of Task Audio Failed" RESETCOLOR "\r\n");
    while (1)
    {
        uint32_t now = GetTicks();
        TaskUnicens_Service();
        TaskAudio_Service();
        if (m.consoleTrigger)
        {
            m.consoleTrigger = false;
            ConsoleService();
        }
        if (now - m.lastToggle >= 333)
        {
            m.lastToggle = now;
            LED_Toggle(0);
        }
    }
    return 0;
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*              CALLBACK FUNCTION FROM TASK UNICENS                     */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void TaskUnicens_CB_OnRouteResult(uint16_t routeId, bool isActive, uint16_t connectionLabel)
{
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                 CALLBACK FUNCTIONS FROM CONSOLE                      */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

void ConsoleCB_OnServiceNeeded(void)
{
    m.consoleTrigger = true;
}

bool ConsoleCB_SendDatagram( uint8_t *pEthHeader, uint32_t ethLen, uint8_t *pPayload, uint32_t payloadLen )
{
    sGmacSGList sgl;
    sGmacSG sg[2];
    if (m.gmacSendInProgress)
        return false;
    sg[0].pBuffer = pEthHeader;
    sg[0].size = ethLen;
    sg[1].pBuffer = pPayload;
    sg[1].size = payloadLen;
    sgl.sg = sg;
    sgl.len = 2;
    if (GMACD_OK != GMACD_SendSG(&gGmacd, &sgl, GmacTransferCallback, NULL, GMAC_QUE_0))
        return false;
    m.gmacSendInProgress = true;
    return true;
}

/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/
/*                  CALLBACK FUNCTIONS FROM GMAC                        */
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>*/

static void GmacTransferCallback(uint32_t status, void *pTag)
{
    m.gmacSendInProgress = false;
}