ATNEL tech-forum https://forum.atnel.pl/ |
|
Tablica wartości funkcji utworzona preprocesorem https://forum.atnel.pl/topic3419.html |
Strona 1 z 1 |
Autor: | Krauser [ 29 cze 2013, o 17:50 ] |
Tytuł: | Tablica wartości funkcji utworzona preprocesorem |
Przeglądając sieć natrafiłem na fajny trik. Typowe podejście na tablicę wartości funkcji wygląda tak, że chcąc skorzystać z przykładowo sinusa, dołączamy do programu kod np. z tej strony albo sami obliczamy to w arkuszu kalkulacyjnym i przenosimy łatwiej lub trudniej do kodu programu. Można to zrobić też jak pokazano poniżej: Plik main.c: język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Plik values.txt: język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jeśli tak jak w przykładzie potrzeba 24 wartości sinusa to w pliku values.txt 24 razy powtarza się dokładnie tą samą linię. Parametr __LINE__ zwraca numer linii (tutaj 1-24). Jako, że zaczyna się numeracja od 1 to we wzorze na sinus odejmowana jest najpierw 1 i wtedy argument ma wartość 0-23. Przeliczając to na stopnie mnoży się razy krok czyli 15, bo akurat potrzeba 24 wartości z całego zakresu 0-360 stopni. Następnie konieczna jest zamiana stopni na radiany (/180.0*M_PI) dlatego, że funkcja sinus na takich wartościach operuje. Kolejnym krokiem jest dopasowanie wyniku do wartości 0-255 co jest realizowane poprzez pomnożenie razy 128 i dodanie 127. No i już nie potrzeba korzystać z innych programów |
Autor: | mirekk36 [ 29 cze 2013, o 18:56 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
O matko jak pierwszy raz to przeczytałem i zobaczyłem to - powiedziałem tylko hyyyyy i nic nie zrozumiałem .... więc jeszcze raz, i jeszcze raz .... i jeszcze raz .... i tak jeszcze n razy jak w tej tabeli a jak zaskoczyłem .... hahahaha - no mega super trick - ale popraw mnie jeśli się mylę bo może jednak coś na końcu przeoczyłem rezultatem tego myku jest fakt że, tzn postaram się to podsumować tak na mój rozum: 1. w programie nie zostaną użyte funkcje zmiennoprzecinkowe z math.h 2. w programie zostanie stworzona ładna tablica sinusów w pamięci FLASH 3. a wartości tej tablicy przygotuje grzecznie sługa PREPROCESOR 4. plik values.txt jest tylko taki pomocniczy .... żeby zadać fuchę preprockowi dobrze myślę ? jeśli tak to działa to na prawdę Krauser super mega TRICK obczaiłeś w necie ! gratulacje no i super że się nim podzieliłeś |
Autor: | SunRiver [ 29 cze 2013, o 18:58 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Ano właśnie ... kiedyś to widziałem i gdzieś przepadło w przepastnych czeluściach sieci zaiste . dzięki za przypomnienie , bo robienie na piechotę czasem dobija |
Autor: | jachu [ 29 cze 2013, o 19:58 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
genialne |
Autor: | chodzikman [ 29 cze 2013, o 20:29 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Ja ostatnio spotykając się z tym problemem, mając naprawdę mało czasu napisałem sobie po prostu programik który generował kod. Generuje on sinusy o 6 różnych amplitudach w dwuwymiarowej tablicy i nie ma problemu z wygenerowaniem za pomoca tego kodu innych funkcji z math.c po lekkim przerobieniu, treść jego jest taka: język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Pod linuksem odpalam skompilowany program np. Kod: ./sinus_gen > sinus.h więc nie potrzebuje zapisu do pliku, ale pod windowsem mogłoby się to przydać. Ponieważ miałem problemy z przetwornikiem, dodatkowo zrobiłem opcję generowania przebiegu do matlaba, aby porównać sobie tablicę do tego, co widze na oscyloskopie. Wykorzystanie preprocesora napewno jest bardziej "hackerskie", ale i trudniejsze w zrozumieniu (chociaż mnie strasznie podobają się takie tricki ) |
Autor: | krz [ 29 cze 2013, o 22:22 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
@mirekk36 Te wartości nie znajdą się tam w magiczny sposób, bez wywołania funkcji sin(x) z biblioteki math. Mniej więcej będzie to wyglądać tak: 1. Preprocesor wpierw zamieni __LINE__ w pliku values.txt na odpowiadające im numery linii 2. Następnie w miejsce #include "values.txt" wklei zawartość tego pliku czyli: Kod: const uint8_t sin_tab[TAB_SIZE] PROGMEM ={ VALUE(1), VALUE(2), ..., VALUE(24), }; 2. Wszystkie miejsca gdzie użyte jest makro VALUE(a) przed kompilacją zamieni na: Kod: const uint8_t sin_tab[TAB_SIZE] PROGMEM ={ (sin( ( ( (1-1) * STEP )/180.0 )*M_PI )*128 + 127 ), (sin( ( ( (2-1) * STEP )/180.0 )*M_PI )*128 + 127 ), ..., (sin( ( ( (24-1) * STEP )/180.0 )*M_PI )*128 + 127 ), }; 3. Kompilator wygeneruje kod w asemblerze, który inicjalizuje tę tablicę, czyli do każdej wartości z tablicy przypisze wartość otrzymaną po wywołaniu tego wyrażenia. Tak przy okazji wydaje mi się, że ten wzór na zamianę <-1.0f, 1.0f> na <0, 255> jest zły. Jak sin(x) wyjdzie -1 to otrzymasz (-1.0f)*128 + 127 => -128.0f + 127 => -1.0f i po rzutowaniu na unsigned short int wyjdzie 255. Imo lepiej użyć wzoru: Kod: (sin((a-1)*STEP*PI/180.0f)*127.5f + 127.5f) Wg mnie zamiast kombinować z takimi hackami lepiej jest po prostu wygenerować sobię tę tablicę i ręczne przekleić do kodu. Niestety takie stuczki zmniejszają czytelność i jak nie znamy dokładnego zachowania kompilatora to mogą prowadzić do powstania błędów w programie. |
Autor: | mirekk36 [ 29 cze 2013, o 23:46 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
krz napisał(a): Te wartości nie znajdą się tam w magiczny sposób, bez wywołania funkcji sin(x) z biblioteki math Nie pisałem, że magiczny pisałem że w programie nie zostanie użyta biblioteka math.h - i nie zostanie bo całe wyliczenia zostaną zrobione na etapie preprocesora właśnie i to jest fajne. Dobrze, że rozpisałeś to po swojemu w punktach bo dzięki temu jeszcze łatwiej będzie zrozumieć ideę działania tego tricku wielu ludziom krz napisał(a): Wg mnie zamiast kombinować z takimi hackami lepiej jest po prostu wygenerować sobię tę tablicę i ręczne przekleić do kodu łeeeej no bez przesady - po to są właśnie takie sposoby, jako alternatywa i tak należy to rozumieć. Sposób działa i to się liczy - jak się już go zrozumie - to okazuje się że wcale nie jest skomplikowany a wręcz banalnie prosty - i to jest siła takich rozwiązań w niektórych przypadkach. krz napisał(a): Niestety takie stuczki zmniejszają czytelność i jak nie znamy dokładnego zachowania kompilatora to mogą prowadzić do powstania błędów w programie To by oznaczało, że w zasadzie jak coś wygląda dziwnie - to lepiej tego nie ruszać. To jest dla osób które już zaskoczą o co tu chodzi - a myślę że sporo zaskoczy dzięki temu całemu wątkowi ... i nic nie będzie się działo ze zmniejszeniem czytelności kodu ... tym bardziej, że działa to TYLKO na poziomie preprocesora. Dlatego ja akurat uważam, że warto na pewno czasem to wykorzystywać jak najbardziej. |
Autor: | Krauser [ 30 cze 2013, o 11:15 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
krz napisał(a): Tak przy okazji wydaje mi się, że ten wzór na zamianę <-1.0f, 1.0f> na <0, 255> jest zły. Jak sin(x) wyjdzie -1 to otrzymasz (-1.0f)*128 + 127 => -128.0f + 127 => -1.0f i po rzutowaniu na unsigned short int wyjdzie 255. Imo lepiej użyć wzoru: Kod: (sin((a-1)*STEP*PI/180.0f)*127.5f + 127.5f) Tak wzór jest zły (pozdrawiam panią od matematyki ), ale w wyniku działań na liczbach zmiennoprzecinkowych sin(270) > -1 i po odcięciu części ułamkowej wychodzi 0. To osobny temat poruszony już przy okazji omawiania obliczania UBRR. W związku z tym lepiej użyć jeszcze innego wzoru (tylko dla preprocesora, gdzie wynik jest większy o 0,5): język c Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod. Teraz wartości są jak te z arkusza po zaokrągleniu. Dodanie do wzoru 360 nic nie zmienia, ale wtedy obie wartości dla 0 i 180 stopni są równe i wynoszą 128 (jak w arkuszu kalkulacyjnym). Chociaż z drugiej strony bardziej symetryczne wyniki są, gdy dla 180 mamy wartość 127. Co kto woli. Środek jest na poziomie 127,5, a takiej wartości nie można wybrać. Zwiększenie rozdzielczości do 16 bitów też nic nie zmieni, bo znowu środek jest na poziomie 511,5 . |
Autor: | rafrew [ 15 wrz 2013, o 20:05 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Czy da się się w tym "tricku" podstawić inną funkcję zamiast sinusa z math.h? Konkretnie chodzi mi o funkcję przez siebie zdefiniowaną spoza biblioteki standardowej.? |
Autor: | Krauser [ 15 wrz 2013, o 20:39 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Zauważ, że: język c Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod. to nie jest po prostu: język c Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod. Można używać innych makr (makro to nie funkcja, ale może ją zastąpić) np. |
Autor: | rafrew [ 15 wrz 2013, o 20:53 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Czy chcesz powiedzieć, że preprocesor umie policzyć wartość sinusa z liczby? Raczej nie. Zakomentowanie lini #include<math.h> spowoduje błędy, zatem wartość sinusa obliczana jest na podstawie algorytmu zawartego w bibliotece math.h. Cytuj: Zauważ, że: Składnia: [ Pobierz ] [ Ukryj ] język c #define VALUE(a) (sin( ( ( (a-1) * STEP)/180.0 )*M_PI )*127.5 + 128 )/* wzór na wartość sinusa */ GeSHi to nie jest po prostu: Składnia: [ Pobierz ] [ Ukryj ] język c #define VALUE(a) (sin(a)) w sumie pierwsze sprowadza się do drugiego |
Autor: | mirekk36 [ 15 wrz 2013, o 20:59 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
rafrew napisał(a): Czy chcesz powiedzieć, że preprocesor umie policzyć wartość sinusa z liczby? Kolego naprawdę poczytaj troszkę o preporcesorze gdzieś ... pewnie że preprocesor oblicza sin() i to bez żadnego inkludowania <math.h> bo ta biblioteka jest potrzebna tylko gdy obliczeń trzeba dokonywać w kodzie w procku. Co to za problem dla preprocesora obliczyć sin czy podobną funkcję - na PC? miałby to być kłopot ? a makro VALUE() działa tu TYLKO i wyłącznie w taki sposób że zwraca stałą dosłowną która zostanie wyliczona przez preprocesor właśnie |
Autor: | rafrew [ 15 wrz 2013, o 21:25 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Ok, jeśli tak to już wszystko jasne. Faktycznie muszę coś poszukać bo o funkcjach jakie umie wyliczyć preprocesor jakoś nigdzie się nie natknąłem. Dzięki za odpowiedzi. Pozdrawiam. |
Autor: | karolek [ 11 lut 2014, o 00:18 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Tamta stronka juz wygasła wiec pomyslalem ze moze dobrze bedzie zgrac z google webcache tametego generatora poki jeszcze jest dostepne. |
Autor: | rskup [ 21 maja 2014, o 09:53 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
Witam, Właśnie natknąłem się na inny ciekawy sposób tworzenia tablicy z wartościami wyliczanymi przez preprocesor. Nie trzeba robić dodatkowego pliku do includowania a wykorzystać rekurencję: Kod: #define XTAB0(n) func(n), #define XTAB1(n) XTAB0(n) XTAB0(n+1) XTAB0(n+2) XTAB0(n+3) #define XTAB2(n) XTAB1(n) XTAB1(n+4) XTAB1(n+8) XTAB1(n+12) #define XTAB3(n) XTAB2(n) XTAB2(n+16) XTAB2(n+32) XTAB2(n+48) #define XTAB4(n) XTAB3(n) XTAB3(n+64) XTAB3(n+128) XTAB3(n+192) const uint8_t TABLE[] PROGMEM = { XTAB4(0) }; Dla powyższego kodu dostajemy w TABLE[] wartości będące wynikiem func(n) dla n od 0 do 255. Ale można to bardzo łatwo zmodyfikować na inne wielkości tablic oraz zmienić wartość początkową n na inną (zmiana w wywołaniu XTAB4(start_value)). -- Pozdrawiam, Robert |
Autor: | mirekk36 [ 21 maja 2014, o 10:04 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
no fajne ciekawostki i smaczki |
Autor: | m@ciej [ 26 gru 2014, o 11:08 ] |
Tytuł: | Re: Tablica wartości funkcji utworzona preprocesorem |
A ja dłubałem program w Delphi, co mi zmienia format Excelowego słupka na format Pgm Space. Szlo to dość szybko, ale ta metoda jest niezła. Będę musiał ją przetrenować bo w perspektywie jest wpisanie okolo 30 tablic po 2048 elementów 16-bitowych by zrobić wavetable. Jak będzie zainteresowanie, udostępnię wspomniany programik. |
Strona 1 z 1 | Strefa czasowa: UTC + 1 |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |