Program Listing for File encoder.cpp
↰ Return to documentation for file (encoder.cpp
)
#include "encoder.hpp"
#include "log.hpp"
void Encoder::set_data_format(int format)
{
#if REGMAP_VERSION < 0x0500
m_header_size = 2;
m_block_bytes = 32;
m_length_mask = TOFLX_LENGTH_MASK_RM4;
m_elink_shift = TOFLX_ELINK_SHIFT_RM4;
#else
switch (format)
{
case FROMHOST_FORMAT_5BIT_LENGTH:
m_header_size = 2;
m_block_bytes = 32;
m_length_mask = TOFLX_LENGTH_MASK;
m_elink_shift = TOFLX_ELINK_SHIFT;
break;
case FROMHOST_FORMAT_HDR32_PACKET32:
m_header_size = 4;
m_block_bytes = 32;
m_length_mask = TOFLX_LENGTH_MASK_HDR32;
m_elink_shift = TOFLX_ELINK_SHIFT_HDR32;
break;
case FROMHOST_FORMAT_HDR32_PACKET64:
m_block_bytes = 64;
m_length_mask = TOFLX_LENGTH_MASK_HDR32;
m_elink_shift = TOFLX_ELINK_SHIFT_HDR32;
break;
case FROMHOST_FORMAT_HDR32_PACKET32_8B:
m_block_bytes = 32;
break;
case FROMHOST_FORMAT_HDR32_PACKET64_8B:
m_block_bytes = 64;
break;
case FROMHOST_FORMAT_HDR32_PACKET128_8B:
m_block_bytes = 128;
break;
default:
LOG_ERR("Invalid FromHost data format %d. Assuming rm-5.1 for PCIe gen3.", format);
break;
}
#endif
m_payload_bytes = m_block_bytes - m_header_size;
}
void Encoder::set_destination_parameters(uint8_t* dest_start, uint32_t dest_size)
{
m_dest_start = dest_start;
m_dest_size = dest_size;
}
size_t Encoder::compute_max_msg_occupancy(size_t size) const
{
return (compute_full_blocks(size) + 1) * m_block_bytes;
}
int Encoder::compute_full_blocks(size_t size) const
{
return ((size + m_payload_bytes - 1) / m_payload_bytes);
}
size_t Encoder::compute_final_bytes(size_t size) const
{
size_t blocks = (size + m_payload_bytes - 1) / m_payload_bytes;
size_t final_bytes = size - (blocks - 1) * m_payload_bytes;
return final_bytes;
}
uint64_t Encoder::encode_and_write_msg(uint64_t elink, const uint8_t *source, size_t size, uint32_t dest_offset)
{
if (m_dest_start == nullptr){
LOG_ERR("FromHost encoder not initialized. The message for 0x%lx will not be written.", elink);
return 0;
}
uint32_t src_i(0);
uint32_t dest_i(dest_offset);
int blocks = compute_full_blocks(size);
int final_bytes = size - (blocks - 1) * m_payload_bytes;
#if REGMAP_VERSION < 0x0500
int hdr = ((elink << m_elink_shift) | ((m_payload_bytes / 2) << TOFLX_LENGTH_SHIFT_RM4));
int final_size = (final_bytes + 1) / 2; // Length in 2-byte units
int final_hdr = hdr & ~m_length_mask;
final_hdr |= ((final_size << TOFLX_LENGTH_SHIFT_RM4) | TOFLX_EOM_MASK_RM4);
#else
// Regmap 0x0500 and beyond, see FLX-1355, FLX-1601 and FLX-1886
if (m_length_mask == TOFLX_LENGTH_MASK_HDR32_8B and m_elink_shift == TOFLX_ELINK_SHIFT_HDR32_8B){
// Keeping the existing 4-byte header e-link numbering,
// so map the e-link number to the '8-bit-fields' version
uint64_t linknr = (elink & 0x07C0) >> 6;
uint64_t eindex = (elink & 0x003F);
elink = (linknr << 8) | eindex;
}
int hdr = ((elink << m_elink_shift) | m_length_mask);
int final_hdr = hdr & ~m_length_mask;
final_hdr |= final_bytes; // Length in bytes
#endif
// Fully-filled FromHost data packets
for (int i = 0; i < blocks - 1; ++i)
{
// Invert payload byte order
for (int j = m_payload_bytes - 1; j >= 0; --j, ++dest_i)
{
m_dest_start[dest_i] = source[src_i + j] & 0xFF;
}
src_i += m_payload_bytes;
// Header
for (int j = 0; j < m_header_size; ++j, ++dest_i)
m_dest_start[dest_i] = (uint8_t)((hdr >> j * 8) & 0xFF);
// Wrap-around ?
if (dest_i >= m_dest_size)
dest_i = 0;
}
// Final (likely not fully filled) FromHost data packet
// Invert payload byte order
for (int j = m_payload_bytes - 1; j >= final_bytes; --j, ++dest_i)
{
// destination[dest_i] = (char) 0xFF; // Remaining payload bytes: set to 0xFF
m_dest_start[dest_i] = (uint8_t)0x00; // Remaining payload bytes: set to 0x00
}
for (int j = final_bytes - 1; j >= 0; --j, ++dest_i)
{
m_dest_start[dest_i] = source[src_i + j] & 0xFF; // Final data bytes
}
// Header
for (int j = 0; j < m_header_size; ++j, ++dest_i)
m_dest_start[dest_i] = (uint8_t)((final_hdr >> j * 8) & 0xFF);
// Wrap-around ?
if (dest_i >= m_dest_size){
dest_i = 0;
}
return dest_i;
}