Главная » Ассемблер, Железо » Непосредственная работа с мышью типа MS Mouse

0

Рассмотрим непосредственную работу с мышью на примере манипуляторов, использующих стандартный формат MS Mouse. Процесс установки нового драйвера мыши включает целый ряд операций, которые необходимо выполнять в следующем порядке.

1.     Запретить прерывания от последовательного порта.

2.     Загрузить в регистры СОМ-порта параметры, соответствующие протоколу передачи данных.

3.     Установить вектор прерывания на новую программу-обработчик.

4.     Разрешить аппаратуре контроллера прерываний формировать прерывания от используемого мышью СОМ-порта.

5.     Подать на мышь напряжение питания.

6.          Разрешить генерацию прерываний СОМ-портом. Разрешить или запретить прохождение прерываний от последовательного порта можно при помощи регистра маски ведущей микросхемы контроллера прерываний, к которой присоединены линии запросов от СОМ1 (линия IRQ4) и COM2 (линия IRQ3). Работа с контроллером прерываний уже была описана в разделе «Контроллер прерываний» главы 1 «Работа с клавиатурой». После завершения обработки прерывания необходимо разблокировать контроллер, послав ему команду завершения обработки прерывания E0I.

Настройка вектора прерывания заключается в записи начального адреса программы-обработчика в соответствующие вектору ячейки оперативной памяти. Для записи вектора необходимо занести в сегментный регистр данных нулевое значение, в индексный регистр поместить номер вектора прерывания, помноженный на 4, записать в ячейку памяти (используя косвенную адресацию) слово — смещение, увеличить значение индексного регистра на 2 и записать слово — сегмент адреса обработчика прерывания.

Рассмотрим более подробно последние два этапа, поскольку они имеют ряд неочевидных особенностей. В процессе разработки способа подключения мыши к последовательным портам был использован радиолюбительский трюк: питание мыши осуществляется от сигнальных линий DTR и RTS. Для управления генераций прерываний применяется линия 0UT2. Таким образом, чтобы подать питание на мышь и разрешить порту вырабатывать прерывания, необходимо установить в 1 биты 0, 1 и 3 регистра управления модемом, то есть записать в регистр xFCh значение OBh.

Чаще всего мышь подключают к порту СОМ1. Однако если заранее не известно, к какому порту подключена мышь (и подключена ли вообще), то можно выполнить операцию идентификации мыши. Обычно процедура идентификации начинается с проверки того, подключено ли к порту какое-либо устройство. Вообще говоря, после подачи питания любое устройство, подключенное к последовательному порту, должно выдать сигнал готовности к работе DSR, значение которого можно прочитать в регистре состояния модема xFEh. Однако для мыши такой метод неприменим, поскольку сигнал DSR обычно отключают с целью сокращения количества проводников в соединительном кабеле мыши.

Чтобы убедиться, что к порту подключена мышь, поддерживающая протокол MS Mouse, нужно временно отключить ее питание (сбросив сигналы DTR и RTS), подождать 0,2 с (4-5 тиков системных часов) и подать питание вновь. После этого мышь должна выдать код 4Dh (латинская заглавная буква «М» в кодировке ASCII) или цепочку символов, начинающуюся с этого кода. У трехкнопочной мыши идентификационный код состоит не менее чем из двух символов (начинается с буквы М и следующей за ней цифры 3). Идентификационные коды для основных изготовителей оборудования можно при необходимости найти в спецификации PC 99 System Design Guide [80], однако на рынке постоянно появляются новые игроки. После того как завершено конфигурирование системы (определен используемый мышью порт) и произведена установка обработчика прерываний, новый драйвер мыши начинает работать. Драйвер должен принимать пакеты данных от мыши, вычислять координаты курсора и управлять перемещением курсора по экрану, то есть выполнять те же операции, что и стандартный драйвер Microsoft Mouse. Однако, в отличие от стандартного, «самодельный» драйвер можно настраивать на работу с любым видеоконтроллером в любом возможном видеорежиме. Кроме того, стандартный драйвер работает только в реальном режиме DOS, а собственные драйверы при необходимости можно написать для любого режима работы процессора х86, например, для защищенного или виртуального.

Процедуры, предназначенные для непосредственной работы с мышью на уровне регистров последовательного порта, собраны в листинге 5.1. Поиск мыши по последовательным портам СОМ1 и COM2 выполняется процедурой MSMouseSearch. После определения порта, к которому подключена мышь, следует запустить подпрограмму Set- MSMouselnterrupt, которая настраивает обработчик прерывания (устанавливая параметры порта и соответствующий вектор прерывания), а затем активизирует порт (подавая на мышь напряжение питания и разблокируя прерывания). Прерывания обрабатываются процедурой MSMouselnterrupt, принимающей от мыши пакеты данных и вычисляющей приращения координат курсора. После завершения работы с мышью необходимо восстановить старый вектор прерывания, вызвав процедуру RestoreOldMSMouselnterrupt.

Листинг 5.1. Универсальные процедуры для работы с мышью MS Mouse

DATASEG

: Предыдущее значение системного таймера Time DD ?

; Номер порта (0 – С0М1, 1 – COM2.

; 2 – мышь не обнаружена) COMPortNum DW О : Базовый адрес порта мыши COMPortBaseAddr DW 3F8h

: Область сохранения старого вектора прерывания 01dMSMouselnterruptOffset DW ? OldMSMouselnterruptSegment DW ?

; Номер принимаемого от мыши байта MouseByteNumber

DB О

; Трехбайтовая структура данных, передаваемая мышью

FirstByte

DB О

SecondByte

DB О

ThirdByte OB 0

; Текущее состояние кнопок

ButtonsStatus

DB О

; Текущие координаты курсора мыши

XCoordinate DW О

YCoordinate DW О

; Предыдущая позиция курсора мыши

01dXCoordinate DW О

OldYCoordinate DW О

; Состояние курсора мыши

; (0 – не отображается, 1 – отображается) ‘

MouseCursorStatus

DB О

ENDS

CODESEG

;* ПОИСК МЫШИ ПО ПОСЛЕДОВАТЕЛЬНЫМ ПОРТАМ * ;* Процедура подготавливает глобальные переменные * ;* COMPortNum и COMPortBaseAddr для подпрограммы * ;* установки обработчика прерывания*

PROC MSMouseSearch NEAR pusha

Листинг 5.1(продолжение)

push ES

; Запретить прерывание С0М1 и COM2 cli

in AL,21h Прочитать наску прерываний or AL,18h .-запретить IRQ3 и IRQ4 out 21h,AL ;заменить наску sti

.- Настроить ES на сегмент данных BIOS : для работы с системным таймером

mov АХ,О

mov ES.AX

; ПОИСК МЫШИ ЧЕРЕЗ СОМ-ПОРТЫ

@@MouseSearch:

; Устанавливаем скорость

; приема/передачи 1200 бод

mov DX,[COMPortBaseAddr]

add DX.3 in AL.DX

or AL,80h установить бит DLAB out DX.AL

mov DX.[COMPortBaseAddr]

mov AL,60h -.1200 бод

out DX.AL

inc DX

mov AL.O

out DX.AL

; Установить длину слова 7 бит. 1 стоповый бит,

; четность не контролировав

mov DX.[C0MPort8aseAddr]

add DX.3

mov AL,00000010b

out DX.AL

Запретить все прерывания

mov DX,[COMPortBaseAddr]

inc DX

mov AL.O out DX.AL

; Проверить, что устройство подключено и является

; мышью типа MSMouse

; Запомнить текущее время

mov ЕАХ,[ES:046Ch]

mov [Time],ЕАХ

; Отключить питание мыши и прерывания

mov DX.[COMPortBaseAddr]

add DX.4 ;регистр управления ноденом

mov AL.O ;сбросить DTR. RTS и 0UT2 out DX.AL

; Ожидать 5 "тиков" (0,2 с)

@@dT:

mov ЕАХ,[ES:046Ch] sub ЕАХ,[Time] cmp ЕАХ,5 jb

@@dT

; Включить питание мыши

mov AL,lib установить DTR и RTS out DX.AL

; Очистить регистр данных

mov DX,[COMPortBaseAddr] in AL.DX

; Цикл опроса порта P@WaitData:

; Ожидать еще 10 "тиков"

mov ЕАХ,[ES:046Ch] sub ЕАХ,[Time] cmp EAX,5+10 jae

@@NoMouse

: Проверить наличие идентификационного байта

mov DX.[COMPortBaseAddr]

add DX.5 in AL.DX

test AL,1 ;Данные готовы? jz P@WaitData : Ввести данные

mov DX,[COMPortBaseAddr] in AL,DX

; Устройство является мышью? cmp AL.’M’

je

@@End

@@NoMouse:

inc [COMPortNum] cmp [COMPortNum],1 ja (apEnd

sub [COMPortBaseAddr],lOOh jmp

@@MouseSearch

@@End: pop ES popa ret

ENDP MSMouseSearch

;* УСТАНОВИТЬ ВЕКТОР ПРЕРЫВАНИЯ ОТ ПОСЛЕДОВАТЕЛЬНОГО * ;*ПОРТА НА НОВЫЙ ДРАЙВЕР МЫШИ*

PROC SetMSMouselnterrupt NEAR pusha

push DS push ES

Листинг 5.1(продолжение)

mov АХ.[CS:Mai nDataSeg]

mov DS.AX

; Запретить прерывание от СОМ-порта

; Вычислить маскируемый разряд

mov CL.[byte ptr COMPortNum]

mov CH.lOh

shr CH.CL ;иаскируемый разряд – в CH cli

in AL,21h ;IMR 1-го контроллера прерываний or AL.CH запретить прерывание out 21h,AL sti

; Обнулить счетчик байтов

mov [MouseByteNumber].0 : Установка вектора прерывания на обработчик ныши

; Настроить ES на область векторов

mov АХ,О

mov ES.AX

; Вычислить адрес вектора

mov BX.OCh sub BX.[COMPortNum] shl BX.2

; Сохранить старый вектор

mov AX.[ES:BX]

mov [OldMSMouselnterruptOffset] ,AX

mov AX,[ES:BX+2]

mov [01dMSMouseInterruptSegment].AX

: Установить новый вектор

cli

mov AX.offset MSMouselnterrupt

mov [ES:BX],AX

mov AX.CS

mov [ES:BX+2],AX

sti

: АКТИВИЗИРОВАТЬ ПОРТ

; Разрешаем прерывание по приеиу данных

mov DX.[COMPortBaseAddr]

inc DX;xF9h

mov AL.l out DX.AL

; Установить DTR, RTS и 0UT2

; (подать напряжение питания и разрешить прерывания)

mov DX.[COMPortBaseAddr]

add DX.4;xFCh

mov AL.00001011b out DX.AL

; Очистить регистр данных

mov DX.[COMPortBaseAddr] ;xF8h

in AL.DX

; Разрешить прерывания от СОМ1 not CH cli

in AL,21h ;IMR 1-го контроллера прерываний and AL.CH разрешить прерывания out 21h,AL sti

pop ES pop DS popa ret

ENDP SetMSMouselnterrupt

;* ВОССТАНОВИТЬ СТАРЫЙ ВЕКТОР ПРЕРЫВАНИЯ МЫШИ *

• ArArilf^f^f^f’A k’if’fdc’k’itic’ic’ic’ic’ic’Mic’k’kif’Mic’ic’itic’ic’k ArJf Атк^г^гЛЛ’А k’if’ic’ic’ic "Mc

PROC RestoreddMSMouselnterrupt NEAR pusha

push ES

; Настроить ES на область векторов

mov AX,О

mov ES,AX

; Вычислить адрес вектора

mov BX.OCh

sub BX,[COMPortNum]

shl BX.2

: Восстановить старый вектор cli

mov AX,[01dMSMouselnterruptOffset]

mov [ES:BX],AX

mov AX,[01dMSMouselnterruptSegment]

mov [ES:BX+2].AX

sti

pop ES

popa

ret

ENDP RestoreddMSMouselnterrupt

;* НОВЫЙ ОБРАБОТЧИК ПРЕРЫВАНИЯ ОТ МЫШИ *

PROC MSMouselnterrupt NEAR pusha

push DS

sti разрешить маскируемые прерывания

mov AX,[CS:Mai nDataSeg]

mov DS.AX

; Проверить наличие данных

mov DX,[COMPortBaseAddr]

Листинг 5.1(продолжение)

add DX.5;xFDh

in AL.DX

test AL.l ;Данные готовы? jz

@@Error

; Ввести данные

mov DX, [COMPortBaseAddr] -.xFBh in AL.DX

; Разблокировать контроллер прерываний

mov AH.AL ;запомнить данные в АН

mov AL,20h

out 20h,AL ;послать команду EOI

mov AL.AH восстановить данные в AL

; Сбросить старший незначащий бит and AL,01111111b

; Определить порядковый номер принимаемого байта

cmp[MouseByteNumber],0

je@@FirstByte

cmp[MouseByteNumber],1

je@@SecondByte

cmp[MouseByteNumber],2

je@@ThirdByte

jmp@@Error

; Сохранить первый байт данных

@@FirstByte:

test AL, 1000000b -.Первый байт посылки?

jz

@@Error

mov [FirstByte],AL

inc [MouseByteNumber] увеличить счетчик jmp

@@EndMouseInterrupt : Сохранить второй байт данных PPSecondByte:

test AL,1000000b jnz

@@Error

mov [SecondByte],AL

inc [MouseByteNumber] .-увеличить счетчик jmp

@@EndMouseInterrupt

; Сохранить третий байт данных

@@ThirdByte:

test AL.1000000b jnz

@@Error

mov [ThirdByte],AL увеличить счетчик

mov [MouseByteNumber],0 : (Пакет данных от мыши принят полностью).

; Записать новое значение состояния кнопок мыши

mov AL,[FirstByte]

shr AL.4

mov [ButtonsStatus].AL

: Прибавить перемещение по X к координате X

mov • AL,[FirstByte] shl AL.6 or AL,[SecondByte] cbw

add AX.[XCoordinate]

; Курсор не должен выходить за левую или

; правую границу экрана

js

@@Х1

cmp AX.ScreenLength

jb <Ж2

: Установить координату X по правой границе

mov AX,ScreenLength-l jmp

@@Х2

@@Х1:

; Установить координату X по левой границе xor АХ,АХ

Ш2:

mov [XCoordinate],AX

: Прибавить перемещение по Y к координате Y

mov AL,[FirstByte] and AL,00001100b shl AL.4 or AL,[ThirdByte] cbw

add AX,[YCoordinate]

; Курсор не должен выходить за верхнюю или

: нижнюю границу экрана

js mi

cmp АХ,ScreenHeigth

jb Ш2

; Установить координату X по нижней границе

mov AX,ScreenHeigth-l jmp

@@Y2

@@Y1: : Установить координату X по верхней границе хог АХ.АХ

m2:

mov [YCoordinate] .АХ

; Показать курсор в новой позиции

cmp [MouseCursorStatus],0

je

@@EndMouseInterrupt call ShowNewMouseCursorPosition

jmp short

@@EndMouseInterrupt

@@Error:

: Произошел сбой в порядке передачи информации от

: мыши, обнулить счетчик байтов пакета данных

mov [MouseByteNumber],0

Листинг 5.1(продолжение)

@@EndMouseInterrupt: pop DS рора iret

ENDP MSMouselnterrupt ENDS

Приведенная в листинге 5.2 программа MSMouseMain, демонстрирующая работу с мышью через последовательный порт, использует процедуры из листинга 5.1. Для вывода курсора на экран вызывается процедура ShowNewMoiiseCursorPosition, которая инвертирует байт атрибута символа в позиции курсора (запоминая предварительно старое значение атрибута и восстанавливая его при перемещении курсора). Основная программа контролирует (в цикле) состояние левой кнопки мыши и завершает свою работу при нажатии на нее, восстанавливая предварительно старый вектор прерывания.

ПРИМЕЧАНИЕ

Данный пример не предъявляет никаких особых требований к составу оборудования. Он может быть запущен на любом AT-совместимом компьютере, к которому подключена мышь типа MS Mouse.

Листинг 5.2. Поиск мыши MS Mouse и установка обработчика прерывания

IDEAL

РЗВ6

LOCALS

MODEL MEDIUM

; Параметры экрана в текстовом режиме ScreenLength equ 80 ;количество символов в строке ScreenHeigth equ 25 количество строк на экране

; Подключить файл мнемонических обозначений

; кодов управляющих клавиш и цветовых кодов

Include "listl_03.inc"

; Подключить файл макросов

Include "1istl_04.inc"

SEGMENT sseg para stack ‘STACK’

DB 400h DUP(?)

ENDS

DATASEG

; Старое значение фона символа

OldCharBackground

DB OFh .

; Текстовые сообщения TxtO

DB YELLOW,0.24

DB "Тестирование мыши типа MS Mouse",0

DB YELLOW.24,35."Идите …",0 Txtl

DB WHITE.9,26."Мышь подключена к порту СОМГ’.О Txt2

DB WHITE.9.26,"Мышь подключена к порту СОМ2",0 Txt3

DB LIGHTGREEN,7.32."Результаты поиска:",0

DB LIGHTCYAN, 15.26

DB "Драйвер MS Mouse установлен".0

DB LIGHTBLUE.17,9,"Отображение курсора "

DB "осуществляется инверсией атрибута символа",0

DB YELLOW,24.21

DB "Для выхода нажмите левую клавишу мыши’,0 Txt4

DB 12,26,"Мышь MS Mouse не обнаружена".0 ENDS

CODESEG

;* Основной модуль программы *

PROC MSMouseMain

mov AX.DGROUP

mov DS.AX

mov [CS:MairiDataSeg],AX

; Установить текстовый режим и очистить экран

mov АХ,3 int 10h

; Скрыть текстовый курсор

mov [ScreenString],25

mov [ScreenColumn],0 call SetCursorPosition

; Вывести текстовые сообщения на экран

MShowColorText 2.TxtO

; Произвести поиск мыши по последовательным портам call MSMouseSearch

cmp [COMPortNum],l -.номер порта больше 1? ja

@@MouseNotFound ;мышь не найдена : Выдать сообщение об обнаружении мыши cmp [COMPortNum],0 jne

@@С0М2

mov SI,offset Txtl

jmp GXstOMl

@@C0M2:

mov SI,offset Txt2

@@C0M1: call ShowColorString

; Выдать сообщение о запуске драйвера MShowColorText 4,Txt3

; ДЕМОНСТРАЦИЯ РАБОТЫ ДРАЙВЕРА МЫШИ : Обнулить позицию курсора мыши

Листинг 5.2 (продолжение)

mov [XCoordiriate],0

mov [YCoordi nate].0

mov [OldXCoordinate],0

mov [OldYCoordinate],0

; Отобразить курсор мыши первый раз

mov [MouseCursorStatus].1 call ShowNewMouseCursorPositiori

; Установить новый обработчик прерывания

call SetMSMouselriterrupt

; Цикл, пока не нажата левая кнопка

@@Next: test [ButtorisStatus], 10b

jz

@@Next

; Восстановить прежний обработчик прерывания

call Restored dMSMouselriterrupt

; Переустановить текстовый режим и очистить экран

@@?nd:

mov АХ.З int 10h

; Выход в DOS

mov AH,4Ch int 21h

; Выдать сообщение "мышь не обнаружена"

@@MouseNotFound:

MFatalError Txt4 ENDP MSMouseMain

;* ОТОБРАЖЕНИЕ КУРСОРА МЫШИ ПУТЕМ ИНВЕРСИИ * ;* АТРИБУТА СИМВОЛА В ПОЗИЦИИ КУРСОРА *

• ‘к’к’к’к’к’к ‘к к "к A* ‘к"к’к ‘к’кк’к’к’к’к’к А* ‘к А* ‘к "к к’к "АА"А’ АгА"А’ Аг А А Аг А А "А1 А"Аг

PROC ShowNewMouseCursorPosition NEAR pusha

push ES

; Настроить ES на видеопаиять

mov AX.OBBOOh

mov ES.AX

: Вычислить старую координату курсора

mov АХ.[01dYCoordinate]

mov DX.160 mul DX

add AX.[OldXCoordinate]

add AX,[01dXCoordinate]

inc AX

mov DI.AX

: Восстановить атрибут символа

mov AL,[01dCharBackground]

mov [ES:DI],AL

: Вычислить новую координату курсора

mov АХ,[YCoordinate]

mov DX,160

mul DX

add AX.[XCoordinate]

add AX,[XCoordinate]

inc AX

mov DI.AX

; Сохранить атрибут символа

mov AL,[ES:DI]

mov [01 dCharBackground],AL

; Инвертировать атрибут

xor [byte ptr ES:DI],1111111b

; Запомнить координаты символа

mov AX,[XCoordi nate]

mov [01 dXCoordi nate],AX

mov AX,[YCoordi nate]

mov [01dYCoordi nate],AX

pop ES

popa

ret

ENDP ShowNewMouseCursorPosition ENDS

: Подключить процедуры вывода данных на экран

Include "listl_02.inc"

: Подключить универсальные процедуры для работы

; с мышью MS Mouse

Include "list5_01.inc"

END

Источник: Кулаков В. К90 Программирование на аппаратном уровне: специальный справочник (+дискета). 2-е издание. — СПб.: Питер, 2003. — 847 е.: ил.

По теме:

  • Комментарии