bit_lib.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. #include "bit_lib.h"
  2. #include <core/check.h>
  3. #include <stdio.h>
  4. void bit_lib_push_bit(uint8_t* data, size_t data_size, bool bit) {
  5. size_t last_index = data_size - 1;
  6. for(size_t i = 0; i < last_index; ++i) {
  7. data[i] = (data[i] << 1) | ((data[i + 1] >> 7) & 1);
  8. }
  9. data[last_index] = (data[last_index] << 1) | bit;
  10. }
  11. void bit_lib_set_bit(uint8_t* data, size_t position, bool bit) {
  12. if(bit) {
  13. data[position / 8] |= 1UL << (7 - (position % 8));
  14. } else {
  15. data[position / 8] &= ~(1UL << (7 - (position % 8)));
  16. }
  17. }
  18. void bit_lib_set_bits(uint8_t* data, size_t position, uint8_t byte, uint8_t length) {
  19. furi_check(length <= 8);
  20. furi_check(length > 0);
  21. for(uint8_t i = 0; i < length; ++i) {
  22. uint8_t shift = (length - 1) - i;
  23. bit_lib_set_bit(data, position + i, (byte >> shift) & 1);
  24. }
  25. }
  26. bool bit_lib_get_bit(const uint8_t* data, size_t position) {
  27. return (data[position / 8] >> (7 - (position % 8))) & 1;
  28. }
  29. uint8_t bit_lib_get_bits(const uint8_t* data, size_t position, uint8_t length) {
  30. uint8_t shift = position % 8;
  31. if(shift == 0) {
  32. return data[position / 8] >> (8 - length);
  33. } else {
  34. // TODO fix read out of bounds
  35. uint8_t value = (data[position / 8] << (shift));
  36. value |= data[position / 8 + 1] >> (8 - shift);
  37. value = value >> (8 - length);
  38. return value;
  39. }
  40. }
  41. uint16_t bit_lib_get_bits_16(const uint8_t* data, size_t position, uint8_t length) {
  42. uint16_t value = 0;
  43. if(length <= 8) {
  44. value = bit_lib_get_bits(data, position, length);
  45. } else {
  46. value = bit_lib_get_bits(data, position, 8) << (length - 8);
  47. value |= bit_lib_get_bits(data, position + 8, length - 8);
  48. }
  49. return value;
  50. }
  51. uint32_t bit_lib_get_bits_32(const uint8_t* data, size_t position, uint8_t length) {
  52. uint32_t value = 0;
  53. if(length <= 8) {
  54. value = bit_lib_get_bits(data, position, length);
  55. } else if(length <= 16) {
  56. value = bit_lib_get_bits(data, position, 8) << (length - 8);
  57. value |= bit_lib_get_bits(data, position + 8, length - 8);
  58. } else if(length <= 24) {
  59. value = bit_lib_get_bits(data, position, 8) << (length - 8);
  60. value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
  61. value |= bit_lib_get_bits(data, position + 16, length - 16);
  62. } else {
  63. value = bit_lib_get_bits(data, position, 8) << (length - 8);
  64. value |= bit_lib_get_bits(data, position + 8, 8) << (length - 16);
  65. value |= bit_lib_get_bits(data, position + 16, 8) << (length - 24);
  66. value |= bit_lib_get_bits(data, position + 24, length - 24);
  67. }
  68. return value;
  69. }
  70. bool bit_lib_test_parity_32(uint32_t bits, BitLibParity parity) {
  71. #if !defined __GNUC__
  72. #error Please, implement parity test for non-GCC compilers
  73. #else
  74. switch(parity) {
  75. case BitLibParityEven:
  76. return __builtin_parity(bits);
  77. case BitLibParityOdd:
  78. return !__builtin_parity(bits);
  79. default:
  80. furi_crash("Unknown parity");
  81. }
  82. #endif
  83. }
  84. bool bit_lib_test_parity(
  85. const uint8_t* bits,
  86. size_t position,
  87. uint8_t length,
  88. BitLibParity parity,
  89. uint8_t parity_length) {
  90. uint32_t parity_block;
  91. bool result = true;
  92. const size_t parity_blocks_count = length / parity_length;
  93. for(size_t i = 0; i < parity_blocks_count; ++i) {
  94. switch(parity) {
  95. case BitLibParityEven:
  96. case BitLibParityOdd:
  97. parity_block = bit_lib_get_bits_32(bits, position + i * parity_length, parity_length);
  98. if(!bit_lib_test_parity_32(parity_block, parity)) {
  99. result = false;
  100. }
  101. break;
  102. case BitLibParityAlways0:
  103. if(bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
  104. result = false;
  105. }
  106. break;
  107. case BitLibParityAlways1:
  108. if(!bit_lib_get_bit(bits, position + i * parity_length + parity_length - 1)) {
  109. result = false;
  110. }
  111. break;
  112. }
  113. if(!result) break;
  114. }
  115. return result;
  116. }
  117. size_t bit_lib_remove_bit_every_nth(uint8_t* data, size_t position, uint8_t length, uint8_t n) {
  118. size_t counter = 0;
  119. size_t result_counter = 0;
  120. uint8_t bit_buffer = 0;
  121. uint8_t bit_counter = 0;
  122. while(counter < length) {
  123. if((counter + 1) % n != 0) {
  124. bit_buffer = (bit_buffer << 1) | bit_lib_get_bit(data, position + counter);
  125. bit_counter++;
  126. }
  127. if(bit_counter == 8) {
  128. bit_lib_set_bits(data, position + result_counter, bit_buffer, 8);
  129. bit_counter = 0;
  130. bit_buffer = 0;
  131. result_counter += 8;
  132. }
  133. counter++;
  134. }
  135. if(bit_counter != 0) {
  136. bit_lib_set_bits(data, position + result_counter, bit_buffer, bit_counter);
  137. result_counter += bit_counter;
  138. }
  139. return result_counter;
  140. }
  141. void bit_lib_copy_bits(
  142. uint8_t* data,
  143. size_t position,
  144. size_t length,
  145. const uint8_t* source,
  146. size_t source_position) {
  147. for(size_t i = 0; i < length; ++i) {
  148. bit_lib_set_bit(data, position + i, bit_lib_get_bit(source, source_position + i));
  149. }
  150. }
  151. void bit_lib_reverse_bits(uint8_t* data, size_t position, uint8_t length) {
  152. size_t i = 0;
  153. size_t j = length - 1;
  154. while(i < j) {
  155. bool tmp = bit_lib_get_bit(data, position + i);
  156. bit_lib_set_bit(data, position + i, bit_lib_get_bit(data, position + j));
  157. bit_lib_set_bit(data, position + j, tmp);
  158. i++;
  159. j--;
  160. }
  161. }
  162. uint8_t bit_lib_get_bit_count(uint32_t data) {
  163. #if defined __GNUC__
  164. return __builtin_popcountl(data);
  165. #else
  166. #error Please, implement popcount for non-GCC compilers
  167. #endif
  168. }
  169. void bit_lib_print_bits(const uint8_t* data, size_t length) {
  170. for(size_t i = 0; i < length; ++i) {
  171. printf("%u", bit_lib_get_bit(data, i));
  172. }
  173. }
  174. void bit_lib_print_regions(
  175. const BitLibRegion* regions,
  176. size_t region_count,
  177. const uint8_t* data,
  178. size_t length) {
  179. // print data
  180. bit_lib_print_bits(data, length);
  181. printf("\r\n");
  182. // print regions
  183. for(size_t c = 0; c < length; ++c) {
  184. bool print = false;
  185. for(size_t i = 0; i < region_count; i++) {
  186. if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
  187. print = true;
  188. printf("%c", regions[i].mark);
  189. break;
  190. }
  191. }
  192. if(!print) {
  193. printf(" ");
  194. }
  195. }
  196. printf("\r\n");
  197. // print regions data
  198. for(size_t c = 0; c < length; ++c) {
  199. bool print = false;
  200. for(size_t i = 0; i < region_count; i++) {
  201. if(regions[i].start <= c && c < regions[i].start + regions[i].length) {
  202. print = true;
  203. printf("%u", bit_lib_get_bit(data, c));
  204. break;
  205. }
  206. }
  207. if(!print) {
  208. printf(" ");
  209. }
  210. }
  211. printf("\r\n");
  212. }
  213. uint16_t bit_lib_reverse_16_fast(uint16_t data) {
  214. uint16_t result = 0;
  215. result |= (data & 0x8000) >> 15;
  216. result |= (data & 0x4000) >> 13;
  217. result |= (data & 0x2000) >> 11;
  218. result |= (data & 0x1000) >> 9;
  219. result |= (data & 0x0800) >> 7;
  220. result |= (data & 0x0400) >> 5;
  221. result |= (data & 0x0200) >> 3;
  222. result |= (data & 0x0100) >> 1;
  223. result |= (data & 0x0080) << 1;
  224. result |= (data & 0x0040) << 3;
  225. result |= (data & 0x0020) << 5;
  226. result |= (data & 0x0010) << 7;
  227. result |= (data & 0x0008) << 9;
  228. result |= (data & 0x0004) << 11;
  229. result |= (data & 0x0002) << 13;
  230. result |= (data & 0x0001) << 15;
  231. return result;
  232. }
  233. uint16_t bit_lib_crc16(
  234. uint8_t const* data,
  235. size_t data_size,
  236. uint16_t polynom,
  237. uint16_t init,
  238. bool ref_in,
  239. bool ref_out,
  240. uint16_t xor_out) {
  241. uint16_t crc = init;
  242. for(size_t i = 0; i < data_size; ++i) {
  243. uint8_t byte = data[i];
  244. if(ref_in) byte = bit_lib_reverse_16_fast(byte) >> 8;
  245. for(size_t j = 0; j < 8; ++j) {
  246. bool c15 = (crc >> 15 & 1);
  247. bool bit = (byte >> (7 - j) & 1);
  248. crc <<= 1;
  249. if(c15 ^ bit) crc ^= polynom;
  250. }
  251. }
  252. if(ref_out) crc = bit_lib_reverse_16_fast(crc);
  253. crc ^= xor_out;
  254. return crc;
  255. }