/****************************************************************************
 * **File:** csp/interfaces/csp_if_can.h
 *
 * **Description:** CAN interface
 *
 * CAN frames contains at most 8 bytes of data, so in order to transmit CSP
 * packets larger than this, a fragmentation protocol is required.
 * The CAN Fragmentation Protocol (CFP) is based on CAN2.0B, using all 29 bits
 * of the identifier. The CAN identifier is divided into these fields:
 *
 * - Source:       5 bits
 * - Destination:  5 bits
 * - Type:         1 bit
 * - Remain:       8 bits
 * - Identifier:   10 bits
 *
 * The Source and Destination fields must match the source and destination addresses
 * in the CSP packet. The Type field is used to distinguish the first and subsequent
 * frames in a fragmented CSP packet. Type is BEGIN (0) for the first fragment and
 * MORE (1) for all other fragments. The Remain field indicates number of remaining
 * fragments, and must be decremented by one for each fragment sent. The identifier
 * field serves the same purpose as in the Internet Protocol, and should be an auto
 * incrementing integer to uniquely separate sessions.
 *
 * For networks configured as CSP version 2, the CAN identifier is divided into:
 *
 * - Priority:     2 bits
 * - Destination:  14 bits
 * - Sender id:    6 bits
 * - Packet count: 2 bits
 * - Frame count:  3 bits
 * - Begin flag:   1 bit
 * - End flag:     1 bit
 *
 * The \b Priority represents the CSP prio field. Placing this as the first bits in
 * the transmission ensure that packets with high priority is prioritized on the bus
 * due to the nature of CAN arbitration.
 * The \b Destination field represents the CSP node of the receiving node
 * The \b Sender holds the least significant bits of the transmitting interface,
 * i.e. the local address when a packet is forwarded by a routing instance.
 * The \b Packet \b count is an incrementing value for every CSP packet
 * The \b Frame \b count represents the frame fragment index for the particular packet
 * The \b Begin \b flag is set for the first CAN frame in a CSP packet
 * The \b End \b flag is set for the last CAN frame in a CSP packet
 *
 * In addition to the 29 bit extended CAN header, CSP utilize four bytes in the 
 * first CAN fragment in every CSP packet as:
 *
 * - Source:       14 bits
 * - Dest port:    6 bits
 * - Source port:  6 bits
 * - CSP flags:    6 bits
 * The \b Source holds the CSP node address of the origin of the CSP packet.
 * The \b Dest and \Source \b port represents the port numbers for the transmission.
 * The \b CSP \b flags holds the CSP_HEADER_FLAGS.
 *
 * Other CAN communication using a standard 11 bit identifier, can co-exist on the wire.
 ****************************************************************************/
#pragma once
#include <csp/csp_interface.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
   @defgroup CFP_SIZE CAN message id field size.
   @{
*/
[docs]/** Host - source/destination address. */
#define CFP_HOST_SIZE		5 
[docs]/** Type - begin fragment or more fragments. */
#define CFP_TYPE_SIZE		1 
[docs]/** Remaining fragments */
#define CFP_REMAIN_SIZE		8 
[docs]/** CFP identification. */
#define CFP_ID_SIZE		10 
/** @} */
/**
   @defgroup CFP_FIELDS Macros for extracting fields from CAN message id.
   @{
*/
[docs]/** Helper macro */
#define CFP_FIELD(id,rsiz,fsiz) ((uint32_t)((uint32_t)((id) >> (rsiz)) & (uint32_t)((1 << (fsiz)) - 1))) 
[docs]/** Extract source address */
#define CFP_SRC(id)		CFP_FIELD(id, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE) 
[docs]/** Extract destination address */
#define CFP_DST(id)		CFP_FIELD(id, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE) 
[docs]/** Extract type (begin or more) */
#define CFP_TYPE(id)		CFP_FIELD(id, CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_TYPE_SIZE) 
[docs]/** Extract remaining fragments */
#define CFP_REMAIN(id)		CFP_FIELD(id, CFP_ID_SIZE, CFP_REMAIN_SIZE) 
[docs]/** Extract CFP identification */
#define CFP_ID(id)		CFP_FIELD(id, 0, CFP_ID_SIZE) 
/** @} */
/**
   @defgroup CFP_MAKE Macros for building CAN message id.
   @{
*/
[docs]/** Helper macro */
#define CFP_MAKE_FIELD(id,fsiz,rsiz) ((uint32_t)(((id) & (uint32_t)((uint32_t)(1 << (fsiz)) - 1)) << (rsiz))) 
[docs]/** Make source */
#define CFP_MAKE_SRC(id)	CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_HOST_SIZE + CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE) 
[docs]/** Make destination */
#define CFP_MAKE_DST(id)	CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE) 
[docs]/** Make type */
#define CFP_MAKE_TYPE(id)	CFP_MAKE_FIELD(id, CFP_TYPE_SIZE, CFP_REMAIN_SIZE + CFP_ID_SIZE) 
[docs]/** Make remaining fragments */
#define CFP_MAKE_REMAIN(id)	CFP_MAKE_FIELD(id, CFP_REMAIN_SIZE, CFP_ID_SIZE) 
[docs]/** Make CFP id */
#define CFP_MAKE_ID(id)		CFP_MAKE_FIELD(id, CFP_ID_SIZE, 0) 
/** @} */
[docs]/** Mask to uniquely separate connections */
#define CFP_ID_CONN_MASK   (CFP_MAKE_SRC((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
			 CFP_MAKE_DST((uint32_t)(1 << CFP_HOST_SIZE) - 1) | \
			 CFP_MAKE_ID((uint32_t)(1 << CFP_ID_SIZE) - 1)) 
#define CFP2_PRIO_MASK 0x3
#define CFP2_PRIO_OFFSET 27
#define CFP2_DST_SIZE 14
#define CFP2_DST_MASK 0x3FFF
#define CFP2_DST_OFFSET 13
#define CFP2_SENDER_SIZE 6
#define CFP2_SENDER_MASK 0x3F
#define CFP2_SENDER_OFFSET 7
#define CFP2_SC_MASK 0x3
#define CFP2_SC_OFFSET 5
#define CFP2_FC_MASK 0x7
#define CFP2_FC_OFFSET 2
#define CFP2_BEGIN_MASK 0x1
#define CFP2_BEGIN_OFFSET 1
#define CFP2_END_MASK 0x1
#define CFP2_END_OFFSET 0
#define CFP2_SRC_SIZE 14
#define CFP2_SRC_MASK 0x3FFF
#define CFP2_SRC_OFFSET 18
#define CFP2_DPORT_MASK 0x3F
#define CFP2_DPORT_OFFSET 12
#define CFP2_SPORT_MASK 0x3F
#define CFP2_SPORT_OFFSET 6
#define CFP2_FLAGS_MASK 0x3F
#define CFP2_FLAGS_OFFSET 0
[docs]/**
 * Fields used to uniquely define a CSP packet within each fragment header
 */
#define CFP2_ID_CONN_MASK ((CFP2_DST_MASK << CFP2_DST_OFFSET) | \
						   (CFP2_SENDER_MASK << CFP2_SENDER_OFFSET) | \
					 (CFP2_PRIO_MASK << CFP2_PRIO_OFFSET) | \
						   (CFP2_SC_MASK << CFP2_SC_OFFSET)) 
[docs]/**
 * Default interface name.
 */
#define CSP_IF_CAN_DEFAULT_NAME "CAN" 
/**
 * Send CAN frame (implemented by driver).
 *
 * Used by csp_can_tx() to send CAN frames.
 *
 * @param[in] driver_data driver data from #csp_iface_t
 * @param[in] id CAM message id.
 * @param[in] data CAN data
 * @param[in] dlc data length of \a data.
 * @return #CSP_ERR_NONE on success, otherwise an error code.
 */
typedef int (*csp_can_driver_tx_t)(void * driver_data, uint32_t id, const uint8_t * data, uint8_t dlc);
[docs]/**
 * Interface data (state information).
 */
typedef struct {
[docs]	uint32_t cfp_packet_counter; /**< CFP Identification number - same number on all fragments from same CSP packet. */ 
[docs]	csp_can_driver_tx_t tx_func; /**< Tx function */ 
[docs]	csp_packet_t * pbufs; /**< PBUF queue */ 
} csp_can_interface_data_t; 
[docs]/**
 * Add interface.
 *
 * @param[in] iface CSP interface, initialized with name and inteface_data
 * 								pointing to a valid #csp_can_interface_data_t structure.
 * @return #CSP_ERR_NONE on success, otherwise an error code.
*/
int csp_can_add_interface(csp_iface_t * iface); 
/**
 * Remove interface.
 *
 * @param[in] iface CSP interface to be removed.
 *
 * @return #CSP_ERR_NONE on success, otherwise an error code.
 */
int csp_can_remove_interface(csp_iface_t * iface);
[docs]/**
 * Send CSP packet over CAN (nexthop).
 *
 * This function will split the CSP packet into several fragments and call
 * csp_can_tx_fram() for sending each fragment.
 *
 * @param[in] iface CSP interface
 * @param[in] via
 * @param[in] packet CSP packet
 * @return #CSP_ERR_NONE on success, otherwise an error code.
 */
int csp_can_tx(csp_iface_t * iface, uint16_t via, csp_packet_t *packet); 
[docs]/**
 * Process received CAN frame.
 *
 * Called from driver when a single CAN frame (up to 8 bytes) has been received.
 * The function will gather the fragments into a single
 * CSP packet and route it on when complete.
 *
 * @param[in] iface incoming interface.
 * @param[in] id received CAN message identifier.
 * @param[in] data received CAN data.
 * @param[in] dlc length of received \a data.
 * @param[out] pxTaskWoken Valid reference if called from ISR, otherwise NULL!
 * @return #CSP_ERR_NONE on success, otherwise an error code.
 */
int csp_can_rx(csp_iface_t * iface, uint32_t id, const uint8_t * data, uint8_t dlc, int *pxTaskWoken); 
#ifdef __cplusplus
}
#endif