[#23]
Re: Amiga i przerwania !!!
@68k_tester,
post #22
Oto finał!!!
Gotowy działający przykład dla zainteresowanych.
Dzieki wszystkim za pomoc i wszelkie uwagi.
Krok po kroku dało to efekt końcowy.
kolej na serial.device
Pozdrawiam.
;-------------------------------------------------------------------
;Przykładowy program synchronicznego odczytu stanu klawiatury
;poprzez urządzenie 'keyboard.device'
;System: Amiga 500 (OS 1.3) Kickstart (v34)
;Procesor: MC68000
;Assembler: DevPac 3.02 (HiSoft)
;Data: 07.05.2009
;Testy: OK Działa!!!
;wektory skoków do funkcji biblioteki 'exec.library'
Exec: equ 4
AllocSignal: equ -330
FreeSignal: equ -336
AddPort: equ -354
RemPort: equ -360
FindTask: equ -294
OpenDevice: equ -444
CloseDevice: equ -450
DoIO: equ -456
;stałe i offsety do struktur programu
ln_Name = 10 ;(DWORD) offset do pola ln_Name struktury Node
ln_Pri = 9 ;(BYTE) offset do pola ln_Pri struktury Node
ln_Type = 8 ;(BYTE) offset do pola ln_Type struktury Node
mp_Flags = 14 ;(BYTE) offset do pola mp_Flag struktury MsgPort
mp_SigBit = 15 ;(BYTE) offset do pola mp_SigBit struktury MsgPort
mp_SigTask = 16 ;(DWORD) offset do pola mp_SigTask struktury MsgPort
NT_MSGPORT = 4 ;identyfikator typu struktury
PA_SIGNAL = 0 ;wiadomość ma otrzymać Task nie Przerwanie
mn_ReplyPort = 14 ;(DWORD) offset do pola mn_ReplyPort struktury Message
mn_Length = 18 ;(WORD) offset do pola mn_Length struktury Message
NT_MESSAGE = 5 ;oznacza stan: wysyłanie wiadomości......
;UWAGA: Gdy wiadomość zostaje odesłana pole to
;zmieni się na wartość NT_REPLYMSG i jeśli wtedy
;z tym parametrem ponownie ją wyślemy będzie Guru...
KBD_READEVENT = 9 ;polecenie wysyłane do urządzenia (odczyt klawiatury)
io_Command = 28 ;(WORD) offset do pola io_Command struktury IOStdReq
io_Length = 36 ;(DWORD) offset do pola io_Length struktury IOStdReq
io_Data = 40 ;(DWORD) offset do pola io_Data struktury IOStdReq
ie_Code = 6 ;(WORD) offset do pola ie_Code struktury InputEvent
ie_Qualifier = 8 ;(WORD) offset do pola ie_Qualifier struktury InputEvent
;Ta dyrektywa assemblacji umieszcza kod programu w pamięci CHIP_RAM
SECTION Program,CODE_C
Start: clr.l d0 ;priorytet portu na 0
move.l d0,a0 ;brak nazy portu
lea StrukturaMsgPort,a1
bsr CreatePort
tst.l d0 ;teraz rej.A1 zawiera wskaźnik do (MsgPort)
bne Error_001
lea StrukturaIOStdReq,a0
move.w #48,d0
bsr CreateExtIO
move.l Exec.w,a6
move.l #DeviceNameKeyboard,a0
moveq #0,d0
move.l #StrukturaIOStdReq,a1
moveq #0,d1
jsr OpenDevice(a6)
tst.l d0
bne.s Error_003
KeyLoopRead: lea StrukturaIOStdReq,a0
move.w #KBD_READEVENT,io_Command(a0)
move.l #StrukturaInputEvent,io_Data(a0)
move.l #22,io_Length(a0) ;Rozmiar struktury (InputEvent)
move.l a0,a1
move.l Exec.w,a6
jsr DoIO(a6) ;czekamy na komunikat z urządzenia!!!!
tst.l d0
bne.s Error_002
;Tutaj odbieramy stan klawiatury
;----------------------------------------------------------
;UWAGA: teraz w polu (ie_Code) struktury (InputEvent) mamy
;kod odebranego klawisza natomiast pole (ie_Qualifier) zawiera
;maskę klawiszy specjalnych oba pola są typu (WORD)
clr.l d0
clr.l d1
lea StrukturaInputEvent,a1
move.w ie_Code(a1),d0 ;rej.D0.w = odczytany kod klawisza
move.w ie_Qualifier(a1),d1 ;rej.D1.w = stan klawiszy specjalnych
;----------------------------------------------------------
;Aby oczekiwać na kolejną zmianę stanu klawiatury
;wykonujemy tu skok do etykiety: KeyLoopRead
Error_002: move.l #StrukturaIOStdReq,a1
move.l Exec.w,a6
jsr CloseDevice(a6)
Error_003: lea StrukturaMsgPort,a1
bsr DeletePort
moveq #0,d0
Error_001: rts
;Ta dyrektywa DevPac'a umieszcza struktury w osobnym
;HUNK'u i zapewnia dodatkowo wyrównanie adresu w pamięci.
SECTION StrukturyProgramu,DATA_C
StrukturaMsgPort: dcb.b 34,0
StrukturaIOStdReq: dcb.b 48,0
StrukturaInputEvent: dcb.b 22,0
DeviceNameKeyboard: dc.b "keyboard.device",0
;Ta dyrektywa assemblacji umieszcza dalszy kod programu w pamięci CHIP_RAM
SECTION Program,CODE_C
;----------------------------------------------------------------------
;[D0.b] = CreatePort([A0.l],[A1.l],[D0.b])
;
;Funkcja tworzy port komunikacyjny o podanych parametrach na jej
;wyjściu pod adresem wskazywanym rej.A1 uzyskujemy przygotowaną
;strukturę (MsgPort) przydzielonego portu.
;UWAGA: Wcześniej rezerwujemy pamięć (struktura MsgPort rozmiar = 34 bajty.)
;
;wejście: A0.l = Wskaźnik do nazwy tworzonego portu lub 0.
; A1.l = Wskaźnik do obszaru pamięci przydzielonego
; wcześniej na bufor dla kreowanej struktury (MsgPort).
; D0.b = Priorytet elementu (struktury) używany do
; sortowania elementów do których przynależy (struktura)
; zakres od najwiekszego (127) do najmniejszego (-128).
; Zwykle jako priorytet podajemy wartość 0.
;
;wyjście: D0.b = Zawiera 0 jeśli wszystko OK czyli przydzielono
; bit sygnałowy i utworzono port lub -1 jeśli Error.
; A1.l = Jeśli rej.D0.b = 0 to rej.A1.l wskazuje na
; aktywną strukturę (MsgPort) przydzielonego portu!
CreatePort: move.b d0,ln_Pri(a1)
move.l a0,ln_Name(a1)
move.b #NT_MSGPORT,ln_Type(a1)
move.b #PA_SIGNAL,mp_Flags(a1)
move.l Exec.w,a6
moveq #-1,d0 ;-1 = dowolny wolny bit sygnałowy.
movem.l a1,-(SP)
jsr AllocSignal(a6)
move.l (SP)+,a1
tst.l d0
bmi.s CP_Error_00 ;wartość ujemna to błąd!
move.b d0,mp_SigBit(a1)
move.l Exec.w,a6
movem.l a1,-(SP)
move.l #0,a1 ;wartość 0 oznacza aktualny Task
jsr FindTask(a6)
movem.l (SP)+,a1
move.l d0,mp_SigTask(a1)
move.l Exec.w,a6
jsr AddPort(a6)
moveq #0,d0
rts
CP_Error_00: moveq #-1,d0
rts
;-------------------------------------------------------------------
;DeletePort([A1.l])
;
;wejście: A1.l = Wskaźnik do obszaru pamięci struktury (MsgPort) która
; została wcześniej utworzona poprzez funkcję CreatePort()
DeletePort: move.l Exec.w,a6
movem.l a1,-(SP)
jsr RemPort(a6)
move.l (SP)+,a1
move.b mp_SigBit(a1),d0
move.l Exec.w,a6
jsr FreeSignal(a6)
rts
;-------------------------------------------------------------------
;CreateExtIO([A0.l],[A1.l],[D0.b])
;
;wejście: A0.l = Wskaźnik do przydzielonego wcześniej obszaru
; struktury wynikowej, która podlega inicjalizacji
; chodzi o struktury typu (IOReuest) lub (IOStdReq)
; A1.l = Wskaźnik do struktury (MsgPort)
; D0.w = Rozmiar nowej struktury.(wartość typu WORD)
; UWAGA: Funkcja nie allokuje samodzielnie obszaru
; który modyfikuje więc nie wymaga istnienia jej
; odpowiednika zamykającego czyli funkcji DeleteExtIO()
;Funkcja inicjalizuje strukturę do której wskaźnik przekazujemy w
;rej.A0 a w rej.D0 podajemy jej rozmiar!!!
CreateExtIO: cmp.w #20,d0 ;rozmiar minimum 20
blt.s CEI_Error_00
move.b #NT_MESSAGE,ln_Type(a0)
move.w d0,mn_Length(a0)
move.l a1,mn_ReplyPort(a0)
CEI_Error_00: rts
;-------------------------------------------------------------------