Мышь PS/2
Для кого этот документ
- Студентам курса "Периферийные устройства"
- Необходимое ПО: Quartus II
Подключение манипулятора к процессорной системе DE 2-115 Media Computer с использованием интерфейса PS/2
Цель работы: Изучение принципа работы манипулятора типа мышь, и его драйверов.
Задание на выполнение работы
Подготовленные для выполнения работы программные заготовки
Заготовка 1. Вначале все индикаторы (ledg, hex) должны быть погашены. Программа считывает слово из порта ввода вывода, анализирует поле VALID. Если оно не равно нулю, то считанное слово действительно. В этом случае программа выводит содержимое поля RAVAL на зеленые светодиоды, с учетом уже считанного слова, извлекает из буфера FIFO содержащиеся там байты и отображает на HEX индикаторах справа налево. На Hex индикаторах можно отобразить только первые 4 байта из буфера. В качестве параметра используется адрес порта ввода вывода. Сначала выполняем манипуляции с мышью или клавиатурой, затем запускаем программу. После того, как программа считает все содержимое буфера, она завершает свое выполнение.
Заготовка 2. Программа считывает слово из порта ввода вывода, анализирует поле VALID, если оно не равно нулю, то это значит данные в буфере FIFO действительны, и в этом случае программа пересылает младший байт считанного слова в ячейку ОП, начиная с заданного адреса. Если данных в буфере FIFO нет, программа ожидает их поступления. Программа работает непрерывно. Для её завершения используется команда Stop из меню Аction приложения АМР. В качестве параметров используются адреса порта вв/выв и ОП. Предполагается, что после завершения программы во вкладке memory можно просмотреть содержимое ОП, используя побайтовое отображение.
Заготовка 2.1 Программа отличается от предыдущей тем, что разбирает считанные из буфера FIFO пакеты и отправляет их в ОП таким образом, чтобы потом во вкладке memory удобно было выполнить анализ последовательности из первых байт пакета (состояние кнопок мыши), вторых байт пакета (перемещение Х), третьих байтов пакета (перемещение У).
Заготовка 3. В программе выполняется программирование таймера для одноразового измерения интервала времени продолжительностью N секунд (N это параметр) и разрешается прерывание от таймера по завершению заданного интервала. Затем она анализирует наличие пакетов в буфере FIFO, переданных мышью. После обнаружения факта передачи пакетов от мыши, программа запускает таймер и непрерывно считывает передаваемые мышью пакеты и сохраняет их в ОП. После завершения заданного временного интервала обработчик прерывания определяет частоту дискретизации мыши поделив общее число принятых пакетов на длительность интервала и отображает вычисленное значение на красных светодиодах стенда. Вначале светодиоды должны быть погашены. Используя эту программу, можно экспериментально определить задаваемый временной параметр работы мыши. В качестве пунктов задания можно определить этот параметр, установленный по умолчанию, минимальное значение, максимальное значение. Рекомендуется использовать прямолинейную траекторию. После завершения работы программы можно исследовать переданные пакеты во вкладке memory и восстановить траекторию движения мыши. Можно предложить изменить скорость перемещения мыши от минимальной до максимально возможной и повторить выполнение программы.
Можно предложить в качестве индивидуальных вариантов траектории в виде квадрата с заданной стороной, треугольника с заданными сторонами, прямоугольника, трапеции. Можно использовать нажатие кнопок в вершинах фигуры. Студенты должны обнаружить этот факт во время анализа переданных пакетов.
1 часть. Режимы работы мыши и команды управления манипулятором
Для выполнения пунктов задания этой части рекомендуется использовать заготовку 1. Программа определяет есть ли информация в буфере FIFO, переданная PS2 устройством, и если она там есть, то программа извлекает её из буфера и отображает, например, на HEX индикаторах стенда.
-
Используя вкладку Memory приложения АМР, отправьте команду Reset 0xFF в порт данных мыши. Наблюдайте ответное сообщение со стороны мыши. Осмыслите переданную устройством информацию и отобразите в отчете ваше объяснение.
-
Экспериментально определите, будет ли устройство отправлять пакеты данных, если нажать одну из кнопок, левую, среднюю, правую?
-
Попробуйте переместить мышь в любом направлении. Проверьте, происходит ли пересылка данных от мыши в процессорную систему. Если да, осмыслите передаваемую устройством информацию. Если нет, попробуйте объяснить причину.
-
Используя вкладку Memory приложения АМР, отправьте команду Enable Data Reporting (0xF4) в порт данных мыши.
-
Повторите выполнение пунктов 1.2. и 1.3. Отразите в отчете произошедшие изменения.
-
Переключите мышь в удаленный режим работы (Remote). Для этого отправьте в порт данных мыши соответствующую команду Set Remote Mode (0xF0). Проверьте будет ли мышь пересылать пакеты данных о своих перемещениях, если нажать любую из кнопок или переместить мышь в некотором направлении. Зафиксируйте в отчете ваши наблюдения.
-
Отправьте команду Read Data (0xEB). в порт данных мыши. Еще раз проверьте, будет ли мышь пересылать пакеты данных о своих перемещениях, если нажать любую из кнопок мыши или переместить мышь в произвольном направлении. Если пакеты будут переданы, осмыслите их содержимое и отразите в отчете.
-
Не меняя положения мыши и не нажимая кнопок, еще раз повторите выполнение предыдущего пункта задания. Объясните содержимое переданного устройством пакета.
-
Установите мышь в обратный режим. Для этого отправьте в порт данных мыши команду Reset Wrap Mode (0xEC). Экспериментально определите поведение мыши в этом режиме. Попробуйте нажимать любые кнопки мыши и перемещать её в некотором направлении. Проверьте пересылает ли мышь в этом режиме пакеты данных о своих перемещениях. Отразите в отчете. Попробуйте отправлять мыши произвольные байты данных. Зафиксируйте в отчете, как на это будет реагировать мышь?
-
Проверьте и отразите в отчете реакцию мыши если в качестве передаваемого ей байта использовать команду (0хEC).
-
Проверьте реакцию мыши если отправить ей байт (0хFF). Следует напомнить, что этот байт используется для кодирования команды Reset.
-
Отправьте в порт данных мыши команду Get Device ID (0xF2). Убедитесь, что мышь передает свой идентификационный номер и сбрасывает свои счетчики перемещения. Занесите в отчет идентификационный номер мыши.
-
Отправьте в порт данных мыши команду запроса состояния Status Request (0xE9). Исследуйте передаваемые мышью ответные пакеты данных. Занесите в отчет. Осмыслите содержимое байтов пакета состояния.
2 часть. Исследование потокового режима работы мыши и формата пересылаемых пакетов
-
Отправьте в порт данных мыши команду Set Stream Mode (0xEA).
-
С помощью команды Enable Data Reporting (0xF4) разрешите мыши отправлять пакеты о своих перемещениях. Убедитесь, что пакеты пересылаются если нажать любую из кнопок мыши или переместить мышь в произвольном направлении.
-
Экспериментально определите формат пересылаемого пакета. Для этого, не перемещая мышь, нажмите левую кнопку и наблюдайте переданный пакет. Повторите эти действия для средней кнопки и для правой. Затем определите, какой разряд, какого байта пакета отображает состояние нажимаемых кнопок и отразите в отчете.
-
Установите минимальную частоту дискретизации, равную десяти отчетам в секунду. Для этого необходимо отправить команду Set Sample Rate (0хF3) в порт данных мыши. После получения байта подтверждения от мыши, отправьте байт с аргументом команды.
-
Для выполнения последующих пунктов задания рекомендуется в качестве коврика для мыши использовать лист миллиметровки с нанесенными на него координатными осями Х и Y.
-
Установите мышь на коврик таким образом, чтобы она была ориентирована строго вдоль оси У, и чтобы точка соединения мыши с проводом попала в центр координат коврика.
-
Переместите равномерно мышь вправо в горизонтальном направлении (по оси Х на коврике) в течении трех секунд. Определите какое количество отчетов было передано за это время в процессорную систему, анализируя поле RAVAL регистра данных порта мыши. Соответствует ли оно ожидаемому значению? Отразите в отчете. С помощью ранее использованной программы извлеките переданные мышью пакеты из буфера FIFO контроллера и осмыслите содержимое байтов со значениями перемещения Х и Y. Уясните, как формируются эти значения и отразите в отчете. По координатной сетке на коврике определите, на какое расстояние переместилась мышь за это время. Определите разрешающую способность мыши, анализируя переданные мышью пакеты и отразите в отчете.
-
Повторите предыдущий пункт задания, равномерно перемещая мышь влево в течении трех секунд, но теперь уже с большей скоростью. Определите координату конечной точки, куда переместилась мышь по координатной сетке на коврике мыши. Проанализируйте переданные мышью пакеты. Уясните в каком коде формируются отрицательные значения перемещения по оси Х. По содержимому переданных пакетов попробуйте определить координату конечной точки траектории и сравните её с экспериментально определенной.
-
Еще раз установите мышь в начало координат. Повторите пункт 1.16. задания, равномерно перемещая мышь по направлению оси Y (от себя в плоскости стола). Занесите в отчет ваши наблюдения. А если предварительно повернуть мышь по часовой стрелке на угол 45 градусов? Уясните, как мышь воспринимает направления Х и У.
-
Повторите пункт 1.16. задания, равномерно перемещая мышь в противоположном оси Y направлении (к себе в плоскости стола), но уже с большей скоростью. Определите координату конечной точки, куда переместилась мышь по координатной сетке на коврике мыши. Проанализируйте переданные мышью пакеты. Уясните в каком коде формируются отрицательные значения перемещения по оси У. По содержимому переданных пакетов попробуйте определить координату конечной точки траектории и сравните её с экспериментально определенной.
Часть3. Определение разрешающей способности мыши и её временных характеристик
Для выполнения последующих пунктов задания…
-
Экспериментально определите параметры мыши, устанавливаемые по умолчанию. Для этого повторно установите мышь в потоковый режим, после получения подтверждения отправьте команду запроса состояния мыши Status Request (0xE9). Исследуйте передаваемый мышью ответный пакет данных. Определите её разрешение, частоту опроса и масштабирование. Для расшифровки переданных мышью данных рекомендуется использовать информацию из предварительно изученного теоретического раздела, включенную в отчет при подготовке к лабораторной работе.
-
Выполните перемещение мыши из центра координат вдоль биссектрисы угла первой координатной четверти, используя установленную по умолчанию частоту дискретизации. Экспериментально определите её значение, сопоставив количество переданных мышью пакетов и время перемещения мыши. Если обнаружится, что буфер полностью заполнен, уменьшите время перемещения мыши. Определите максимальный размер буфера FIFO и предельное время его заполнения при работе мыши с такой частотой дискретизации. Проанализируйте содержимое переданных мышью пакетов.
-
Установите частоту дискретизации 20 значений в секунду, отправив в порт данных мыши соответствующую команду.
-
Установите минимальное разрешение, соответствующее одному значению на миллиметр, отправив в порт данных мыши команду Set Resolution (0xE8), наблюдайте ответный байт от мыши, после чего передайте байт с аргументом для этой команды (00).
-
Выполните перемещение мыши в противоположном направлении вдоль биссектрисы угла первой координатной четверти в центр координат. Проанализируйте количество и содержимое переданных за это время пакетов данных. Сопоставьте с ожидаемыми значениями. Отразите в отчете ваше заключение.
-
Установите максимальное разрешение, соответствующее восьми значениям на миллиметр, отправив в порт данных мыши команду Set Resolution (0xE8), наблюдайте ответный байт от мыши, после чего передайте байт с аргументом для этой команды (03).
-
Выполните перемещение мыши в любом направлении. Проанализируйте количество и содержимое переданных за это время пакетов данных. Сопоставьте с ожидаемыми значениями. Отразите в отчете ваше заключение.
4 часть. Исследование параметра масштабирования мыши
-
Повторно установите мышь в потоковый режим. Для этого повторите выполнение пункта 1.20 задания. Следует напомнить, что после выполнения этой команды устанавливаются параметры работы мыши, соответствующие настройкам по умолчанию, включая масштабирование 1:1.
-
Установите мышь в центр координат на коврике и ориентируйте вдоль оси У. Переместите мышь с некоторым ускорением по прямой линии в первой четверти в течении 2 секунд. С помощью программной заготовки 3 сохраните передаваемые мышью пакеты о её перемещении в ОП.
-
Установите масштабирование 2 :1, отправив в порт данных мыши команду Set Scaling 2:1 (0хЕ7). Повторите выполнение предыдущего пункта. Сопоставьте переданные мышью данные с наблюдаемыми в предыдущем пункте. Занесите в отчет ваше заключение.
Отчетные материалы
Отчет должен включать в себя:
- Цель работы.
- Краткие сведения из теоретической части.
- Информацию по выполнению пунктов задания.
- Краткое заключение.
Контрольные вопросы
- Какой режим работы мыши является основным?
- В чем особенность удаленного режима работы мыши?
- В чем заключается обратный режим работы мыши?
- Какие команды работают в обратном режиме?
- Как разрешить/запретить отправку мышью пакетов?
- Как экспериментально в лабораторной работе определяется разрешение мыши? Каково его минимальное и максимальное значение?
- Как экспериментально в лабораторной работе определяется частота дискретизации мыши? Каково её минимальное и максимальное значение?
- Как инициализируется использование колеса прокрутки в мыши?
- Как хост может понять, какое устройство к нему подключено?
- Какой идентификационный номер соответствует обычной мыши?
- Какой идентификационный номер соответствует мыши с колесом прокрутки?
- Чем отличаются пакеты, отправляемые мышью с колесом прокрутки?
- Как отличить пакет состояния мыши от пакета перемещения мыши?
Литература
- Ефремов Н. В., Бородин А. А. Инструментальные средства проектирования и отладки цифровых систем на программируемом кристалле фирмы «Altera». Учебное пособие. — М.: ФГБОУ ВПО МГУЛ, 2012. — 151 с.
- Ввод с помощью мыши. [Электронный ресурс] // OSDev Wiki. URL: https://wiki.osdev.org/Mouse_Input.
- Контроллер интерфейса PS/2. [Электронный ресурс] // OSDev Wiki. — URL: https://osdev.fandom.com/ru/wiki/%D0%9A%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D0%BB%D0%B5%D1%80_%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81%D0%B0_PS/2#%D0%98%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81_PS/2.
- Altera Monitor Program. [Электронный ресурс] // URL: http://www-ug.eecg.toronto.edu/desl/docs/Monitor_tutorial.pdf.
Приложение 1
Варианты заданий
| № Варианта | Дискретизация п.4.8 | Разрешение п.4.8 |
|---|---|---|
| 1 | 10 | 1/mm |
| 2 | 20 | 2/mm |
| 3 | 40 | 4/mm |
| 4 | 60 | 8/mm |
| 5 | 80 | 1/mm |
| 6 | 100 | 2/mm |
| 7 | 200 | 4/mm |
| 8 | 80 | 8/mm |
| 9 | 40 | 1/mm |
| 10 | 10 | 2/mm |
| 11 | 60 | 4/mm |
| 12 | 100 | 8/mm |
Приложение 2
В зависимости от версии программы Altera Monitor Program могут использоваться другие адреса портов для периферийных устройств. В более ранних версиях используются следующие адреса:
.equ LED_R, 0x10000000
.equ PS2_DATA, 0x10000100
.equ TIMER, 0x10002000
.equ JTAG_UART_BASE, 0x10001000
Листинг 1
Исходный файл программы PS2_X_Y_Packets_Rate_to_JTAG_and_LedR.s
.equ LED_R, 0xFF200000
.equ PS2_DATA, 0xFF200100
.equ TIMER, 0xFF202000
.equ JTAG_UART_BASE, 0xFF201000
.equ PACKETS_START, 0x1000
.equ PACKETS_END, 0x2000
# Время работы таймера в секундах.
.equ TIMER_DURATION, 3
.text
.org 0x20
handler:
# Сохранение регистров.
stw ra, (sp)
stw r4, -4(sp)
stw r8, -8(sp)
stw r9, -12(sp)
subi sp, sp, 16
# Выход, если прерывание не является внешним.
rdctl r8, ctl4
beq r8, zero, handler_end
# Декремент ea на 1 команду.
subi ea, ea, 4
# Выход, если прерывание не от таймера.
andi r8, r8, 0b1
beq r8, zero, handler_end
# Выход, если программа завершилась.
movia r8, PROG_ENDED
ldb r8, (r8)
bne r8, zero, handler_end
# Печать абсолютного смещения по X.
movia r4, ABS_X_STR
call LOG_STR
movia r4, ABS_X
ldw r4, (r4)
call LOG_NUM
call LOG_LINE
# Печать абсолютного смещения по Y.
movia r4, ABS_Y_STR
call LOG_STR
movia r4, ABS_Y
ldw r4, (r4)
call LOG_NUM
call LOG_LINE
# Печать общего количества считанных пакетов.
movia r4, TOTAL_PACKETS_STR
call LOG_STR
movia r4, TOTAL_PACKETS
ldw r4, (r4)
call LOG_NUM
call LOG_LINE
# Печать частоты дискретизаци.
movi r8, TIMER_DURATION
div r8, r4, r8
movia r4, SAMPLING_RATE_STR
call LOG_STR
mov r4, r8
call LOG_NUM
call LOG_LINE
# Вывод частоты дискретизации на красные светодиоды.
movia r8, LED_R
stwio r4, (r8)
# Установка флага завершения программы.
movia r8, PROG_ENDED
movi r9, 1
stb r9, (r8)
handler_end:
# Восстановление регистров.
addi sp, sp, 16
ldw ra, (sp)
ldw r4, -4(sp)
ldw r8, -8(sp)
ldw r9, -12(sp)
eret
.global _start
_start:
# Начальный адрес стека.
movia sp, 0x3FFFFFC
# Инициализация переменных.
movia r8, ABS_X
stw zero, (r8)
movia r8, ABS_Y
stw zero, (r8)
movia r8, TOTAL_PACKETS
stw zero, (r8)
movia r8, PROG_ENDED
stb zero, (r8)
# Очистка красных светодиодов.
call CLEAR_LED_R
# Очистка буфера.
call CLEAR_PS2_BUFF
# Очистка ОП для записи пакетов.
movia r4, PACKETS_START
movia r5, PACKETS_END
call CLEAR_MEM
# Адрес начала регистров таймера.
movia r8, TIMER
# Остановка таймера.
movi r9, 0b1000
sthio r9, 0x4(r8)
# Сброс поля TO таймера.
sthio zero, (r8)
# Установка длительности работы таймера = 50МГц * TIMER_DURATION.
movia r9, 50000000
muli r9, r9, TIMER_DURATION
# Запись младшего полуслова длительности.
sthio r9, 0x8(r8)
# Запись старшего полуслова длительности.
srli r9, r9, 16
sthio r9, 0xC(r8)
# Разрешение внешних прерываний.
movi r9, 0b1
wrctl status, r9
# Разрешение прерываний от таймера.
wrctl ienable, r9
# Чтение первого пакета мыши в r2.
call READ_PS2_PACKET
# Запуск таймера STOP = 0, START = 1, CONT = 0, ITO = 1.
movi r9, 0b0101
sthio r9, 0x4(r8)
# Начальный адрес пакетов в ОП в r8.
movia r8, PACKETS_START
# Общее количество считанных пакетов в r9.
mov r9, zero
# Абсолютное смещение по X в r10.
mov r10, zero
# Абсолютное смещение по Y в r11.
mov r11, zero
while:
# Адрес записи пакета в ОП.
muli r12, r9, 4
add r12, r8, r12
# Запись пакета в ОП.
stw r2, (r12)
# Выделение 1 байта с флагами в r12.
andi r12, r2, 0xFF
# Выделение 2-го байта с относительным смещением по X в r2.
srli r2, r2, 8
andi r13, r2, 0xFF
# Относительное смещение по X со знаком.
slli r14, r12, 4
andi r14, r14, 0x100
sub r13, r13, r14
# Увеличение абсолютного смещения по X.
add r10, r10, r13
movia r13, ABS_X
stw r10, (r13)
# Выделение 3 байта с относительным смещением по Y.
srli r2, r2, 8
andi r13, r2, 0xFF
# Относительное смещение по Y со знаком.
slli r14, r12, 3
andi r14, r14, 0x100
sub r13, r13, r14
# Увеличение абсолютного смещения по Y.
add r11, r11, r13
movia r13, ABS_Y
stw r11, (r13)
# Увеличение количества считанных пакетов.
addi r9, r9, 1
movia r13, TOTAL_PACKETS
stw r9, (r13)
# Чтение следующего пакета.
call READ_PS2_PACKET
br while
/* Очищает красные светодиоды. */
CLEAR_LED_R:
# Сохранение регистра.
stw r8, (sp)
movia r8, LED_R
stwio zero, (r8)
# Восстановление регистра.
ldw r8, (sp)
ret
/* Очищает буфер FIFO. */
CLEAR_PS2_BUFF:
# Сохранение регистров.
stw ra, (sp)
stw r2, -4(sp)
subi sp, sp, 8
CLEAR_PS2_BUFF_LOOP:
# Чтение регистра PS2_Data в r2.
call READ_PS2_DATA
# Выделение 15 бита RVALID.
andi r2, r2, 0x8000
# Если RVALID = 1, то продолжаем чтение.
bne r2, zero, CLEAR_PS2_BUFF_LOOP
# Восстановление регистров.
addi sp, sp, 8
ldw ra, (sp)
ldw r2, -4(sp)
ret
/* Очистка области памяти с адреса r4 по r5 */
CLEAR_MEM:
# Сохранение регистра.
stw r4, (sp)
CLEAR_MEM_LOOP:
# Очистка памяти.
stw zero, (r4)
addi r4, r4, 4
# Если очистили не всю область памяти, то продолжаем.
blt r4, r5, CLEAR_MEM_LOOP
# Восстановление регистра.
ldw r4, (sp)
ret
/* Записывает значение регистра PS2_Data в r2. */
READ_PS2_DATA:
movia r2, PS2_DATA
ldwio r2, (r2)
ret
/* Возвращает байты пакета мыши PS2 в r2. */
READ_PS2_PACKET:
# Сохранение регистров.
stw ra, (sp)
stw r8, -4(sp)
stw r9, -8(sp)
stw r10, -12(sp)
subi sp, sp, 16
# Номер байта в пакете.
mov r8, zero
# Результат (байты пакета).
mov r9, zero
READ_PS2_PACKET_LOOP:
# Чтение регистра PS2_Data в r2.
call READ_PS2_DATA
# Выделение 15 бита RVALID.
srli r10, r2, 15
andi r10, r10, 1
# Если RVALID = 0, то ожидаем следующий байт.
beq r10, zero, READ_PS2_PACKET_LOOP
# Выделение поля DATA.
andi r2, r2, 0xFF
# Сдвиг значения влево на (номер байта * 8 бит).
muli r10, r8, 8
sll r2, r2, r10
# Добавление байта к результату.
or r9, r9, r2
# Инкремент номера байта.
addi r8, r8, 1
# Если номер байта < 3, то продолжаем чтение.
cmplti r10, r8, 3
bne r10, zero, READ_PS2_PACKET_LOOP
# Запись результата в r2.
mov r2, r9
# Восстановление регистров.
addi sp, sp, 16
ldw ra, (sp)
ldw r8, -4(sp)
ldw r9, -8(sp)
ldw r10, -12(sp)
ret
/* Отправляет символ из r4 в JTAG UART. */
LOG_CHAR:
# Сохранение регистров.
stw r8, (sp)
stw r9, -4(sp)
stw r10, -8(sp)
# Загрузка базового адреса JTAG UART в r8.
movia r8, JTAG_UART_BASE
# Чтение регистра управления.
ldwio r9, 4(r8)
# Выделение поля WSPACE (доступное место в буфере записи).
srli r9, r9, 16
# Запись символа в поле DATA регистра данных.
stbio r4, (r8)
# Восстановление регистров.
ldw r8, (sp)
ldw r9, -4(sp)
ldw r10, -8(sp)
ret
/* Отправляет число из r4 в JTAG UART. */
LOG_NUM:
# Сохранение регистров.
stw ra, (sp)
stw r4, -4(sp)
stw r8, -8(sp)
stw r9, -12(sp)
stw r10, -16(sp)
stw r11, -20(sp)
subi sp, sp, 24
# Адрес текущего символа в r8.
mov r8, r4
# Число 10 в r9.
movi r9, 10
# Изначальный адрес стека в r11.
mov r11, sp
# Проверка является ли число положительным.
bge r8, zero, LOG_NUM_POSITIVE
# Если число отрицательное, печатаем минус.
movi r4, 0x2D
call LOG_CHAR
# И делаем число положительным.
muli r8, r8, -1
LOG_NUM_POSITIVE:
# Получаем остаток от деления на 10 в r4.
div r10, r8, r9
mul r4, r10, r9
sub r4, r8, r4
# Добавляем цифру в стек.
stw r4, (sp)
subi sp, sp, 4
# Цикл пока результат деления != 0.
mov r8, r10
bne r8, zero, LOG_NUM_POSITIVE
LOG_NUM_DIGITS:
# Печать цифр.
addi sp, sp, 4
ldw r4, (sp)
addi r4, r4, 0x30
call LOG_CHAR
bne sp, r11, LOG_NUM_DIGITS
# Восстановление регистров.
addi sp, sp, 24
ldw ra, (sp)
ldw r4, -4(sp)
ldw r8, -8(sp)
ldw r9, -12(sp)
ldw r10, -16(sp)
ldw r11, -20(sp)
ret
/* Отправляет строку по адресу r4 в JTAG UART. */
LOG_STR:
# Сохранение регистров.
stw ra, (sp)
stw r4, -4(sp)
stw r8, -8(sp)
subi sp, sp, 12
# Адрес текущего символа в r8.
mov r8, r4
LOG_STR_LOOP:
# Печать символов.
ldb r4, (r8)
# Если по адресу текущего символа пусто, то выходим.
beq r4, zero, LOG_STR_END
call LOG_CHAR
addi r8, r8, 1
br LOG_STR_LOOP
LOG_STR_END:
# Восстановление регистров.
addi sp, sp, 12
ldw ra, (sp)
ldw r4, -4(sp)
ldw r8, -8(sp)
ret
/* Отправляет символ перехода на новую строку в JTAG UART. */
LOG_LINE:
# Сохранение регистров.
stw ra, (sp)
stw r4, -4(sp)
subi sp, sp, 8
# Печать пробела.
movi r4, 0xA
call LOG_CHAR
# Восстановление регистров.
addi sp, sp, 8
ldw ra, (sp)
ldw r4, -4(sp)
ret
.data
ABS_X:
.word 0
ABS_Y:
.word 0
TOTAL_PACKETS:
.word 0
PROG_ENDED:
.byte 0
ABS_X_STR:
.asciz "x: "
ABS_Y_STR:
.asciz "y: "
TOTAL_PACKETS_STR:
.asciz "packets: "
SAMPLING_RATE_STR:
.asciz "sampling rate: "
.end
Чеклист выполнения
- Работа выполнена
- Отчет подготовлен