Wprowadzenie do programowania na procesorze sygnałowym

Podobne dokumenty
Filtry FIR i biblioteka DSPLIB

Zastosowania Procesorów Sygnałowych. dr inż. Grzegorz Szwoch p Katedra Systemów Multimedialnych.

Generowanie sygnałów na DSP

Przykładowe pytania DSP 1

LABORATORIUM PROCESORY SYGNAŁOWE W AUTOMATYCE PRZEMYSŁOWEJ. Zasady arytmetyki stałoprzecinkowej oraz operacji arytmetycznych w formatach Q

Instrukcja do ćwiczeń nr 4 typy i rodzaje zmiennych w języku C dla AVR, oraz ich deklarowanie, oraz podstawowe operatory

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Adam Korzeniewski p Katedra Systemów Multimedialnych

Adam Korzeniewski p Katedra Systemów Multimedialnych

Dr inż. Grażyna KRUPIŃSKA. D-10 pokój 227 WYKŁAD 7 WSTĘP DO INFORMATYKI

Poradnik programowania procesorów AVR na przykładzie ATMEGA8

Jak napisać program obliczający pola powierzchni różnych figur płaskich?

PROCESORY SYGNAŁOWE - LABORATORIUM. Ćwiczenie nr 04

Programowanie. programowania. Klasa 3 Lekcja 9 PASCAL & C++

Wprowadzenie do architektury komputerów systemy liczbowe, operacje arytmetyczne i logiczne

Kompilator języka C na procesor 8051 RC51 implementacja

Podstawy programowania. Wykład Funkcje. Krzysztof Banaś Podstawy programowania 1

Wskaźniki a tablice Wskaźniki i tablice są ze sobą w języku C++ ściśle związane. Aby się o tym przekonać wykonajmy cwiczenie.

2. Arytmetyka procesorów 16-bitowych stałoprzecinkowych

1 Podstawy c++ w pigułce.

ARCHITEKTURA SYSTEMÓW KOMPUTEROWYCH

Wielkości liczbowe. Wykład z Podstaw Informatyki dla I roku BO. Piotr Mika

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

Podstawy programowania w języku C

Wielkości liczbowe. Wykład z Podstaw Informatyki. Piotr Mika

Adam Korzeniewski - p. 732 dr inż. Grzegorz Szwoch - p. 732 dr inż.

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 4 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 44

Typ użyty w deklaracji zmiennej decyduje o rodzaju informacji, a nazwa zmiennej symbolicznie opisuje wartość.

Zestaw 3. - Zapis liczb binarnych ze znakiem 1

Technologie Informacyjne

PROCESORY SYGNAŁOWE - LABORATORIUM. Ćwiczenie nr 03

ZASADY PROGRAMOWANIA KOMPUTERÓW

Wykład 4. Przegląd mikrokontrolerów 16-bit: - PIC24 - dspic - MSP430

Przekształcenie Fouriera i splot

Filtry cyfrowe i procesory sygnałowe

znajdowały się różne instrukcje) to tak naprawdę definicja funkcji main.

Techniki multimedialne

Podstawy Programowania. Wykład 1

Wiadomości wstępne Środowisko programistyczne Najważniejsze różnice C/C++ vs Java

SPRZĘTOWA REALIZACJA FILTRÓW CYFROWYCH TYPU SOI

Spis treœci. Co to jest mikrokontroler? Kody i liczby stosowane w systemach komputerowych. Podstawowe elementy logiczne

Zmienne, stałe i operatory

Lab 9 Podstawy Programowania

Programowanie w C++ Wykład 2. Katarzyna Grzelak. 5 marca K.Grzelak (Wykład 1) Programowanie w C++ 1 / 41

Podstawy programowania w języku C i C++

Typy złożone. Struktury, pola bitowe i unie. Programowanie Proceduralne 1

Programowanie w języku C++ Grażyna Koba

Szkolenia specjalistyczne

1 Wskaźniki i zmienne dynamiczne, instrukcja przed zajęciami

Podstawy programowania. Wykład: 5. Instrukcje sterujące c.d. Stałe, Typy zmiennych c.d. dr Artur Bartoszewski -Podstawy programowania, sem 1 - WYKŁAD

Programowanie strukturalne i obiektowe

Temat 1: Podstawowe pojęcia: program, kompilacja, kod

Programowanie mikrokontrolerów AVR

Język ludzki kod maszynowy

ZASTOSOWANIA PROCESORÓW SYGNAŁOWYCH

Wprowadzenie. Organizacja pracy i środowisko programistyczne. Mirosław Ochodek

2 Przygotował: mgr inż. Maciej Lasota

Temat: Dynamiczne przydzielanie i zwalnianie pamięci. Struktura listy operacje wstawiania, wyszukiwania oraz usuwania danych.

Języki C i C++ Wykład: 2. Wstęp Instrukcje sterujące. dr Artur Bartoszewski - Języki C i C++, sem. 1I- WYKŁAD

Pytania sprawdzające wiedzę z programowania C++

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Podstawy programowania. Wykład Co jeszcze... Przypomnienia, uzupełnienia. Krzysztof Banaś Podstawy programowania 1

Język C zajęcia nr 11. Funkcje

Metody numeryczne Technika obliczeniowa i symulacyjna Sem. 2, EiT, 2014/2015

Mikrokontroler ATmega32. Język symboliczny

1 Podstawy c++ w pigułce.

Laboratorium 1: Wprowadzenie do środowiska programowego. oraz podstawowe operacje na rejestrach i komórkach pamięci

Temat 7. Programowanie mikrokontrolerów z rodziny PIC16 w języku C przy użyciu HI-TECH C for PIC10/12/16

start Program mikroprocesorowego miernika mocy generowanej $crystal = deklaracja

Operacje arytmetyczne

Laboratorium 5: Tablice. Wyszukiwanie binarne

1 P roste e t ypy p d a d n a ych c - c ąg ą g d a d l a szy 2 T y T py p z ł z o ł żo ż ne e d a d n a ych c : T BLICE

Teoretyczne Podstawy Informatyki

Wstęp do programowania INP003203L rok akademicki 2018/19 semestr zimowy. Laboratorium 2. Karol Tarnowski A-1 p.

Metody optymalizacji soft-procesorów NIOS

ZASTOSOWANIA PROCESORÓW SYGNAŁOWYCH - PROJEKT

Podstawy Programowania C++

Kodowanie informacji. Kody liczbowe

Arytmetyka komputera. Na podstawie podręcznika Urządzenia techniki komputerowej Tomasza Marciniuka. Opracował: Kamil Kowalski klasa III TI

> C++ wskaźniki. Dane: Iwona Polak. Uniwersytet Śląski Instytut Informatyki 26 kwietnia 2017

Dla człowieka naturalnym sposobem liczenia jest korzystanie z systemu dziesiętnego, dla komputera natomiast korzystanie z zapisu dwójkowego

ARCHITEKTURA KOMPUTERÓW Liczby zmiennoprzecinkowe

Sterowniki Programowalne (SP) Wykład 13

Języki programowania obiektowego Nieobiektowe elementy języka C++

Programowanie - wykład 4

Zaawansowane algorytmy DSP

I. KARTA PRZEDMIOTU CEL PRZEDMIOTU WYMAGANIA WSTĘPNE W ZAKRESIE WIEDZY, UMIEJĘTNOŚCI I INNYCH KOMPETENCJI EFEKTY KSZTAŁCENIA

Wydział Elektryczny Katedra Telekomunikacji i Aparatury Elektronicznej

PROE wykład 2 operacje na wskaźnikach. dr inż. Jacek Naruniec

Wstęp do informatyki- wykład 1 Systemy liczbowe

Konwersje napis <-> liczba Struktury, unie Scanf / printf Wskaźniki

Rejestry procesora. Nazwa ilość bitów. AX 16 (accumulator) rejestr akumulatora. BX 16 (base) rejestr bazowy. CX 16 (count) rejestr licznika

Programowanie mikrokontrolerów. 8 listopada 2007

Wydział Elektryczny. Katedra Telekomunikacji i Aparatury Elektronicznej. Konstrukcje i Technologie w Aparaturze Elektronicznej.

Podstawy Programowania Podstawowa składnia języka C++

Magistrala systemowa (System Bus)

Arytmetyka liczb binarnych

Wprowadzenie do języka Java

LABORATORIUM 3 ALGORYTMY OBLICZENIOWE W ELEKTRONICE I TELEKOMUNIKACJI. Wprowadzenie do środowiska Matlab

Zadanie 1. Potęgi (14 pkt)

Transkrypt:

Zastosowania Procesorów Sygnałowych dr inż. Grzegorz Szwoch greg@multimed.org p. 732 - Katedra Systemów Multimedialnych Wprowadzenie do programowania na procesorze sygnałowym

Wstęp Czego nauczymy się na tym i na kolejnych wykładach? Jak implementować algorytmy DSP na stałoprzecinkowym procesorze sygnałowym. Jak działają podstawowe algorytmy DSP - filtry, FFT, generatory sygnałów, itp. Jakie są ich praktyczne zastosowania. W przyszłym semestrze (6) będziemy wykonywać projekt. Bez wiedzy przedstawionej na tych wykładach będzie bardzo trudno!!!

Układ DSP TMS320C5535 Bohater opowieści: Układ uruchomieniowy ezdsp Texas Instruments Stałoprzecinkowy procesor DSP TMS320C5535 zegar 50-100 MHz 320 KB RAM Pamięć flash 8 MB kodek audio

Uruchamianie algorytmów Tworzenie kodu tryb Debug: podłączamy płytkę przez USB do komputera, używamy programu Code Composer Studio do pisania kodu, uruchamiania, debugowania Gotowy program tryb Release: wgrywamy do pamięci flash lub na kartę SD, program uruchamia się po włączeniu zasilania

Asembler Jak piszemy kod? Pierwsza możliwość Asembler. Język tworzący praktycznie kod maszynowy. Pozwala wykorzystać wszystkie możliwości DSP. Umożliwia pisanie optymalnego (najszybszego) kodu. Tradycyjny sposób implementowania na DSP. Wada: wymaga dużej wiedzy, jest dość trudny. Na szczęście, typowe algorytmy DSP w Asemblerze są już dostępne biblioteka DSPLIB. Nie będziemy pisali w Asemblerze na tym przedmiocie.

Język C Drugi sposób dostępny na naszym DSP język C Znacznie łatwiejsze programowanie. Kompilator tłumaczy kod C na asembler. Robi to dobrze, ale nie jest w stanie być tak dokładny, jak programista Asemblera. Kod napisany w C będzie zwykle wolniejszy. Możliwe jest łączenie C z Asemblerem. Będziemy używali języka C do tworzenia kodu.

Czas działania algorytmu Częstotliwość zegara DSP wyznacza liczbę cykli na sekundę. Np. 100 MHz to 100 mln cykli/s. Każda instrukcja kodu zużywa określoną liczbę cykli zegarowych. Czas działania algorytmu mierzymy liczbą cykli. Np. jeżeli alg. zużywa 600 cykli, to czas = 0,6 ms. Optymalizacja algorytmu pozwala nam wykonać więcej operacji w ciągu sekundy bardzo ważne w zastosowaniach praktycznych.

Czas działania algorytmu Praktyczny wniosek: Programowanie na typowe komputery uczy nas nie dbać o czas wykonywania kodu ( nie optymalizować dopóki nie jest to niezbędne ). Takie podejście nie sprawdzi się na DSP. Jeżeli nie będziemy od początku dbali o czas wykonywania kodu, to może nam zabraknąć cykli zegarowych.

Kod w języku C Struktura kodu w języku C: dołączenie nagłówków (#include), deklaracje zmiennych, w tym buforów, (opcjonalnie) definicje funkcji, funkcja main tutaj rozpoczyna się wykonanie programu. Program może być zapisany w więcej niż jednym pliku.

Inicjalizacja układu Na początku main trzeba skonfigurować naszą płytkę: ustawienie częstotliwości zegara, włączenie kodeka dźwięku, ust. cz. próbkowania, uruchomienie wyświetlacza, przycisków, itp. i inne rzeczy. Te operacje wykonujemy w każdym programie, dlatego są one zwykle umieszczone w osobnej bibliotece. Trzeba jedynie je wywołać.

Schemat przetwarzania Przykład: chcemy przetworzyć dźwięk z wejścia i wysłać go na wyjście. Wewnątrz main implementujemy pętlę wykonującą następujące operacje: odczyt próbki z wejścia, przetwarzanie: próbka po próbce każdą próbkę z osobna, lub blokowe zapisujemy próbkę do bufora, przetwarzamy bufor gdy się zapełni, zapisanie przetworzonej próbki na wyjście.

Obliczanie średniej ruchomej Zabieramy się wreszcie do pisania kodu. Obliczamy wartość średnią ostatnich 5 próbek: y( n) = x( n) + x( n 1) + x( n 2) 5 + x( n 3) + x( n 4) lub inaczej: y( n) = 0,2x( n) + 0,2x( n 1) + 0,2x( n 2) + 0,2x( n 3) + 0,2x( n 4) Musimy przechować 5 ostatnich próbek w pamięci.

Bufor liniowy Najprostsze podejście bufor liniowy. Wyrzucamy z bufora najstarszą próbkę, przesuwamy pozostałe próbki o jedno miejsce, wpisujemy nową próbkę na wolne miejsce. Wada: tracimy czas na przesuwanie próbek. Jeśli w buforze będzie np. 100 próbek, zmarnujemy dużo cykli.

Bufor kołowy Lepsze rozwiązanie: bufor kołowy. Próbki nie są przesuwane. Przesuwany jest indeks wskazujący na najstarszą próbkę w to miejsce zapisujemy nową próbkę. Indeks musi się zawijać po dojściu na koniec bufora, wraca na pozycję 0.

Bufor kołowy i liniowy -ilustracja Bufor kołowy Bufor liniowy 13 14 10 11 12 10 11 12 13 14 15 13 14 15 11 12 15 11 12 13 14 15 16 13 14 15 16 12 16 12 13 14 15 16 17 13 14 15 16 17 17 13 14 15 16 17 18 18 14 15 16 17 18 14 15 16 17 18 19 18 19 15 16 17 19 15 16 17 18 19

Bufor kołowy w języku C Implementacja w naszym programie: #define N 5 int bufor[n]; int indeks = 0; // rozmiar bufora // deklaracja bufora // wskazuje najstarszą próbkę bufor[indeks] = nowa_probka; // zapis // tutaj wykonujemy obliczenia indeks += 1; if (indeks == N) indeks -= N; // przesunięcie indeksu // jesteśmy na końcu // zawijamy indeks

Bufor kołowy na DSP Bufory kołowe są zwykle używane na DSP. Procesor ma specjalne instrukcje do ich obsługi. W kodzie C mamy dostęp do wewnętrznych instrukcji procesora (intrinsics) za pomocą specjalnych komend. Np. zwiększenie indeksu w buforze kołowym to instrukcja _circ_incr. Instrukcje wewnętrzne skracają pisany kod.

Bufor kołowy na DSP Zamiast: indeks += 1; if (indeks == N) indeks -= N; możemy napisać: indeks = _circ_incr(indeks, 1, N);

Deklarowanie buforów Zanim pójdziemy dalej: gdzie deklarować bufory? DSP ma pamięć o ciągłym zakresie adresów. Pamięć jest logicznie dzielona na zakresy: danych, programu, stosu, itp. (definicje w pliku.cmd). Nie ma zabezpieczenia przed przekroczeniem danego zakresu! Zmienne (w tym bufory) możemy definiować: przed main w obszarze danych, wewnątrz main na stosie.

Stos Stos jest obszarem pamięci dla zmiennych deklarowanych wewnątrz funkcji (w tym main). Obszar stosu jest niewielki, np. 4 KB. Deklarując duże bufory wewnątrz main, możemy spowodować przepełnienie stosu. Objawy mogą być rożne, np.: zawieszenie się programu, program działa, ale generuje błędne dane.

Przepełnienie stosu Ilustracja problemu: Zajęty obszar stosu Deklarujemy duży bufor na stosie Wolny obszar stosu Zajęty obszar danych Przepełnienie stosu! Wolny obszar danych

Przepełnienie stosu Efekty przepełnienia stosu są trudne do debugowania. Obszar danych jest większy od stosu i wystarczający. Dlatego proszę zapamiętać i stosować poniższą zasadę. Wszelkie bufory danych deklarujemy globalnie, tzn. poza main i innymi funkcjami!

Typy danych Nasz DSP daje nam do dyspozycji następujące typy danych liczb całkowitych: int liczba 16-bitowa (także: short, DATA, Int16), long liczba 32-bitowa (także LDATA, Int32). Każdy typ jest w wersji: signed ze znakiem (domyślnie), unsigned bez znaku (np. unsignedint). NIE MA typów zmiennoprzecinkowych float, double!

Deklarowanie zmiennych w C Zmienna skalarna : typ, nazwa int probka; unsigned int indeks; Tablice (np. bufory): typ, nazwa[rozmiar] int bufor[1024]; Tablice stałych, np. współczynników: const int wsp[] = {1000, 2000, 3000}; Stałe liczbowe, np. rozmiar tablicy: const int N = 5; #define N 5

Mnożenie na DSP Wracamy do naszego kodu. Mamy policzyć średnią ruchomą. Musimy przemnożyć próbki przez 0,2. Pamiętajmy: tylko typy całkowitoliczbowe. Stosujemy zapis Q15 (wykład nr 5): 0,2 * 32768 6535 Próbki sygnału są zapisane jako int (16 bit). Mnożenie dwóch liczb 16-bitowych daje wynik 32-bitowy (typ long).

Mnożenie na DSP W języku C, mnożenie dwóch liczb 16-bitowych daje zawsze wynik 16-bitowy, starsze bity zostają usunięte! Musimy rzutować mnożoną liczbę na typ long. Prawidłowo: long wynik = (long)probka * 6535; // OK Nieprawidłowo: int wynik = probka * 6535; // obcięcie wyniku long wynik = probka * 6535; // również obcięcie wyniku!

Obliczenie średniej Mnożymy przez 0,2 próbki zapisane w buforze kołowym, zaczynając od pozycji indeks, i sumujemy. const int WSP = 6535; // współczynnik 0,2 int i = 0; // licznik pętli int poz = indeks; // pozycja odczytu próbki long wynik = 0; // nasza średnia for (i = 0; i < n; i++) { // pętla po próbkach wynik += (long)bufor[poz] * WSP; poz = _circ_incr(poz, -1, N); }

MAC Jedna z typowych operacji na DSP: przemnożenie dwóch liczb i dodanie wyniku do akumulatora: y y + a * x Taka operacja nazywa się MAC multiplyand accumulate. DSP ma specjalne instrukcje do szybkiego MAC Nasz DSP potrafi wykonywać dwie operacje MAC w tym samym cyklu (Dual MAC). Wymaga to zwykle użycia Asemblera.

Przepełnienie zakresu Arytmetyka stałoprzecinkowa jest wrażliwa na przepełnienie zakresu liczby. Np. x = 32760. Obliczamy (x + 10). Liczba 32770 nie mieści się na 15 bitach (>32767). Następuje przepełnienie (overflow) jedynka przeskakuje na bit znaku. Wynik 8002h jest interpretowany jako -32766! Dostajemy całkowicie błędny wynik!

Przepełnienie zakresu Jak bronić się przed przepełnieniem? Najlepiej zapewnić, aby żadna cząstkowa suma nie przekraczała zakresu. Np. w naszym algorytmie mamy współczynniki 5 0,2 = 1. Jeżeli nie możemy tego zapewnić, możemy użyć 40-bitowego rejestru (typ longlong), ale spowalnia to obliczenia. Możemy też użyć arytmetyki nasycenia.

Arytmetyka nasycenia Saturationarithmetic obcina wartości przekraczające zakres do wartości maksymalnej. Np. dla liczb Q15 wynik jest równy: 32767, gdy wynik > 32767, -32768, gdy wynik < -32768. Wyniki nadal są błędne, ale przynajmniej nie ma przeskoku na wartości z przeciwnym znakiem. Procesor DSP ma możliwość włączenia trybu nasycenia. Kosztuje to jeden cykl na operację.

Arytmetyka nasycenia Wybrane instrukcje wewnętrzne dla trybu nasycenia: _sadd / _lsadd dodawanie (wynik: int / long) _ssub / _lssub - odejmowanie _smpy / _lsmpy mnożenie _smac / _llsmac MAC (wynik: long / long long) UWAGA: instrukcje te włączają tzw. tryb ułamkowy (fractionalmode). Wynik typu long jest zapisywany w formacie Q31 (wynik Q30 jest mnożony razy 2)! Ułatwia to późniejszą konwersję do typu int.

Obliczenie średniej (c.d.) Stara wersja naszego algorytmu: for (i = 0; i < n; i++) { // pętla po próbkach wynik += (long)bufor[poz] * WSP; poz = _circ_incr(poz, -1, N); } Wersja z wykorzystaniem MAC i nasycenia: for (i = 0; i < n; i++) { // pętla po próbkach wynik = _smac(wynik, bufor[poz], WSP); poz = _circ_incr(poz, -1, N); }

Konwersja wyniku do typu int Po wykonaniu obliczeń, wynik (typu long) musi być skonwertowany do typu int. Są dwie metody. Obcięcie usunięcie najmłodszych 15 bitów (Q30) lub 16 bitów (Q31) poprzez przesunięcie bitowe. Należy pamiętać o rzutowaniu typu. // wynik: zmienna typu long (Q30) int wyjscie = (int)(wynik >> 15);

Konwersja wyniku do typu int Drugi sposób zaokrąglenie. Bardziej kosztowne, ale zmniejsza błędy zaokrągleń o połowę. Przed przesunięciem o n bitów, dodajemy 2 n-1. // wynik: zmienna typu long (Q30) int wyjscie = (int)((wynik + 16384) >> 15); Dla liczb Q31 w trybie ułamkowym mamy instrukcję: int wyjscie = (int)(_sround(wynik) >> 16);

Obliczanie średniej (finał) Mamy już cały kod obliczający średnią z ostatnich pięciu próbek sygnału: y( n) = 0,2x( n) + 0,2x( n 1) + 0,2x( n 2) + 0,2x( n 3) + 0,2x( n Algorytm wygładza sygnał: 4)

Obliczanie średniej Jak wygląda charakterystyka częstotliwościowa naszego algorytmu?

Obliczanie średniej Możemy łatwo zmodyfikować nasz algorytm tak, aby liczył średnią z N próbek, ze współczynnikiem 1 / N

Obliczanie średniej To, co napisaliśmy, jest przykładem filtru cyfrowego typu FIR: o skończonej odpowiedzi impulsowej. Jedyna różnica to taka, że w filtrze FIR, współczynniki zwykle nie są stałe (u nas: stałe 0,2). Ale implementacja jest taka sama. Czyli wiemy już jak zaimplementować filtr FIR na DSP! Więcej o praktycznych implementacjach FIR - na kolejnym wykładzie.

Ważne rzeczy do zapamiętania Struktura kodu DSP w języku C Bufory deklarujemy poza main Typy int i long, rzutowanie i konwersje Arytmetyka Q mnożenie, dodawanie, MAC Problem przepełnienia zakresu, nasycenie Instrukcje wewnętrzne DSP