It is common to share information in buffers in a binary structure. Here are some example how to do it elegant:
/* Pack mandatory fields of header */
can_id = (((packet->id.pri & CFP2_PRIO_MASK) << CFP2_PRIO_OFFSET) |
((packet->id.dst & CFP2_DST_MASK) << CFP2_DST_OFFSET) |
((iface->addr & CFP2_SENDER_MASK) << CFP2_SENDER_OFFSET) |
((sender_count & CFP2_SC_MASK) << CFP2_SC_OFFSET) |
((1 & CFP2_BEGIN_MASK) << CFP2_BEGIN_OFFSET));
Or even more elegant for extracting and writting:
/**
@defgroup CFP_SIZE CAN message id field size.
@{
*/
/** Host - source/destination address. */
#define CFP_HOST_SIZE 5
/** Type - \a begin fragment or \a more fragments. */
#define CFP_TYPE_SIZE 1
/** Remaining fragments */
#define CFP_REMAIN_SIZE 8
/** CFP identification. */
#define CFP_ID_SIZE 10
/** @} */
/**
@defgroup CFP_FIELDS Macros for extracting fields from CAN message id.
@{
*/
/** Helper macro */
#define CFP_FIELD(id,rsiz,fsiz) ((uint32_t)((uint32_t)((id) >> (rsiz)) & (uint32_t)((1 << (fsiz)) - 1)))
/** 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)
/** Extract destination address */
#define CFP_DST(id) CFP_FIELD(id, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_HOST_SIZE)
/** Extract type (begin or more) */
#define CFP_TYPE(id) CFP_FIELD(id, CFP_REMAIN_SIZE + CFP_ID_SIZE, CFP_TYPE_SIZE)
/** Extract remaining fragments */
#define CFP_REMAIN(id) CFP_FIELD(id, CFP_ID_SIZE, CFP_REMAIN_SIZE)
/** Extract CFP identification */
#define CFP_ID(id) CFP_FIELD(id, 0, CFP_ID_SIZE)
/** @} */
/**
@defgroup CFP_MAKE Macros for building CAN message id.
@{
*/
/** Helper macro */
#define CFP_MAKE_FIELD(id,fsiz,rsiz) ((uint32_t)(((id) & (uint32_t)((uint32_t)(1 << (fsiz)) - 1)) << (rsiz)))
/** 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)
/** Make destination */
#define CFP_MAKE_DST(id) CFP_MAKE_FIELD(id, CFP_HOST_SIZE, CFP_TYPE_SIZE + CFP_REMAIN_SIZE + CFP_ID_SIZE)
/** Make type */
#define CFP_MAKE_TYPE(id) CFP_MAKE_FIELD(id, CFP_TYPE_SIZE, CFP_REMAIN_SIZE + CFP_ID_SIZE)
/** Make remaining fragments */
#define CFP_MAKE_REMAIN(id) CFP_MAKE_FIELD(id, CFP_REMAIN_SIZE, CFP_ID_SIZE)
/** Make CFP id */
#define CFP_MAKE_ID(id) CFP_MAKE_FIELD(id, CFP_ID_SIZE, 0)
/** @} */
/**
* CSP 1.x Frame Header:
* Data offset is always 6.
*/
can_id = (CFP_MAKE_SRC(packet->id.src) |
CFP_MAKE_DST(dest) |
CFP_MAKE_ID(ident) |
CFP_MAKE_TYPE(CFP_BEGIN) |
CFP_MAKE_REMAIN((packet->length + CFP1_DATA_OFFSET - 1) / CAN_FRAME_SIZE));
Other example
packet->primary_header->version = (buffer[0] >> 5) & 0b111;
packet->primary_header->type = (buffer[0] >> 4) & 0b1;
packet->primary_header->sec_header_flag = (buffer[0] >> 3) & 0b1;
packet->primary_header->proc_id = ((buffer[0] & 0b111) << 8) | buffer[1];
packet->primary_header->seq_flags = (buffer[2] >> 6) & 0b11;
packet->primary_header->seq_cnt = (buffer[2] & 0b111111) | buffer[3];
packet->primary_header->length = (unsigned short) buffer[4] << 8 |
(unsigned short) buffer[5];