\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}

