\documentclass[a4paper,fontsize=14bp]{article} \input{../common-preamble} \input{../bmstu-preamble} \input{../fancy-listings-preamble} \numerationTop \newcolumntype{s}{>{\tiny{}}c} \begin{document} \thispagestyle{empty} \makeBMSTUHeader \makeReportTitle{домашней}{2}{Библиотечная подпрограмма}{Микропроцессорные устройства обработки сигналов}{}{проф. каф. ИУЗ, д.т.н. \\В.С. Выхованец} \newpage \thispagestyle{empty} \tableofcontents \addtocontents{toc}{\vspace{2ex}} \newpage \pagestyle{fancy} \section{Задача} Темой домашнего задания является изучение алгоритмов и исследование способов их реализации, выполняющих Вычисление арктангенсов \code{atan16} \cite[с. 32 (4-11)]{ti:dsp-lib-prog-ref}. Для выполнения домашнего задания необходимо: \begin{enumerate}[label=\arabic*),ref=\arabic*] \item ознакомиться с рекомендованной литературой \cite[с. 102-165]{dsp:lectures}; \item привести в отчете теоретические сведения по методам обработки сигналов; \item описать алгоритм обработки сигналов и данных; \item прокомментировать текст библиотечной функции; \item оформить\cite{gost:texts} отчет\cite{gost:links} по домашнему заданию\cite{bmstu:dsp-methodics2}. \end{enumerate} Основным результатом домашнего задания является комментированный текст библиотечной функции на языке ассемблера, а также описание выполняемого ею алгоритма цифровой обработки сигналов и данных. \section{Выполнение} \subsection{Теоретические сведения} Арктангенс (arctg или arctan) – это обратная тригонометрическая функция. Арктангенс x определяется как функция, обратная к тангенсу x, где x – любое число ($x\in\mathbb{R}$). Если тангенс угла у равен х ($\tan(y) = x$), значит арктангенс x равняется y: \[ \arctan(x) = \tan^{-1} x = y, \text{причем} -\pi / 2 < y < \pi / 2.\] При этом $\tan^{-1}x$ означает обратный тангенс, а не тангенс в степени -1. Функция арктангенс непрерывна на своей области определения, то есть для всех x. Функция арктангенс является нечетной: \[ \arctan(–x) = \arctan(–\tan \arctan x) = \arctan(\tan(–\arctan x)) = –\arctan x.\] График арктангенса получается из графика тангенса, если поменять местами оси абсцисс и ординат. Чтобы устранить многозначность, множество значений ограничивают интервалом, на котором функция монотонна. Такое определение называют главным значением арктангенса. \subsection{Интерфейс библиотечной функции} Согласно документации \cite[c. 32 (4-11)]{ti:dsp-lib-prog-ref} функция вычисления арктангенса вектора значений имеет прототип, представленный в листинге \hrf{lst:atan-proto}: \begin{lstlisting}[language=C,style=CCodeStyle,caption={Прототип функции вычисления арктангенса},label={lst:atan-proto}] \code{ushort oflag = atan16 (DATA *x, DATA *r, ushort nx)} \end{lstlisting} где \code{ushort} – тип данных, определенный как \code{unsigned short}; \code{DATA} – тип данных, являющийся синонимом \code{int}; \code{x} – указатель на вектор исходных данных; \code{r} – указатель на вектор выходных данных арктангенса \code{x} в диапазоне $[-\pi/4, \pi/4]$, при этом, \code{atan(1.0) = 0.7854 или 6478h}; \code{nx} – число элементов в векторах \code{x} и \code{r}. Векторы входных и выходных данных функции представляют собой одномерные массивы, элементами которых являются 16-разрядные числа (целые или дробные), пронумерованные в порядке увеличения их адресов в памяти данных (таблица \hrf{table:vectors}). \begin{table}[H] \captionsetup{labelsep=endash} \centering \caption{Общий вид вектора функции atan16} \label{table:vectors} \begin{tabular}{|c|c|c|c|c|c|c|} \hline Адрес & x(+0) & x+1 & x+2 & x... & x+(nx-2) & x+(nx-1) \\ [0.5ex] \hline Индекс & x[0] & x[1] & x[2] & x... & x[nx-2] & x[nx-1] \\ [1ex] \hline \end{tabular} \end{table} Длина векторов \code{nx} задается в формате N16 – беззнаковом 16-разрядном целочисленном формате. Сами массивы, а также их элементы выравнены по границе слова. Разрешается использование одного и того же указателя для задания двух векторов\footnote{In-place processing allowed (r can be equal to x)}. Функция управляет флагом переполнения \code{oflag}, который выставляется в 1 или 0 если произошло или не произошло 32-разрядное переполнение, соответственно. \subsection{Описание алгоритма} Функция \code{atan16} подсчитывает значение арктангенса каждого элемента вектора \code{x}, Результат записывается в выходной вектор \code{r} в диапазоне $[-\pi/4, \pi/4]$ радиан. Например, если x = [0x7fff, 0x3505, 0x1976, 0x0], что эквивалентно $\tan(\frac{\pi}{4})$, $\tan(\frac{\pi}{8})$, $\tan(\frac{\pi}{16})$, $\tan(0)$ в формате float, то вызов функции \code{atan16(x, r, 4);} должен выдать r = [0x6478, 0x3243, 0x1921, 0x0], что эквивалентно $\frac{\pi}{4}$, $\frac{\pi}{8}$, $\frac{\pi}{16}$, $0$. Реализуемый функцией \code{atan16} алгоритм описан на языке программирования Cи и приведен на листинге \hrf{lst:atan-alg}. \begin{lstlisting}[language=C, style=CCodeStyle, caption = {Алгоритм вычисления арктангенса}, label={lst:atan-alg}] #define DATA int #define ushort unsigned short void atan(DATA* x, DATA* r, ushort nx) { ushort i; for (i = 0; i < nx; i++) { r[i] = atan(x[i]); } } \end{lstlisting} В теле основного цикла функции выполняется извлечение очередных элементов вектороа \code{x} и передача их в функцию \code{atan()}, с последующим присваиванием результата в соответствующий индекс выходного вектора \code{r}. Для организации цикла используется целочисленная переменная \code{i}, которая задает индекс элементов векторов. Комментированный текст библиотечной функции \code{atan()} на основе сведений о мнемониках \cite{ti:dsp-mnemonics} приведен в приложении \hrf{appendix:asm}. \section{Выводы} В домашнем задании 2 приведено описание библиотечной функции вычисления арктангенса вектора. Для функции вычисления значений арктангенса разработан алгоритм на языке Си и приведен комментированный текст его реализации библиотечной функцией на языке ассемблера для микропроцессора цифровой обработки сигналов TMS320C5515. \newpage \printbibliography[heading=bibintoc, title={Список литературы}, resetnumbers=1] \newpage \begin{appendices} \renewcommand{\thesubsection}{\Asbuk{subsection}} \subsection{Библиотечная функция atan()} \label{appendix:asm} \begin{lstlisting}[style=ASMStyle] ;<@\lh{dkgreen}{************************************************************}@> ;<@\lh{dkgreen}{* Version 3.00.00 }@> ;<@\lh{dkgreen}{************************************************************}@> ;<@\lh{dkgreen}{* Функция: atan16}@> ;<@\lh{dkgreen}{* Процессор: C55xx}@> ;<@\lh{dkgreen}{* Описание: реализация арктангенса}@> ;<@\lh{dkgreen}{* Использование: short atan16( DATA *x, DATA *r, int nx)} @> ;<@\lh{dkgreen}{* nx : число элементов x и r}@> ;<@\lh{dkgreen}{* r[i] = atan(x[i]) где x и r в формате Q15}@> ;<@\lh{dkgreen}{* return 0}@> ;<@\lh{dkgreen}{*}@> ;<@\lh{dkgreen}{* Производительность (бенчмарки):}@> ;<@\lh{dkgreen}{* Циклов: (5 * nx) + 14 (Асимптотическая сложность О(n))}@> ;<@\lh{dkgreen}{* Объём кода (в байтах): 49}@> ;<@\lh{dkgreen}{*}@> ;<@\lh{dkgreen}{************************************************************}@> .mmregs ;<@\lh{dkgreen}{Разрешение MMR-регистров}@> .cpl_on ;<@\lh{dkgreen}{Режим компилятора}@> .arms_on ;<@\lh{dkgreen}{Сигнальный режим адресации}@> ;<@\lh{dkgreen}{-----------------------------------------------------------}@> ;<@\lh{dkgreen}{| Тело функции}@> ;<@\lh{dkgreen}{-----------------------------------------------------------}@> .def _atan16 .text _atan16: ; <@\lh{dkgreen}{* AR0 присваивается \_x}@> ; <@\lh{dkgreen}{* AR1 присваивается \_r}@> ; <@\lh{dkgreen}{* T0 присваивается \_nx}@> PSH T3 ; <@\lh{dkgreen}{использовать временный регистр}@> || BSET FRCT ; <@\lh{dkgreen}{режим рациональных чисел}@> SUB #1, T0 ; nx - 1 MOV T0, BRC0 ; <@\lh{dkgreen}{повторить nx раз}@> MOV #2596 << #16, AC3 ; <@\lh{dkgreen}{старшие разряды AC3 = C5}@> MOV #-9464 << #16, AC1 ; <@\lh{dkgreen}{старшие разряды AC1 = C3}@> MOV #32617 << #16, AC2 ; <@\lh{dkgreen}{старшие разряды AC2 = C1}@> ; <@\lh{dkgreen}{Загрузка T3 на инструкцию раньше, чем умножение его}@> ; <@\lh{dkgreen}{использует, приведёт к задержке в один такт}@> MPYMR T3=*AR0+, AC3, AC0 ; <@\lh{dkgreen}{непосредственное умножение значения из х}@> || RPTBLOCAL loop1 - 1 ; <@\lh{dkgreen}{и запустить цикл}@> MACR AC0,T3,AC1,AC0; <@\lh{dkgreen}{вычислить смещение для следующего значения}@> MPYR T3, AC0 ; <@\lh{dkgreen}{сохранить временный результат умножения}@> || MOV *AR0+, T1 ; <@\lh{dkgreen}{сместить указатель на следующее значение х}@> MACR AC0,T3,AC2,AC0; <@\lh{dkgreen}{вычислить смещение для следующего значения}@> MPYR T3, AC0 ; <@\lh{dkgreen}{сохранить временный результат умножения}@> || MOV T1, T3 ; <@\lh{dkgreen}{сохранить значение итератора}@> MOV HI(AC0), *AR1+ ; <@\lh{dkgreen}{сохранить старшую часть результата вычислений}@> || MPYR T1, AC3, AC0 ; <@\lh{dkgreen}{следующая итерация}@> loop1: ; <@\lh{dkgreen}{цикл}@> POP T3 ; || BCLR FRCT ; <@\lh{dkgreen}{вернуться в режим обычного C}@> MOV #0, T0 ; <@\lh{dkgreen}{вернуть значение ОК}@> || RET ; <@\lh{dkgreen}{(нет возможных ошибок)}@> \end{lstlisting} \end{appendices} \end{document}