\documentclass{article}

\input{settings/common-preamble}
\input{settings/bmstu-preamble}
\input{settings/fancy-listings-preamble}

\def\makeyear{2021}
\def\grpNum{11М}

\begin{document}
\thispagestyle{empty}
\makeBMSTUHeader

\makeReportTitle{лабораторной}{1}{Создание простой системы в Platform Designer \\ в пакете Quartus Prime}{Программное обеспечение встроенных систем}{}{доцент кафедры ИУ-3 \\ Федоров С.В.}
\newpage
\blankpage
\pagestyle{fancy}
\tableofcontents
\newpage
\section*{Цель работы}
\addcontentsline{toc}{section}{Цель работы}
Изучить средства создания систем на кристалле на основе процессора Nios II фирмы Intel в средстве Platfrom Designer. Освоить методику создания и конфигурации систем на кристалле. Реализовать и отладить программное обеспечение системы на кристалле. Освоить методику отладки проекта с применением программных и аппаратных средств. Получить навыки работы с документацией производителя.

\section*{Задания}
\begin{enumerate}
\item Модифицируйте исходную программу следующим образом: нажатие кнопки KEY3 должно зажигать все светодиоды, KEY0 -- гасить все светодиоды, нажатие центральных кнопок KEY2 и KEY1 должно гасить светодиоды по очереди слева и справа по одному на каждое нажатие.
\item Реализуйте обработку нажатия кнопок и формирование значений на светодиодах по прерыванию. Используйте справочные материалы в каталоге лабораторной работы.
\end{enumerate}

\section*{Листинги программ}
\textbf{Программа по заданию 1} (изменения выделены красным цветом, комментарии приведены и выделены зеленым). для сдвига влево или вправо используется оператор \code{>>}, а для наложения полученного значения на текущие обжуленные биты побитовая маска \& с последующим присваиванием обратно в переменную \code{led}:

\begin{lstlisting}[language=C,style=CCodeStyle]
  #include <stdio.h>
  #include <unistd.h>
  #include "altera_avalon_pio_regs.h"
  #include "system.h"
  <@\texttt{\textcolor{codecomments}{// Value read from button PIO when no buttons pressed}}@>
  #define NONE_PRESSED 0xF
  <@\texttt{\textcolor{codecomments}{// Time in microseconds to wait for switch debounce}}@>
  #define DEBOUNCE 30000
  int main(void) {
    #define KEY_3 0x7
    #define KEY_2 0xB
    #define KEY_1 0xD
    #define KEY_0 0xE
    int buttons;
    int led = 0x01;
    IOWR_ALTERA_AVALON_PIO_DATA(GREEN_LED_BASE,led);
    while (1) {
      buttons = IORD_ALTERA_AVALON_PIO_DATA(BUTTONS_BASE);
      if (buttons != NONE_PRESSED) {
        <@\texttt{\textcolor{red}{switch(buttons) \{}}@>
          <@\texttt{\textcolor{red}{case KEY\_3:}}@>
            <@\texttt{\textcolor{red}{led = 0xFF;}\textcolor{codecomments}{ // all bits 1}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_2:}}@>
            <@\texttt{\textcolor{red}{led \&= led >> 1;}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_1:}}@>
            <@\texttt{\textcolor{red}{led \&= led << 1;}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_0:}}@>
            <@\texttt{\textcolor{red}{led = 0x00;}\textcolor{codecomments}{ // all bits 0}}@>
          <@\texttt{\textcolor{red}{break;}}@>
        <@\texttt{\textcolor{red}{\}}}@>
        IOWR_ALTERA_AVALON_PIO_DATA(GREEN_LED_BASE,led);
        usleep (DEBOUNCE);
        while (buttons != NONE_PRESSED)
        buttons = IORD_ALTERA_AVALON_PIO_DATA(BUTTONS_BASE);
        usleep (DEBOUNCE);
      }
    }
  } // end
\end{lstlisting}

\textbf{Программа по заданию 2.} Структура программы: обработчик прерывания от кнопок (в нем считываются задетектированные нажатия кнопок), подпрограмма регистрации обработчика прерывания и главная программа, которая вызывает подпрограмму регистрации и управляет состоянием светодиодов. Во всех функциях использовались макроконстанты, объявленные в заголовочных файлах \code{system.h} и \code{altera_avalon_pio_regs.h}, хранящих адреса соответствующих инструкций и данных. Также был добавлен заголовочный файл \code{sys/alt_irq.h}. Адреса изменились, потому что теперь это не значения на кнопках (1 для свободной, 0 для нажатой), а значения в регистре прерываний (1 для места, где сработало прерывание).

\begin{lstlisting}[language=C,style=CCodeStyle]
  #include <stdio.h>
  #include <unistd.h>
  #include "altera_avalon_pio_regs.h"
  #include "sys/alt_irq.h"
  #include "system.h"
  #define NONE_PRESSED 0xF
  <@\texttt{\textcolor{red}{\#define KEY\_3 0x8}}@>
  <@\texttt{\textcolor{red}{\#define KEY\_2 0x4}}@>
  <@\texttt{\textcolor{red}{\#define KEY\_1 0x2}}@>
  <@\texttt{\textcolor{red}{\#define KEY\_0 0x1}}@>
  #define DEBOUNCE 30000
  volatile int edge_capture; //from docs
  void handle_button_interrupts(void* context, alt_u32 id) {
    volatile int* edge_capture_ptr = (volatile int*) context;
    *edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(<@\texttt{\textcolor{red}{BUTTONS\_BASE}}@>);
    // Сбросили флажки зарегистрированного прерывания
    <@\texttt{\textcolor{red}{IOWR\_ALTERA\_AVALON\_PIO\_EDGE\_CAP}}@>(BUTTONS_BASE, 0x0);
    IORD_ALTERA_AVALON_PIO_EDGE_CAP(BUTTONS_BASE);
  }
  void init_button_pio() {
    // from docs
    void* edge_capture_ptr = (void*) &edge_capture; // для формирования передаваемого в
    прерывание контекста
    IOWR_ALTERA_AVALON_PIO_IRQ_MASK(BUTTONS_BASE, 0xf);
    IOWR_ALTERA_AVALON_PIO_EDGE_CAP(BUTTONS_BASE, 0x0);
    alt_ic_isr_register(BUTTONS_IRQ_INTERRUPT_CONTROLLER_ID,
    BUTTONS_IRQ
    handle_button_interrupts,
    edge_capture_ptr, 0x0);
  }
  int main(void) {
    int led = 0x01;
    printf("Simple\n");
    IOWR_ALTERA_AVALON_PIO_DATA(GREEN_LED_BASE,led);
    init_button_pio();
    <@\texttt{\textcolor{red}{edge\_capture = 0;} \textcolor{codecomments}{// инициализация}}@>
    <@\texttt{\textcolor{red}{while (1) \{}}@>
      <@\texttt{\textcolor{red}{if (edge\_capture != 0) \{} \textcolor{codecomments}{// Если переменная была изменена (случилось прерывание)}}@>
        <@\texttt{\textcolor{red}{switch(edge\_capture) \{}}@>
          <@\texttt{\textcolor{red}{case KEY\_3:}}@>
            <@\texttt{\textcolor{red}{led = 0xFF;}\textcolor{codecomments}{ // all bits 1}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_2:}}@>
            <@\texttt{\textcolor{red}{led \&= led >> 1;}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_1:}}@>
            <@\texttt{\textcolor{red}{led \&= led << 1;}}@>
          <@\texttt{\textcolor{red}{break;}}@>
          <@\texttt{\textcolor{red}{case KEY\_0:}}@>
            <@\texttt{\textcolor{red}{led = 0x00;}\textcolor{codecomments}{ // all bits 0}}@>
          <@\texttt{\textcolor{red}{break;}}@>
        <@\texttt{\textcolor{red}{\}}}@>
        IOWR_ALTERA_AVALON_PIO_DATA(GREEN_LED_BASE,led);
        edge_capture = 0; <@\texttt{\textcolor{codecomments}{// сбросили глобальную переменную наличия данных от периферии}}@>
      }
    }
  }
\end{lstlisting}

\end{document}