Aha alles klar. Gibt es irgendwo eine Tabelle/Beschreibung von den ganzen Interrupts ? Ich hab nähmlich nur so eine Portlist:
http://bochs.sourceforge.net/techspec/PORTS.LST
Den Timer muss ich in der ISR neu setzten. Sonst passiert folgendes: Timer an Port H40 mit Wert 1193 laden, der Wert wird nun herunter gezählt 1192, 1191, 1190... 3, 2, 1, 0 -> ISR wird aufgerufen, danach wird der Wert weiter runtergezählt, ist er jedoch bereits bei 0, überläuft der Timer und beginnt wieder bei 65535.... Deshalb muss ich den Timer immer wieder neu setzten.
Durch leichte Anpassung deines Code, funktioniert dieser einwandfrei. Frequenz wird am LPT ausgegeben, und die Uhr stimmt ebenfalls.
Code:
DIM Frequenz AS Shared word
DIM OldAddr AS SHARED DWORD
Frequenz = 2000
ClockOn
sleep
ClockOff
SUB ClockOn()
! mov Word Ptr CS: SaveDS, DS ;store PowerBASIC Data segment
GetInterruptVector &H08, OldAddr
SetInterruptVector &H08, CODEPTR32(ClockISR)
SetInterruptVector &H68, OldAddr
END SUB
SUB ClockOff()
SetInterruptVector &H08, OldAddr
END SUB
SUB SetInterruptVector(BYVAL Intr?, BYVAL NewAddr???) LOCAL
! push ds ; save DS
! mov ah, &H25 ; set AH to 25h (function number)
! mov al, Intr? ; set AL to interrupt vector being redirected
! lds DX, NewAddr???
! int &H21 ; call DOS services
! pop ds ; restore DS
END SUB
SUB GetInterruptVector(BYVAL Intr?, VAddr???) LOCAL PUBLIC
! push ds ; save DS
! push si ; save SI
! mov ah, &H35 ; set AH to 35h (function number)
! mov al, Intr? ; set AL to interrupt vector
! int &H21 ; call DOS services (ES:BX now holds address)
! lds si, VAddr??? ; get a pointer to VSeg??
! mov ds:[si+2], es ; copy ES (segment address) into VSeg??
! mov ds:[si], bx ; copy BX (offset address) into VOff??
! pop si ; restore SI
! pop ds ; restore DS
END SUB
SUB ISR () PRIVATE
DIM IsrStack AS STATIC STRING * 1024 '1k stack (probably too much)
DIM Counter AS STATIC INTEGER
DIM zaehler AS STATIC word
DIM L AS STATIC byte
DIM H AS STATIC byte
DIM ISRCounter AS STATIC word
SaveDS:
! dw 0
SaveSS:
! dw 0
SaveSP:
! dw 0
ClockISR:
! push ax ; save the general registers
! push bx
! push cx
! push dx
! push si
! push di
! push bp
! push ds
! push es
! push bp
! pushf ; save the flags register
! cli ; suspend all maskable interrupts
! mov Word Ptr CS:SaveSS, SS ; save current stack segment
! mov Word Ptr CS:SaveSP, SP ; save current stack pointer
! mov DS, Word Ptr CS:SaveDS ; restore PowerBASIC data segment
' Create a local stack frame
! mov SS, Word Ptr CS:SaveDS ; SS must equal DS for PowerBASIC runtime
! lea BX, IsrStack ; get address of the local stack frame
! add BX, 1024 ; point to the end of the fixed-length string
! mov SP, BX ; set the stack pointer
' ** Your Basic code goes here **
zaehler = 1193180 / Frequenz
L = zaehler
shift right zaehler, 8
H = zaehler
OUT (&H43), &b00110110
OUT (&H40), L
OUT (&H40), H
l = inp(888)
bit toggle l, 1
OUT (888), l
IF Counter = 0 THEN
LOCATE 1, 72, 0
COLOR 14,0
PRINT TIME$;
Counter = 18 '18 ticks per second
END IF
DECR Counter
IF ISRCounter = 0 THEN
! int &H68
ISRCounter = Frequenz / 18.2
ELSE
OUT (&H20), &H20
END IF
DECR ISRCounter
' ** End of Basic code
! mov SP, Word Ptr CS:SaveSP ; restore the original stack segment
! mov SS, Word Ptr CS:SaveSS ; and stack pointer before restoring the registers
! popf ; restore the flags register
! pop bp ; restore the general registers
! pop es
! pop ds
! pop bp
! pop di
! pop si
! pop dx
! pop cx
! pop bx
! pop ax
! sti ; re-enable maskable interrupt processing
! iret ; return from our interrupt handler
END SUB
Aha alles klar. Gibt es irgendwo eine Tabelle/Beschreibung von den ganzen Interrupts ? Ich hab nähmlich nur so eine Portlist: http://bochs.sourceforge.net/techspec/PORTS.LST
Den Timer muss ich in der ISR neu setzten. Sonst passiert folgendes: Timer an Port H40 mit Wert 1193 laden, der Wert wird nun herunter gezählt 1192, 1191, 1190... 3, 2, 1, 0 -> ISR wird aufgerufen, danach wird der Wert weiter runtergezählt, ist er jedoch bereits bei 0, überläuft der Timer und beginnt wieder bei 65535.... Deshalb muss ich den Timer immer wieder neu setzten.
Durch leichte Anpassung deines Code, funktioniert dieser einwandfrei. Frequenz wird am LPT ausgegeben, und die Uhr stimmt ebenfalls.
Code:
DIM Frequenz AS Shared word
DIM OldAddr AS SHARED DWORD
Frequenz = 2000
ClockOn
sleep
ClockOff
SUB ClockOn()
! mov Word Ptr CS: SaveDS, DS ;store PowerBASIC Data segment
GetInterruptVector &H08, OldAddr
SetInterruptVector &H08, CODEPTR32(ClockISR)
SetInterruptVector &H68, OldAddr
END SUB
SUB ClockOff()
SetInterruptVector &H08, OldAddr
END SUB
SUB SetInterruptVector(BYVAL Intr?, BYVAL NewAddr???) LOCAL
! push ds ; save DS
! mov ah, &H25 ; set AH to 25h (function number)
! mov al, Intr? ; set AL to interrupt vector being redirected
! lds DX, NewAddr???
! int &H21 ; call DOS services
! pop ds ; restore DS
END SUB
SUB GetInterruptVector(BYVAL Intr?, VAddr???) LOCAL PUBLIC
! push ds ; save DS
! push si ; save SI
! mov ah, &H35 ; set AH to 35h (function number)
! mov al, Intr? ; set AL to interrupt vector
! int &H21 ; call DOS services (ES:BX now holds address)
! lds si, VAddr??? ; get a pointer to VSeg??
! mov ds:[si+2], es ; copy ES (segment address) into VSeg??
! mov ds:[si], bx ; copy BX (offset address) into VOff??
! pop si ; restore SI
! pop ds ; restore DS
END SUB
SUB ISR () PRIVATE
DIM IsrStack AS STATIC STRING * 1024 '1k stack (probably too much)
DIM Counter AS STATIC INTEGER
DIM zaehler AS STATIC word
DIM L AS STATIC byte
DIM H AS STATIC byte
DIM ISRCounter AS STATIC word
SaveDS:
! dw 0
SaveSS:
! dw 0
SaveSP:
! dw 0
ClockISR:
! push ax ; save the general registers
! push bx
! push cx
! push dx
! push si
! push di
! push bp
! push ds
! push es
! push bp
! pushf ; save the flags register
! cli ; suspend all maskable interrupts
! mov Word Ptr CS:SaveSS, SS ; save current stack segment
! mov Word Ptr CS:SaveSP, SP ; save current stack pointer
! mov DS, Word Ptr CS:SaveDS ; restore PowerBASIC data segment
' Create a local stack frame
! mov SS, Word Ptr CS:SaveDS ; SS must equal DS for PowerBASIC runtime
! lea BX, IsrStack ; get address of the local stack frame
! add BX, 1024 ; point to the end of the fixed-length string
! mov SP, BX ; set the stack pointer
' ** Your Basic code goes here **
zaehler = 1193180 / Frequenz
L = zaehler
shift right zaehler, 8
H = zaehler
OUT (&H43), &b00110110
OUT (&H40), L
OUT (&H40), H
l = inp(888)
bit toggle l, 1
OUT (888), l
IF Counter = 0 THEN
LOCATE 1, 72, 0
COLOR 14,0
PRINT TIME$;
Counter = 18 '18 ticks per second
END IF
DECR Counter
IF ISRCounter = 0 THEN
! int &H68
ISRCounter = Frequenz / 18.2
ELSE
OUT (&H20), &H20
END IF
DECR ISRCounter
' ** End of Basic code
! mov SP, Word Ptr CS:SaveSP ; restore the original stack segment
! mov SS, Word Ptr CS:SaveSS ; and stack pointer before restoring the registers
! popf ; restore the flags register
! pop bp ; restore the general registers
! pop es
! pop ds
! pop bp
! pop di
! pop si
! pop dx
! pop cx
! pop bx
! pop ax
! sti ; re-enable maskable interrupt processing
! iret ; return from our interrupt handler
END SUB