/*
 * This describes a best effort communication channel. Mainly designed for
 * communication between Core-Controllers, so they can inform each other about
 * their status and pass work around. This is to avoid idling cores that occupy
 * the Masterlock.
 * 
 * The communication entities poll a central trigger counter that increases when
 * there are new messages. However it's not guaranteed that the increase of the
 * counter reflects the number of new messages.
 * 
 * The messages consist of a single 64bit word so it can be written in one 
 * operation and therefore avoiding inconsistent messages.
 * 
 * The messages are handled with a handler function provided by the receiver
 * when acquiring the communication endpoint.
 * 
 * The message passing is handled by a central struct that is used w/o any lock.
 * It consists of a array messages for the number of communicating entities. The
 * number of entities is fixed at initialization.
 */

#include <stdint.h>

/***********************************
 * General Defines
 ***********************************/
//never use this number as a endpoint!
#define BROADCAST_ID 65535

/***********************************
 * Type Definitions
 ***********************************/

/*
 * A message consists of the 
 * 16bit saved trigger value +1 when the message was sent
 * 16bit receiver identifier, this is the index of the slot in the array
 *  65536 is the broadcast identifier
 * 32bit message body, the message format is defined by the endpoints
 * 
 * | 16bit trigger value | 16bit receiverID | 32bit message body |
 */
#define ENDPOINT_ID_SHIFT 32
#define TRIGGER_SHIFT 48
typedef uint64_t lossyCom__msg_t;
typedef uint32_t lossyCom__msgBody_t;
typedef uint16_t lossyCom__endpointID_t;

/*
 * Message Handler that has two arguments the sender endpoint ID and the Msg
 * Example: 
 * void handler_func(lossyCom__endpointID_t senderID, lossyCom__msgBody_t msg);
 */
typedef void  (*lossyCom__msgHandler) (lossyCom__endpointID_t, lossyCom__msgBody_t, void*);

/*
 * Central communication structure.
 */
typedef struct{
    uint16_t triggerCounter;
    uint16_t numEndpoints;
    lossyCom__msg_t* outboxArray;
}lossyCom__exchange_t;

/*
 * Endpoint data structure.
 */
typedef struct {
    uint16_t localTriggerCopy;
    lossyCom__endpointID_t endpointID;
    lossyCom__exchange_t* centralExchange;
    lossyCom__msgHandler msgHandler;
    void* msgHandlerData;
} lossyCom__endpoint_t;

/***********************************
 * Function Declarations
 ***********************************/

lossyCom__exchange_t* lossyCom__initialize(uint16_t numEndpoints);

void lossyCom__initialize_endpoint(lossyCom__endpoint_t* localEndpoint,
                                   lossyCom__exchange_t* exchange,
                                   lossyCom__endpointID_t endpointID,
                                   lossyCom__msgHandler msgHandler,
                                   void* msgHandlerData);

void lossyCom__broadcastMsg(lossyCom__endpoint_t* localEndpoint,
                            lossyCom__msgBody_t msg);

void lossyCom__sendMsg(lossyCom__endpoint_t* localEndpoint,
                       lossyCom__endpointID_t receiverEndpointID,
                       lossyCom__msgBody_t msg);

void lossyCom__receiveMsg(lossyCom__endpoint_t* localEndpoint);