Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

PB/DOS: Calling BASIC code in an ISR

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PB/DOS: Calling BASIC code in an ISR

    Code:
    $DIM ALL
    $COMPILE UNIT
     
    DECLARE FUNCTION SetOnExit(BYVAL ProcedurePointer AS DWORD) AS INTEGER
     
    SUB ISR() PRIVATE
     
      DIM IsrStack AS STATIC STRING * 2048
     
    IsrChain:
      ! db 0
     
    OldAddress:
      ! dw 0
      ! dw 0
     
    IsrAddress:
      ! dw 0
      ! dw 0
     
    SaveDS:
      ! dw 0
     
    SaveSS:
      ! dw 0
     
    SaveSP:
      ! dw 0
     
    IsrHandler:
      ! pushf
      ! cmp  Byte Ptr CS: IsrChain, 1
      ! jne  NoPreChain
      ! call DWord CS:OldAddress
      ! jmp  Short SaveRegisters
    NoPreChain:
      ! popf
    SaveRegisters:
      ! push bp
      ! mov  bp, sp
      ! pushf                         ; save the flags register
      ! push es
      ! push ds
      ! push di
      ! push si
      ! push dx
      ! push cx
      ! push bx
      ! push ax                       ; save the general registers
      ! mov  bp, sp                   ; set up the stack pointer
      ! cli                           ; suspend all maskable interrupts
      ! cld                           ; clear the direction flag
     
      ! 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, 2048                  ; point to the end of the fixed-length string
      ! mov SP, BX                    ; set the stack pointer
     
      ' Call the Basic code
      ! mov  BX, CS: SaveSS           ; segment of original stack
      ! push BX                       ;
      ! mov  BX, BP                   ; pointer to the register stack frame
      ! push BX                       ;
      ! call Dword Ptr CS:IsrAddress
     
      ' Restore the stack
      ! mov SP, Word Ptr CS:SaveSP ; restore the original stack segment
      ! mov SS, Word Ptr CS:SaveSS ;  and stack pointer before restoring the registers
     
      ! pop ax
      ! pop bx
      ! pop cx
      ! pop dx
      ! pop si
      ! pop di
      ! pop ds
      ! pop es
      ! popf               ; restore the flags register
      ! pop bp
     
      ! cmp  Byte Ptr CS: IsrChain, 2
      ! jne  IsrDone
      ! jmp  DWord Ptr CS: OldAddress
     
    IsrDone:
      ! sti                ; re-enable maskable interrupt processing
      ! iret               ; return from our interrupt handler
     
    END SUB
     
    SUB SetInterruptVector(BYVAL Intr AS BYTE, BYVAL NewAddr AS DWORD) PRIVATE
      ! 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 AS BYTE, VAddr AS DWORD) PRIVATE
      ! 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 IsrEnd() PUBLIC
     
      DIM OldAddr AS SHARED DWORD
      DIM IntSave AS SHARED WORD
     
      IF IntSave AND OldAddr THEN
        SetInterruptVector IntSave, OldAddr
        IntSave = 0
      END IF
     
    END SUB
     
    SUB IsrBegin(BYVAL Intr AS WORD, BYVAL Address AS DWORD, BYVAL fChain AS INTEGER) PUBLIC
     
      DIM OldAddr  AS SHARED DWORD
      DIM IntSave  AS SHARED WORD
      DIM SaveExit AS STATIC INTEGER
     
      IF IntSave THEN
        IsrEnd
      END IF
     
      IF SaveExit = 0 THEN
        SetOnExit CODEPTR32(IsrEnd)
        SaveExit = 1
      END IF
     
      GetInterruptVector Intr, OldAddr
     
      ! mov  Word Ptr CS: SaveDS, DS   ;store PowerBASIC Data segment
      ! les  DI, Address
      ! mov  Word Ptr CS: IsrAddress, DI
      ! mov  Word Ptr CS: IsrAddress[2], ES
      ! les  DI, DS: OldAddr
      ! mov  Word Ptr CS: OldAddress, DI
      ! mov  Word Ptr CS: OldAddress[2], ES
      ! mov  AX, fChain
      ! mov  Byte Ptr CS: IsrChain, AL
     
      SetInterruptVector Intr, CODEPTR32(IsrHandler)
     
      IntSave = Intr
     
    END SUB

    -------------
    PowerBASIC Support
    mailto:[email protected][email protected]</A>

    Home of the BASIC Gurus
    www.basicguru.com
Working...
X