<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pl-pl">
<link rel="self" type="application/atom+xml" href="https://forum.atnel.pl/feed.php?f=56&amp;t=3836&amp;mode" />

<title>ATNEL tech-forum</title>
<link href="https://forum.atnel.pl/index.php" />
<updated>2013-09-16T22:14:00+01:00</updated>

<author><name><![CDATA[ATNEL tech-forum]]></name></author>
<id>https://forum.atnel.pl/feed.php?f=56&amp;t=3836&amp;mode</id>
<entry>
<author><name><![CDATA[barney]]></name></author>
<updated>2013-09-16T22:14:00+01:00</updated>
<published>2013-09-16T22:14:00+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=49900#p49900</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=49900#p49900"/>
<title type="html"><![CDATA[Re: CRC w 10 minut]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=49900#p49900"><![CDATA[
phill2k: Tak, czytałem. I muszę przyznać, że wiedzy jest ogrom. Niestety nie tego potrzebowałem, kiedy chciałem zaimplementować standard <img src="https://forum.atnel.pl/images/smilies/icon_e_sad.gif" alt=":(" title="Smutny" />. Kiedy muszę zaimplementować z góry narzuconą technologię to niestety nie interesuje mnie jej etymologia, sens (no, tutaj obchodziła, ale jest oczywista), wydajność/sprawność... tylko chce wiedzieć co muszę zrobić, żeby &quot;było dobrze&quot;.<br /><br />Wiedza tam zawarta jest naprawdę bardzo ciekawa, ale jest jej za dużo... Mnie czytanie tego poradnika wprawiło jedynie w frustrację. Potrzebowałem jedynie zaimplementować CRC, a czytałem o jakiś metodach przy słowie dziesiętnym, co to jest XOR... a na końcu metody były, tylko że było ich z ~5 i nie wiedziałem którą wybrać.<br /><br />Z kolei dokument Maxima w rozdziale &quot;Cyclic Redundancy Check&quot; zawierał to (i jedynie to) czego potrzebowałem, aby zrozumieć co mam zrobić, aby dobrze zaimplementować CRC. I to on do mnie trafił, kiedy poradnik mg101 niestety tego nie potrafił <img src="https://forum.atnel.pl/images/smilies/icon_cry.gif" alt=":cry:" title="Płacze" /><br /><br />-- 12 sie 2013, o 11:51 --<br /><br /><span style="font-size: 150%; line-height: normal"><strong>Optymalizacja przez tablicowanie</strong></span><br />Metoda bit-po-bicie jest metodą najprostszą w implementacji, zajmującą najmniej FLASHa oraz najwolniejszą (no bo nic w życiu nie może być proste <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" />). Obliczanie CRC można przyśpieszyć poprzez przygotowanie tablicy w której będziemy mieć wartość z którą będziemy XORować rejestr w zależności od wartości bitów, które robią &quot;wypad&quot;.<br /><br />Wzorem:<br />Bcrc = Bo + Bp<br />gdzie:<br />Bcrc - ilość bitów rejestru CRC<br />Bo - ilość bitów, których &quot;wypad&quot; będziemy optymalizować (od MSB do LSB)<br />Bp - bity, które pozostaną w rejestrze (od LSB do MSD)<br /><br />Należy pamiętać, że nie interesuje nas wartość bitów Bp, a jedynie wartość z jaką będą one XORowane.<br /><br />Pseudokodem C można zapisać to tak:<br />Bcrc=0bBoBp;<br /><br />Mechanizm optymalizacji opiera się na tym, że jeżeli mamy 16bitowe CRC i wprowadzamy do niego bajt (8bitów) to sekwencja XORowania rejestru kluczem jest zależna jedynie od najstarszych 8bitów rejestru (czyli tych, które zrobią &quot;wypad&quot;). Sekwencję tą można zoptymalizować do postaci:<br />XORoptymalizacji=(XOR0&lt;&lt;0)^(XOR1&lt;&lt;1)^(XOR2&lt;&lt;2)........<br /><br />W praktyce polega to na stablicowaniu wszystkich możliwości bitów Bo za pomocą następującego algorytmu:<br />1. Ustawiamy rejestr CRC na wartość:<br />Bo - obecnie sprawdzana wartość<br />Bp - wszystkie na zero<br />2. Dodajemy do rejestru tyle &quot;0&quot; ile jest Bo (tak jak zwykłe dane)<br />3. W rejestrze czeka na nas nasz XORoptymalizacji <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> <br /><br />Podany algorytm realizuje poniższa funkcja:<br />[syntax=c]voidcrc_table_generator(const u08 number_of_bits)<br />{<br />for (Tcrc x=0; x&lt;((Tcrc)1&lt;&lt;number_of_bits); x++)<br />{<br />crc=(Tcrc)x&lt;&lt;(current_length-number_of_bits+1);<br />for (u08 y=0; y&lt;number_of_bits; y++) crc_add_bit(0);<br />{<br />/*<br /> *Tutaj musimy zapisac stan rejestru (zmienna crc) dla danego indexu tablicy (zmienna x)<br /> */<br />}<br />}<br />}[/syntax]<br />Przed jej wywołaniem inicjalizujemy bibliotekę funkcją crc_init(...), a następnie wywołujemy naszą nową funkcję podając jako parametr ilość bitów które chcemy optymalizować.<br />Mądrze będzie wyrzucić wyliczone wartości na jakiś terminal, aby wygodnie skopiować je do kodu programu.<br /><br />Skoro mamy już mamy naszą tablicę z wyliczonymi sekwencjami XORowania rejestru (zastępującą klucz w metodzie bit-po-bicie) musimy jeszcze przerobić funkcję dodającą bajt do CRC, tak aby była w stanie wykorzystać nową optymalizację <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br />Zakładając, że będziemy korzystać tylko z CRC16 i przygotowaliśmy tablicę dla Bo=8, funkcja może wyglądać tak:<br />[syntax=c]voidcrc_add_byte(u08 byte)<br />{<br />Tcrc get_table_element (const u08 table_index)<br />{<br />Tcrc ret=0;<br />for (u08 x=0; x&lt;2; x++) ret=(ret&lt;&lt;8)|pgm_read_byte(&amp;tablica_z_wyliczonymi_wartosciami&#91;table_index*2+x&#93;);<br />return ret;<br />}<br />crc=(((Tcrc)crc&lt;&lt;8)|byte)^get_table_element(crc&gt;&gt;8);<br />}[/syntax]<br />Czyli do rejestru jest dodawany nowy bajt, a potem rejestr jest XORowany wartością zapisaną pod indeksem tablicy będącym bajtem, który zaliczył &quot;wypad&quot; z rejestru.<br /><br />Kilka właściwości:<br />1. Możliwe jest wykorzystanie tablicy przygotowanej dla n bitów podczas dodawania m&lt;=n bitów.<br />Dowód<br />Bo_m=3<br />Bo_n=5<br /><br />Stan wejściowy CRC (przy generowaniu tablic dla takich ilości bitów i wartości bitów Bo = 3 (0b011)), rejestr CRC 8 bitowy:<br />CRC_m=0b01100000; // 3x&quot;0&quot;<br />CRC_n=0b00011000; // 5x&quot;0&quot;<br /><br />Po dodawaniu zer tak długo, aż następnym bitem, który zrobi &quot;wypad&quot; będzie &quot;1&quot; uzyskamy<br />CRC_m=0b11100000; // 2x&quot;0&quot; - wsunęliśmy 1 bit<br />CRC_n=0b11100000; // 2x&quot;0&quot; - wsunęliśmy 3 bity, wartości rejestrów zrównały się<br /><br />2. Możliwe jest stosowanie tablicy optymalizacji obliczonej dla Klucza1, dla Klucza2, jeżeli K2 ma mniej bitów niż K1 i ich wartości są identyczne z tymi klucza K1 (aż do końca bitów K2, potem bez znaczenia).<br /><br />3. Szybkość konwersji skaluje się prawie liniowo do ilości bitów optymalizacji:<br />Szybkość=Szybkość_bit_po_bicie*Bo<br />Zajętość pamięci niestety rośnie wykładniczo:<br />FLASH=(rozmiar_rejestru)*(2^Bo)<br /><br />Nowe kody:<br />bCRCnoInit.h (kompilator narzekał na niewykorzystane definicje i deklaracje)<br />[syntax=c]/*<br /> *Cyclic Redundance Check calculation<br /> * Created on: 10-08-2013v1<br /> *Author: barney<br /> *forum.atnel.pl<br /> */<br /><br />#include &quot;../common.h&quot;<br /><br />#ifndef BCRCNOINIT_H_<br />#define BCRCNOINIT_H_<br /><br />typedef u16 Tcrc;// Maximum crc size<br /><br />voidcrc_add_byte(u08 byte);<br />Tcrccrc_read(void);<br /><br />#endif /* BCRCNOINIT_H_ */[/syntax]<br /><br />bCRC.h<br />[syntax=c]/*<br /> *Cyclic Redundance Check calculation<br /> * Created on: 10-08-2013v1<br /> *Author: barney<br /> *forum.atnel.pl<br /> */<br /><br />#include &quot;bCRCnoInit.h&quot;<br />#include &lt;avr/pgmspace.h&gt;<br /><br />#ifndef CRC_H_<br />#define CRC_H_<br /><br />extern const u08 crc16_table &#91;256&#93; &#91;2&#93; PROGMEM;<br />static inline u08 log2b (u16 x)<br />{<br />u08 ret=0;<br />while ((x&gt;&gt;=1)) ret++;<br />return ret;<br />}<br /><br />#define CRC_RST0,(Tcrc)0,0,0,0<br />#define CRC77,(Tcrc) 0b10001001/* x^7 + x^3 + x^0 */,0,0,0<br />#define CRC1616,(Tcrc) 0b10001000000100001/* x^16+ x^12+ x^5+ x^0 */,crc16_table,log2b(sizeof(crc16_table)/sizeof(crc16_table&#91;0&#93;)),sizeof(crc16_table&#91;0&#93;)<br /><br />/*<br /> *If length==0 then only re-init.<br /> */<br />voidcrc_init(const u08 length, const Tcrc polynomial, const void const *table, const u08 table_bits, const u08 table_element_size);// If length==0 then only re-init.<br /><br />//voidcrc_table_generator(u08 number_of_bits);<br /><br />#endif /* CRC_H_ */[/syntax]<br /><br />[syntax=c]bCRC.c<br />/*<br /> *Cyclic Redundance Check calculation<br /> * Created on: 10-08-2013v1<br /> *Author: barney<br /> *forum.atnel.pl<br /> */<br /><br />#include &quot;bCRC.h&quot;<br /><br />const u08 crc16_table &#91;256&#93; &#91;2&#93; PROGMEM =<br />{<br />{0b00000000, 0b00000000},// 000<br />{0b00010000, 0b00100001},// 001<br />{0b00100000, 0b01000010},// 002<br />{0b00110000, 0b01100011},// 003<br />{0b01000000, 0b10000100},// 004<br />{0b01010000, 0b10100101},// 005<br />{0b01100000, 0b11000110},// 006<br />{0b01110000, 0b11100111},// 007<br />{0b10000001, 0b00001000},// 008<br />{0b10010001, 0b00101001},// 009<br />{0b10100001, 0b01001010},// 010<br />{0b10110001, 0b01101011},// 011<br />{0b11000001, 0b10001100},// 012<br />{0b11010001, 0b10101101},// 013<br />{0b11100001, 0b11001110},// 014<br />{0b11110001, 0b11101111},// 015<br />{0b00010010, 0b00110001},// 016<br />{0b00000010, 0b00010000},// 017<br />{0b00110010, 0b01110011},// 018<br />{0b00100010, 0b01010010},// 019<br />{0b01010010, 0b10110101},// 020<br />{0b01000010, 0b10010100},// 021<br />{0b01110010, 0b11110111},// 022<br />{0b01100010, 0b11010110},// 023<br />{0b10010011, 0b00111001},// 024<br />{0b10000011, 0b00011000},// 025<br />{0b10110011, 0b01111011},// 026<br />{0b10100011, 0b01011010},// 027<br />{0b11010011, 0b10111101},// 028<br />{0b11000011, 0b10011100},// 029<br />{0b11110011, 0b11111111},// 030<br />{0b11100011, 0b11011110},// 031<br />{0b00100100, 0b01100010},// 032<br />{0b00110100, 0b01000011},// 033<br />{0b00000100, 0b00100000},// 034<br />{0b00010100, 0b00000001},// 035<br />{0b01100100, 0b11100110},// 036<br />{0b01110100, 0b11000111},// 037<br />{0b01000100, 0b10100100},// 038<br />{0b01010100, 0b10000101},// 039<br />{0b10100101, 0b01101010},// 040<br />{0b10110101, 0b01001011},// 041<br />{0b10000101, 0b00101000},// 042<br />{0b10010101, 0b00001001},// 043<br />{0b11100101, 0b11101110},// 044<br />{0b11110101, 0b11001111},// 045<br />{0b11000101, 0b10101100},// 046<br />{0b11010101, 0b10001101},// 047<br />{0b00110110, 0b01010011},// 048<br />{0b00100110, 0b01110010},// 049<br />{0b00010110, 0b00010001},// 050<br />{0b00000110, 0b00110000},// 051<br />{0b01110110, 0b11010111},// 052<br />{0b01100110, 0b11110110},// 053<br />{0b01010110, 0b10010101},// 054<br />{0b01000110, 0b10110100},// 055<br />{0b10110111, 0b01011011},// 056<br />{0b10100111, 0b01111010},// 057<br />{0b10010111, 0b00011001},// 058<br />{0b10000111, 0b00111000},// 059<br />{0b11110111, 0b11011111},// 060<br />{0b11100111, 0b11111110},// 061<br />{0b11010111, 0b10011101},// 062<br />{0b11000111, 0b10111100},// 063<br />{0b01001000, 0b11000100},// 064<br />{0b01011000, 0b11100101},// 065<br />{0b01101000, 0b10000110},// 066<br />{0b01111000, 0b10100111},// 067<br />{0b00001000, 0b01000000},// 068<br />{0b00011000, 0b01100001},// 069<br />{0b00101000, 0b00000010},// 070<br />{0b00111000, 0b00100011},// 071<br />{0b11001001, 0b11001100},// 072<br />{0b11011001, 0b11101101},// 073<br />{0b11101001, 0b10001110},// 074<br />{0b11111001, 0b10101111},// 075<br />{0b10001001, 0b01001000},// 076<br />{0b10011001, 0b01101001},// 077<br />{0b10101001, 0b00001010},// 078<br />{0b10111001, 0b00101011},// 079<br />{0b01011010, 0b11110101},// 080<br />{0b01001010, 0b11010100},// 081<br />{0b01111010, 0b10110111},// 082<br />{0b01101010, 0b10010110},// 083<br />{0b00011010, 0b01110001},// 084<br />{0b00001010, 0b01010000},// 085<br />{0b00111010, 0b00110011},// 086<br />{0b00101010, 0b00010010},// 087<br />{0b11011011, 0b11111101},// 088<br />{0b11001011, 0b11011100},// 089<br />{0b11111011, 0b10111111},// 090<br />{0b11101011, 0b10011110},// 091<br />{0b10011011, 0b01111001},// 092<br />{0b10001011, 0b01011000},// 093<br />{0b10111011, 0b00111011},// 094<br />{0b10101011, 0b00011010},// 095<br />{0b01101100, 0b10100110},// 096<br />{0b01111100, 0b10000111},// 097<br />{0b01001100, 0b11100100},// 098<br />{0b01011100, 0b11000101},// 099<br />{0b00101100, 0b00100010},// 100<br />{0b00111100, 0b00000011},// 101<br />{0b00001100, 0b01100000},// 102<br />{0b00011100, 0b01000001},// 103<br />{0b11101101, 0b10101110},// 104<br />{0b11111101, 0b10001111},// 105<br />{0b11001101, 0b11101100},// 106<br />{0b11011101, 0b11001101},// 107<br />{0b10101101, 0b00101010},// 108<br />{0b10111101, 0b00001011},// 109<br />{0b10001101, 0b01101000},// 110<br />{0b10011101, 0b01001001},// 111<br />{0b01111110, 0b10010111},// 112<br />{0b01101110, 0b10110110},// 113<br />{0b01011110, 0b11010101},// 114<br />{0b01001110, 0b11110100},// 115<br />{0b00111110, 0b00010011},// 116<br />{0b00101110, 0b00110010},// 117<br />{0b00011110, 0b01010001},// 118<br />{0b00001110, 0b01110000},// 119<br />{0b11111111, 0b10011111},// 120<br />{0b11101111, 0b10111110},// 121<br />{0b11011111, 0b11011101},// 122<br />{0b11001111, 0b11111100},// 123<br />{0b10111111, 0b00011011},// 124<br />{0b10101111, 0b00111010},// 125<br />{0b10011111, 0b01011001},// 126<br />{0b10001111, 0b01111000},// 127<br />{0b10010001, 0b10001000},// 128<br />{0b10000001, 0b10101001},// 129<br />{0b10110001, 0b11001010},// 130<br />{0b10100001, 0b11101011},// 131<br />{0b11010001, 0b00001100},// 132<br />{0b11000001, 0b00101101},// 133<br />{0b11110001, 0b01001110},// 134<br />{0b11100001, 0b01101111},// 135<br />{0b00010000, 0b10000000},// 136<br />{0b00000000, 0b10100001},// 137<br />{0b00110000, 0b11000010},// 138<br />{0b00100000, 0b11100011},// 139<br />{0b01010000, 0b00000100},// 140<br />{0b01000000, 0b00100101},// 141<br />{0b01110000, 0b01000110},// 142<br />{0b01100000, 0b01100111},// 143<br />{0b10000011, 0b10111001},// 144<br />{0b10010011, 0b10011000},// 145<br />{0b10100011, 0b11111011},// 146<br />{0b10110011, 0b11011010},// 147<br />{0b11000011, 0b00111101},// 148<br />{0b11010011, 0b00011100},// 149<br />{0b11100011, 0b01111111},// 150<br />{0b11110011, 0b01011110},// 151<br />{0b00000010, 0b10110001},// 152<br />{0b00010010, 0b10010000},// 153<br />{0b00100010, 0b11110011},// 154<br />{0b00110010, 0b11010010},// 155<br />{0b01000010, 0b00110101},// 156<br />{0b01010010, 0b00010100},// 157<br />{0b01100010, 0b01110111},// 158<br />{0b01110010, 0b01010110},// 159<br />{0b10110101, 0b11101010},// 160<br />{0b10100101, 0b11001011},// 161<br />{0b10010101, 0b10101000},// 162<br />{0b10000101, 0b10001001},// 163<br />{0b11110101, 0b01101110},// 164<br />{0b11100101, 0b01001111},// 165<br />{0b11010101, 0b00101100},// 166<br />{0b11000101, 0b00001101},// 167<br />{0b00110100, 0b11100010},// 168<br />{0b00100100, 0b11000011},// 169<br />{0b00010100, 0b10100000},// 170<br />{0b00000100, 0b10000001},// 171<br />{0b01110100, 0b01100110},// 172<br />{0b01100100, 0b01000111},// 173<br />{0b01010100, 0b00100100},// 174<br />{0b01000100, 0b00000101},// 175<br />{0b10100111, 0b11011011},// 176<br />{0b10110111, 0b11111010},// 177<br />{0b10000111, 0b10011001},// 178<br />{0b10010111, 0b10111000},// 179<br />{0b11100111, 0b01011111},// 180<br />{0b11110111, 0b01111110},// 181<br />{0b11000111, 0b00011101},// 182<br />{0b11010111, 0b00111100},// 183<br />{0b00100110, 0b11010011},// 184<br />{0b00110110, 0b11110010},// 185<br />{0b00000110, 0b10010001},// 186<br />{0b00010110, 0b10110000},// 187<br />{0b01100110, 0b01010111},// 188<br />{0b01110110, 0b01110110},// 189<br />{0b01000110, 0b00010101},// 190<br />{0b01010110, 0b00110100},// 191<br />{0b11011001, 0b01001100},// 192<br />{0b11001001, 0b01101101},// 193<br />{0b11111001, 0b00001110},// 194<br />{0b11101001, 0b00101111},// 195<br />{0b10011001, 0b11001000},// 196<br />{0b10001001, 0b11101001},// 197<br />{0b10111001, 0b10001010},// 198<br />{0b10101001, 0b10101011},// 199<br />{0b01011000, 0b01000100},// 200<br />{0b01001000, 0b01100101},// 201<br />{0b01111000, 0b00000110},// 202<br />{0b01101000, 0b00100111},// 203<br />{0b00011000, 0b11000000},// 204<br />{0b00001000, 0b11100001},// 205<br />{0b00111000, 0b10000010},// 206<br />{0b00101000, 0b10100011},// 207<br />{0b11001011, 0b01111101},// 208<br />{0b11011011, 0b01011100},// 209<br />{0b11101011, 0b00111111},// 210<br />{0b11111011, 0b00011110},// 211<br />{0b10001011, 0b11111001},// 212<br />{0b10011011, 0b11011000},// 213<br />{0b10101011, 0b10111011},// 214<br />{0b10111011, 0b10011010},// 215<br />{0b01001010, 0b01110101},// 216<br />{0b01011010, 0b01010100},// 217<br />{0b01101010, 0b00110111},// 218<br />{0b01111010, 0b00010110},// 219<br />{0b00001010, 0b11110001},// 220<br />{0b00011010, 0b11010000},// 221<br />{0b00101010, 0b10110011},// 222<br />{0b00111010, 0b10010010},// 223<br />{0b11111101, 0b00101110},// 224<br />{0b11101101, 0b00001111},// 225<br />{0b11011101, 0b01101100},// 226<br />{0b11001101, 0b01001101},// 227<br />{0b10111101, 0b10101010},// 228<br />{0b10101101, 0b10001011},// 229<br />{0b10011101, 0b11101000},// 230<br />{0b10001101, 0b11001001},// 231<br />{0b01111100, 0b00100110},// 232<br />{0b01101100, 0b00000111},// 233<br />{0b01011100, 0b01100100},// 234<br />{0b01001100, 0b01000101},// 235<br />{0b00111100, 0b10100010},// 236<br />{0b00101100, 0b10000011},// 237<br />{0b00011100, 0b11100000},// 238<br />{0b00001100, 0b11000001},// 239<br />{0b11101111, 0b00011111},// 240<br />{0b11111111, 0b00111110},// 241<br />{0b11001111, 0b01011101},// 242<br />{0b11011111, 0b01111100},// 243<br />{0b10101111, 0b10011011},// 244<br />{0b10111111, 0b10111010},// 245<br />{0b10001111, 0b11011001},// 246<br />{0b10011111, 0b11111000},// 247<br />{0b01101110, 0b00010111},// 248<br />{0b01111110, 0b00110110},// 249<br />{0b01001110, 0b01010101},// 250<br />{0b01011110, 0b01110100},// 251<br />{0b00101110, 0b10010011},// 252<br />{0b00111110, 0b10110010},// 253<br />{0b00001110, 0b11010001},// 254<br />{0b00011110, 0b11110000}// 255<br />};<br /><br />static Tcrc crc, current_polynomial, crc_mask;<br />static u08 current_length, current_table_bits, current_table_element_size;<br />static const u08 *current_table;<br /><br />static void crc_add_bit(const u08 new_bit);<br /><br />//#include &lt;stdlib.h&gt;<br />//#include &quot;../../mkUART/mkuart.h&quot;<br />//voidcrc_table_generator(const u08 number_of_bits)<br />//{<br />//for (Tcrc x=0; x&lt;((Tcrc)1&lt;&lt;number_of_bits); x++)<br />//{<br />//crc=(Tcrc)x&lt;&lt;(current_length-number_of_bits+1);<br />//for (u08 y=0; y&lt;number_of_bits; y++) crc_add_bit(0);<br />//{// Here save 'crc' for current 'x' table position<br />//void uart_bin (u08 x)<br />//{<br />//uart_puts_P(PSTR(&quot;0b&quot;));<br />//for (u08 y=8; --y;) if (x&lt;((Tcrc)1&lt;&lt;y)) uart_putc('0');<br />//char buf &#91;17&#93;;<br />//uart_puts(ltoa(x, buf, 2));<br />//}<br />//{<br />//char buf &#91;4&#93;;<br />//uart_putc('{');<br />//uart_bin(crc&gt;&gt;8);<br />//uart_puts_P(PSTR(&quot;, &quot;));<br />//uart_bin(crc);<br />//uart_puts_P(PSTR(&quot;},\t// &quot;));<br />//if (x&lt;100)uart_putc('0');<br />//if (x&lt;10)uart_putc('0');<br />//uart_puts(ltoa(x, buf, 10));<br />//uart_puts_P(PSTR(&quot;\n\r&quot;));<br />//}<br />//}<br />//}<br />//}<br /><br />voidcrc_init(const u08 length, const Tcrc polynomial, const void const *table, const u08 table_bits, const u08 table_element_size)// If length==0 then only re-init.<br />{<br />crc=(Tcrc)0;<br />if (length)<br />{<br />current_length=length-1;<br />current_polynomial=(Tcrc)polynomial;<br />current_table=table;<br />current_table_bits=table_bits;<br />current_table_element_size=table_element_size;<br /><br />crc_mask=(Tcrc)0;<br />for (u08 x=0; x&lt;=current_length; x++) crc_mask|=(Tcrc)1&lt;&lt;x;<br />}<br />}<br /><br />static void crc_add_bit(const u08 new_bit)<br />{<br />u08 do_xor=((Tcrc)crc&gt;&gt;current_length)&amp;0b1;<br />crc=(Tcrc)(crc&lt;&lt;1)|new_bit;<br />if (do_xor) crc^=(Tcrc)current_polynomial;<br />}<br /><br />voidcrc_add_byte(u08 byte)<br />{<br />if (!current_table)<br />for (u08 x=0; x&lt;8; x++)<br />{<br />crc_add_bit(byte&gt;&gt;7);<br />byte&lt;&lt;=1;<br />}<br />else<br />{<br />Tcrc get_table_element (const u08 table_index)<br />{<br />Tcrc ret=0;<br />for (u08 x=0; x&lt;current_table_element_size; x++) ret=(ret&lt;&lt;8)|pgm_read_byte(&amp;current_table&#91;table_index*current_table_element_size+x&#93;);<br />return ret;<br />}<br /><br />//{// Universal method<br />//u08 bits_to_do=8;<br />//<br />//while (bits_to_do&gt;=current_table_bits)<br />//{<br />//bits_to_do-=current_table_bits;<br />//crc=(((Tcrc)crc&lt;&lt;current_table_bits)|(byte&gt;&gt;(8-current_table_bits)))^get_table_element((crc&gt;&gt;(current_length+1-current_table_bits))&amp;((1&lt;&lt;current_table_bits)-1));<br />//byte&lt;&lt;=current_table_bits;<br />//}<br />//if (bits_to_do) crc=(((Tcrc)crc&lt;&lt;bits_to_do)|(byte&gt;&gt;(8-bits_to_do)))^get_table_element((crc&gt;&gt;(current_length+1-bits_to_do))&amp;((1&lt;&lt;bits_to_do)-1));<br />//}<br />{// 8bit method<br />crc=(((Tcrc)crc&lt;&lt;8)|byte)^get_table_element(crc&gt;&gt;8);<br />}<br />//{// 4bit method<br />//for (u08 x=0; x&lt;2; x++)<br />//{<br />//crc=(((Tcrc)crc&lt;&lt;4)|(byte&gt;&gt;4))^get_table_element((Tcrc)crc&gt;&gt;12);<br />//byte&lt;&lt;=4;<br />//}<br />//}<br />}<br />}<br /><br />Tcrccrc_read(void)<br />{<br />u08 bits_to_do=current_length+1;<br /><br />while (bits_to_do&gt;=8)<br />{<br />bits_to_do-=8;<br />crc_add_byte(0);<br />}<br />while (bits_to_do--) crc_add_bit(0);<br /><br />return (Tcrc)crc&amp;crc_mask;<br />}[/syntax]<br /><br />Tablica wartości dla CRC16 do wykorzystania przy kartach SD w bonusie <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" /><br /><br />No i kilka fotek z pogaduszek z kartą <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /><br />F_CPU=8MHz<br />SPI=F_CPU/2 (czyli do oporu <img src="https://forum.atnel.pl/images/smilies/icon_twisted.gif" alt=":twisted:" title="Szalony" /> )<br /><br />Dla transmisji bajtu T1-T2 to czas transmisji SPI, width to czas obliczeń (w większości).<br />Dla transmisji bloku T1-T2 to czas faktycznego przesyłania bloku, a width zawiera do tego &quot;prolog&quot; i &quot;epilog&quot; transmisji.<br /><br />Bit-po-bicie<br /><a href="http://forum.atnel.pl/_obrazki/o/973/a965912c7c4c0beac290807bdff5c4db.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/a965912c7c4c0beac290807bdff5c4db.jpg" alt="Obrazek" /></a> <a href="http://forum.atnel.pl/_obrazki/o/973/409149b30e68dafb7dd7de6b60dfd37e.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/409149b30e68dafb7dd7de6b60dfd37e.jpg" alt="Obrazek" /></a><br /><br />Optymalizacja 4bitowa<br /><a href="http://forum.atnel.pl/_obrazki/o/973/292c52f59c13ecdcd6b4998a1bc1df30.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/292c52f59c13ecdcd6b4998a1bc1df30.jpg" alt="Obrazek" /></a> <a href="http://forum.atnel.pl/_obrazki/o/973/dec120d344bb7ad704dd8368c02035a4.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/dec120d344bb7ad704dd8368c02035a4.jpg" alt="Obrazek" /></a><br /><br />Optymalizacja 8bitowa<br /><a href="http://forum.atnel.pl/_obrazki/o/973/de7c3da09444f20f759cae0fb750eca1.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/de7c3da09444f20f759cae0fb750eca1.jpg" alt="Obrazek" /></a> <a href="http://forum.atnel.pl/_obrazki/o/973/703faec46992ee09ce2d1125a0609aa3.jpg"  class="postlink"><img src="http://forum.atnel.pl/_obrazki/o/thumb/973/703faec46992ee09ce2d1125a0609aa3.jpg" alt="Obrazek" /></a><br /><br />W kodach jest jeszcze metoda uniwersalna, ale jak to metody uniwersalne mają w zwyczaju, jej szybkość jest taka, że żal pokazywać (dla 8 bitów optymalizacji ~połowa czasu bit-po-bicie)...<br /><br />Na zakończenie chciałbym podziękować Fredkowi za analizator stanów, bez niego nic nie byłoby takie proste <img src="https://forum.atnel.pl/images/smilies/icon_cool.gif" alt="8-)" title="Cool" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=973">barney</a> — 16 wrz 2013, o 22:14</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[mirekk36]]></name></author>
<updated>2013-08-12T09:43:47+01:00</updated>
<published>2013-08-12T09:43:47+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45432#p45432</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45432#p45432"/>
<title type="html"><![CDATA[Re: CRC w 10 minut]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45432#p45432"><![CDATA[
<div class="quotetitle">phill2k napisał(a):</div><div class="quotecontent"><br />A tam, a tam   , cudze chwalicie swego nie znacie   , a to czytałeś - <!-- l --><a class="postlink-local" href="http://forum.atnel.pl/post42077.html#p42077" >post42077.html#p42077</a><!-- l --><br /></div><br /><br />No dokładnie <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ja też się zdziwiłem bo już jeden tłusty poradnik leży na forum <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> ale jak to mówią od przybytku głowa nie boli <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=54">mirekk36</a> — 12 sie 2013, o 09:43</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[phill2k]]></name></author>
<updated>2013-08-12T07:31:05+01:00</updated>
<published>2013-08-12T07:31:05+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45424#p45424</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45424#p45424"/>
<title type="html"><![CDATA[Re: CRC w 10 minut]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45424#p45424"><![CDATA[
<div class="quotetitle">barney napisał(a):</div><div class="quotecontent"><br />Pomalutku, powolutku przymierzam się do obsługi kart SD. Stwierdziłem, że dobrze będzie mieć działające CRC. Niestety wszystko co znalazłem w internecie to jakaś czarna magia i miliony wzorów, a nic prosto wyjaśnionego co i jak po kolei zrobić, żeby &quot;było dobrze&quot;.<br /><br />I gdybym nie znalazł tego: <!-- m --><a class="postlink" href="http://www.maximintegrated.com/app-notes/index.mvp/id/3969" >http://www.maximintegrated.com/app-note ... vp/id/3969</a><!-- m --> to chyba pogryzłbym stykówkę<br /></div><br /><br />A tam, a tam  <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> , cudze chwalicie swego nie znacie  <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /> , a to czytałeś  - <a href="http://forum.atnel.pl/post42077.html#p42077"  class="postlink">http://forum.atnel.pl/post42077.html#p42077</a>  <img src="https://forum.atnel.pl/images/smilies/icon_e_biggrin.gif" alt=":D" title="Bardzo szczęśliwy" /><p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=75">phill2k</a> — 12 sie 2013, o 07:31</p><hr />
]]></content>
</entry>
<entry>
<author><name><![CDATA[barney]]></name></author>
<updated>2013-08-11T22:45:10+01:00</updated>
<published>2013-08-11T22:45:10+01:00</published>
<id>https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45399#p45399</id>
<link href="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45399#p45399"/>
<title type="html"><![CDATA[CRC w 10 minut]]></title>

<content type="html" xml:base="https://forum.atnel.pl/viewtopic.php?t=3836&amp;p=45399#p45399"><![CDATA[
Pomalutku, powolutku przymierzam się do obsługi kart SD. Stwierdziłem, że dobrze będzie mieć działające CRC. Niestety wszystko co znalazłem w internecie to jakaś czarna magia i miliony wzorów, a nic prosto wyjaśnionego co i jak po kolei zrobić, żeby &quot;było dobrze&quot;.<br /><br />I gdybym nie znalazł tego: <a href="http://www.maximintegrated.com/app-notes/index.mvp/id/3969"  class="postlink">http://www.maximintegrated.com/app-notes/index.mvp/id/3969</a> to chyba pogryzłbym stykówkę <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" /><br /><br />A teraz spróbuję wyjaśnić jak obsłużyć CRC najprościej jak się da <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br /><br /><strong>Co to jest CRC?</strong><br />Są to nadmiarowe bity danych dodawane do właściwych, dzięki którym można z wysokim prawdopodobieństwem stwierdzić integralność tychże bitów.<br />&quot;Standard&quot; CRC określa sposób obliczania tych nadmiarowych bitów, a jego podtypy (CRC7 / CRC16 / CRC8) określają jego dalsze parametry.<br /><br /><strong>Czym się różni CRC7 od CRC16?</strong><br />Różni się ilością nadmiarowych bitów (7/16). Wymusza to różną długość rejestru przesuwnego oraz klucza (mądrzy ludzie nazywają to wielomianem, cholera wie dlaczego <img src="https://forum.atnel.pl/images/smilies/icon_lol.gif" alt=":lol:" title="Śmieje się" /> ).<br /><br /><strong>Co to jest rejestr przesuwny?</strong><br />Jest to miejsce gdzie będziemy obliczać nasze CRC. Można to porównać do rejestru SPDR w SPI. Nowy bit jaki chcemy dodać do sumy wchodzi do LSB, cały rejestr jest przesuwany, a MSB traci miejsce w rejestrze, ale w zależności od jego wartości będziemy robić XORowanie rejestru kluczem.<br /><br /><strong>Co to jest klucz?</strong><br />Klucz jest to stała wartość dla danego podtypu CRC, którą w pewnej sytuacji XORuję się rejestr. Niektóre podtypy mają tą samą ilość bitów, ale różne klucze, powoduje to uzyskanie różnych sum kontrolnych dla tych samych danych.<br /><br /><span style="font-size: 125%; line-height: normal"><strong>A teraz zaimplementujmy co trzeba <img src="https://forum.atnel.pl/images/smilies/icon_e_smile.gif" alt=":)" title="Szczęśliwy" /> </strong></span><br /><br /><strong>Inicjacja</strong> - &quot;Zacznijmy od początku...&quot;<br />Inicjacja polega jedynie na wyzerowaniu rejestru. Jeżeli podtyp się zmienił należy dodatkowo podać jego parametry.<br /><br /><strong>Dodajemy bit</strong> - &quot;Weź się posuń, a jak się nie mieścisz to wypad&quot;<br />Jako, że bit jest najmniejszą jednostką niosącą informację, to jego dodanie opiszę. Nie ma sensu budować piramidy od czubka <img src="https://forum.atnel.pl/images/smilies/icon_e_wink.gif" alt=";)" title="Puszcza oko" /><br />Bit danych których sumę kontrolną chcemy obliczyć wpisujemy do LSB rejestru. Poprzednią wartość rejestru przesuwamy &quot;w lewo&quot; / &quot;w stronę MSB&quot; / &quot;&lt;&lt;1&quot;. Jeżeli bit który zrobił &quot;wypad&quot; (poprzednie MSB) to 1 to cały rejestr XORujemy kluczem. Jeżeli było to 0 to nie robimy nic.<br /><br /><strong>Finalizowanie obliczeń</strong> - &quot;Wszystko dobre co się dobrze kończy&quot;<br />Kiedy dodaliśmy już wszystkie dane, których sumę chcemy obliczyć, musimy jeszcze dodać tyle bitów '0' ile wynosi wielkość rejestru. Traktujemy je oczywiście jako zwykłe dane (jak przy dodawaniu bitów). I to wszystko! W rejestrze czeka na nas nasze wyczekiwane CRC <img src="https://forum.atnel.pl/images/smilies/icon_cool.gif" alt="8-)" title="Cool" /> <br /><br />crc.h<br />[syntax=c]/*<br /> *Basic SD library for sector access<br /> * Created on: 10-08-2013v1<br /> *Author: barney<br /> *forum.atnel.pl<br /> *<br /> *Cyclic Redundance Check calculation<br /> */<br /><br />#include &quot;common.h&quot;<br /><br />#ifndef CRC_H_<br />#define CRC_H_<br /><br />typedef u16 Tcrc;// Maximum crc size<br /><br />#define CRC_RST(Tcrc) 0,0<br />#define CRC7(Tcrc) 0b0001001/* x^7 + x^3 + 1 */,7<br />#define CRC16(Tcrc) 0b1000000000000101/* x^16 + x^15 + x^2 + 1 */,16<br /><br />voidcrc_init(const Tcrc polynomial, const u08 length);// length=0 - do not change, only re-init<br />voidcrc_add_byte(u08 byte);<br />Tcrccrc_read(void);<br /><br />#endif /* CRC_H_ */[/syntax]<br /><br />crc.c<br />[syntax=c]/*<br /> *Basic SD library for sector access<br /> * Created on: 10-08-2013v1<br /> *Author: barney<br /> *forum.atnel.pl<br /> *<br /> *Cyclic Redundance Check calculation<br /> */<br /><br />#include &quot;crc.h&quot;<br /><br />static Tcrc crc, current_polynomial, crc_mask;<br />static u08 current_length;<br /><br />voidcrc_init(const Tcrc polynomial, const u08 length)// length=0 - do not change, only re-init<br />{<br />if (length)<br />{<br />current_polynomial=polynomial;<br />current_length=length-1;<br /><br />crc_mask=0;<br />for (u08 x=0; x&lt;=current_length; x++) crc_mask|=(Tcrc)1&lt;&lt;x;<br />}<br />crc=(Tcrc)0;<br />}<br /><br />static void crc_add_bit(const u08 new_bit)<br />{<br />u08 do_xor=(crc&gt;&gt;current_length)&amp;0b1;<br />crc=(Tcrc)(crc&lt;&lt;1)|new_bit;<br />if (do_xor) crc^=(Tcrc)current_polynomial;<br />}<br /><br />voidcrc_add_byte(u08 byte)<br />{<br />for (u08 x=0; x&lt;8; x++)<br />{<br />crc_add_bit(byte&gt;&gt;7);<br />byte&lt;&lt;=1;<br />}<br />}<br /><br />Tcrccrc_read(void)<br />{<br />for (u08 x=0; x&lt;=current_length; x++) crc_add_bit(0);<br />return (Tcrc)crc&amp;crc_mask;<br />}[/syntax]<p>Statystyki: Napisane przez <a href="https://forum.atnel.pl/memberlist.php?mode=viewprofile&amp;u=973">barney</a> — 11 sie 2013, o 22:45</p><hr />
]]></content>
</entry>
</feed>