MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/UMLibrary/common/Crc.hpp

169 lines
4.5 KiB
C++

/**
* @file Crc.hpp
*
* @date Created on: 30 íîÿá. 2018 ã.
* @author ÀÎ ÄÈÀÊÎÍÒ
* - maksimenko
* @revision
* v1.0 - 6.12.2018
*/
#ifndef SOURCE_COMMON_CRC_HPP_
#define SOURCE_COMMON_CRC_HPP_
#include <cstddef>
#include <stdint.h>
namespace common {
namespace crc {
/**
* @brief Ìåíåäæåð òàáëèöû ðàñ÷åòà êîíòðîëüíîé ñóììû
* @param Param òèï îïèñûâàþùèé àëãîðèòì ïîäñ÷åòà (ñì. CrcDesc.hpp)
* @detailed Âåäåò ïîäñ÷åò ññûëîê íà îáúåêòû õðàíåíèÿ êîíòðîëüíîé ñóììû äëÿ
* îáåñïå÷èâàÿ âûäåíëåííûì íà êó÷å òàáëèöåé ðàñ÷åòà CRC. Óäàëÿåì òàáëèöó
* ïðè óíè÷òîæåíèè âñåõ îáúåêòû õðàíåíèÿ êîíòðîëüíîé ñóììû.
*/
template <typename Param>
class CrcTable {
typedef typename Param::res_t res_t;
res_t * mCrcTbl;
uint16_t mcRef;
public:
static CrcTable & Instance();
res_t operator[](int i) { return mCrcTbl[i]; }
CrcTable & operator++() { mcRef++; if ( !mCrcTbl )alloc (); return *this; }
CrcTable & operator--() { if ( !--mcRef )free (); return *this; }
void inititialize() {
alloc();
}
private:
CrcTable() : mCrcTbl(NULL), mcRef(1) {}
CrcTable(const CrcTable &);
CrcTable & operator=(const CrcTable &);
void alloc() {
static res_t crc_table[256];
mCrcTbl = crc_table;
for ( uint32_t i = 0; i < 256; i++ ) {
uint32_t v = Param::reflect ? i: i << (Param::width_bit-8);
for ( uint16_t j = 0; j < 8; j++ ) {
v = Param::reflect ?
v & (1UL<<(0 )) ? (v>>1) ^ Param::poly : (v>>1) :
v & (1UL<<(Param::width_bit-1)) ? (v<<1) ^ Param::poly : (v<<1);
}
mCrcTbl[i] = v & ~0UL>>(32-Param::width_bit);
}
}
void free() {
//mCrcTbl = NULL;
}
};
template <typename Param>
CrcTable<Param>& CrcTable<Param>::Instance() {
static CrcTable mObj;
return mObj;
}
/**
* @brief Õðàíèëèùå çíà÷åíèÿ êîíòðîëüíîé ñóììû
* @detailed Âçàèìîäåéñòâóåò c CrcTable<Param> îáåñïå÷èâàÿ äîñòóï ê òàáëèöå
* äëÿ ðàñ÷åòà CRC. Îáåñïå÷èâàåò íà÷àëüíûé è êîíå÷íûé ýòàï ïîëó÷åíèÿ
* êîíòðîëüíîé ñóììû. Ðåàëèçóåò îïåðàòîðû ïðèâåäåíèÿ òèïà âîçâðàùàþùèé
* êîíå÷íóþ ñòàäèþ (XOR) âû÷èñëåíèÿ CRC.
*/
template <typename Param>
class CrcVal {
typedef typename Param::res_t res_t;
res_t mCrc;
public:
CrcTable<Param> & mCrcTbl;
public:
CrcVal () : mCrc(Param::init), mCrcTbl(CrcTable<Param>::Instance()) {
++mCrcTbl;
}
CrcVal & operator=(const CrcVal & obj) {
mCrc = obj.mCrc;
return *this;
}
CrcVal( const CrcVal & obj ) : mCrcTbl(CrcTable<Param>::Instance()) {
mCrc = obj.mCrc;
++mCrcTbl;
}
operator uint32_t() const {
return mCrc & ~0UL>>(32-Param::width_bit) ^ Param::final;
}
operator uint16_t () const {
return (uint32_t)mCrc;
}
#ifdef __GNUG__
operator uint8_t () const { return (uint32_t)mCrc; }
#endif
res_t & value() const {
return const_cast<res_t &>(mCrc);
}
res_t & value() {
return mCrc;
}
~CrcVal () {
--mCrcTbl;
}
};
/**
* @brief Ïîäñ÷åò êîíòðîëüíîé ñóììû áëîêà äàííûõ
* @param Param òèï îïèñûâàþùèé àëãîðèòì ïîäñ÷åòà (ñì. CrcDesc.hpp)
* @param pData óêàçàòåëü íà áëîê äàííûõ
* @param nBytes ðàçìåð áëîêà äàííûõ â áàéòàõ (îêòåòû)
* @param crcOld îáúåêò õðàíåíèÿ òåêóùåãî çíà÷åíèÿ êîíòðîëüíîé ñóììû
* @retval Îáíîâëåííûé îáúåêò õðàíåíèÿ çíà÷åíèÿ êîíòðîëüíîé ñóììû
* @detailed Âîçìîæíû äâà òèïà çàïóñêà: ñ ïàðàìåòðîì ïî óìîë÷àíèþ - ñîçäàåì
* íîâîå èíèöèàëèçèðîâàííîå õðàíèëèùå íà âûõîäå (íà÷àëî ðàñ÷åòà),
* èñïîëüçóåì ñóùåñòâóþùåå õðàíèëèùå - äîáàâëåíèå ðåçóëüòàòà ðàñ÷åòà
* î÷åðåäíîãî áëîêà äàííûõ.
*/
template <typename Param>
typename Param::crc_t crcCalc( const char * pData, uint32_t nBytes,
const typename Param::crc_t & crcOld = typename Param::crc_t() ) {
typename Param::res_t & crc = crcOld.value();
uint16_t data, octet = 0; (void)octet;
while ( nBytes-- ) {
#ifdef __TMS320C2000__
data = __byte( (int*)pData, octet );// nSize -= octet;
octet ^= 1; pData += !octet;// Àäðåñ ñëåäóþùåãî ñëîâà äàííûõ
#endif
#ifdef __GNUG__
data = *pData++;
#endif
data &= 0xFF;
crc = Param::reflect ?
crcOld.mCrcTbl[data^(crc & 0xFF)] ^ (crc >> 8):
crcOld.mCrcTbl[data^(crc >> (Param::width_bit-8) & 0xFF)] ^ (crc << 8);
}
return crcOld;
}
} // namespace crc
} // namespace common
#include "CrcDesc.hpp"
#endif /* SOURCE_COMMON_CRC_HPP_ */