169 lines
4.5 KiB
C++
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_ */
|