Merge pull request #1269 from pkendall64/crsf-max-output
[ExpressLRS.git] / src / test / crc_native / ucrc_t.cpp
blobf27580efa9422afdbb50bd77302277b16847a4b9
1 /*
2 * ucrc_t.cpp
5 * version 1.3
8 * BSD 3-Clause License
10 * Copyright (c) 2015, Koynov Stas - skojnov@yandex.ru
12 * All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are met:
17 * 1. Redistributions of source code must retain the above copyright notice, this
18 * list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright notice,
21 * this list of conditions and the following disclaimer in the documentation
22 * and/or other materials provided with the distribution.
24 * 3. Neither the name of the copyright holder nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
31 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
35 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
36 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
37 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 #include "ucrc_t.h"
42 #include <cstdio>
43 #include <errno.h>
45 uCRC_t::uCRC_t(const std::string &Name, uint8_t Bits, uint64_t Poly, uint64_t Init, bool RefIn, bool RefOut, uint64_t XorOut) : name(Name),
46 poly(Poly),
47 init(Init),
48 xor_out(XorOut),
49 bits(Bits),
50 ref_in(RefIn),
51 ref_out(RefOut)
53 init_class();
56 uCRC_t::uCRC_t(uint8_t Bits, uint64_t Poly, uint64_t Init, bool RefIn, bool RefOut, uint64_t XorOut) : poly(Poly),
57 init(Init),
58 xor_out(XorOut),
59 bits(Bits),
60 ref_in(RefIn),
61 ref_out(RefOut)
63 init_class();
66 uint64_t uCRC_t::get_check() const
68 const uint8_t data[] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39};
70 return get_crc(data, sizeof(data));
73 int uCRC_t::set_bits(uint8_t new_value)
75 if ((new_value < 1) || (new_value > 64))
76 return -1; //error
78 bits = new_value;
79 init_class();
81 return 0; //good job
84 uint64_t uCRC_t::get_crc(const void *data, size_t len) const
86 uint64_t crc = get_raw_crc(data, len, crc_init);
88 return get_final_crc(crc);
91 int uCRC_t::get_crc(uint64_t &crc, const char *file_name) const
93 char buf[4096];
95 return get_crc(crc, file_name, buf, sizeof(buf));
98 int uCRC_t::get_crc(uint64_t &crc, const char *file_name, void *buf, size_t size_buf) const
100 std::ifstream ifs(file_name, std::ios_base::binary);
102 if (!ifs || !buf || !size_buf)
104 errno = EINVAL;
105 return -1;
108 return get_crc(crc, ifs, buf, size_buf);
111 int uCRC_t::get_crc(uint64_t &crc, std::ifstream &ifs, void *buf, size_t size_buf) const
113 crc = crc_init;
115 while (ifs)
117 ifs.read(static_cast<char *>(buf), size_buf);
118 crc = get_raw_crc(buf, ifs.gcount(), crc);
121 crc = get_final_crc(crc);
123 return (ifs.rdstate() & std::ios_base::badbit); //return 0 if all good
126 uint64_t uCRC_t::get_raw_crc(const void *data, size_t len, uint64_t crc) const
128 const uint8_t *buf = static_cast<const uint8_t *>(data);
130 if (bits > 8)
132 if (ref_in)
133 while (len--)
134 crc = (crc >> 8) ^ crc_table[(crc ^ *buf++) & 0xff];
135 else
136 while (len--)
137 crc = (crc << 8) ^ crc_table[((crc >> shift) ^ *buf++) & 0xff];
139 else
141 if (ref_in)
142 while (len--)
143 crc = crc_table[(crc ^ *buf++) & 0xff];
144 else
145 while (len--)
146 crc = crc_table[((crc << shift) ^ *buf++) & 0xff];
149 return crc;
152 uint64_t uCRC_t::get_final_crc(uint64_t raw_crc) const
154 if (ref_out ^ ref_in)
155 raw_crc = reflect(raw_crc, bits);
157 raw_crc ^= xor_out;
158 raw_crc &= crc_mask; //for CRC not power 2
160 return raw_crc;
163 uint64_t uCRC_t::reflect(uint64_t data, uint8_t num_bits) const
165 uint64_t reflection = 0;
167 while (num_bits--)
169 reflection = (reflection << 1) | (data & 1);
170 data >>= 1;
173 return reflection;
176 void uCRC_t::init_crc_table()
178 //Calculation of the standard CRC table for byte.
179 for (int i = 0; i < 256; i++)
182 uint64_t crc = 0;
184 for (uint8_t mask = 0x80; mask; mask >>= 1)
187 if (i & mask)
188 crc ^= top_bit;
190 if (crc & top_bit)
192 crc <<= 1;
193 crc ^= poly;
195 else
196 crc <<= 1;
199 crc &= crc_mask; //for CRC not power 2
201 if (ref_in)
202 crc_table[reflect(i, 8)] = reflect(crc, bits);
203 else
204 crc_table[i] = crc;
208 void uCRC_t::init_class()
210 top_bit = (uint64_t)1 << (bits - 1);
211 crc_mask = ((top_bit - 1) << 1) | 1;
213 if (bits > 8)
214 shift = (bits - 8);
215 else
216 shift = (8 - bits);
218 if (ref_in)
219 crc_init = reflect(init, bits);
220 else
221 crc_init = init;
223 init_crc_table();