;***************************************************************
;  STARTUP.ASM  für Betty-TV-Fernbedienung                     *
;  mit Philips LPC2220 und 2 externen Flash-ROMs               *
;                                                              *
;  die CPU kann max. 75 MHz, läuft mit 30 MHz,                 *
;  die Peripherie läuft mit 15 MHz                             *
;  Quarz = 10 MHz                                              *
;***************************************************************

     EXPORT     PixLane1        ; 2560 Bytes
     EXPORT     PixLane2        ; 2560 Bytes
     EXPORT     DirtyPages      ; DWORD
     EXPORT     Errors          ; DWORD
     EXPORT     ErrAddr
     EXPORT     Manifest
     EXPORT     CS_Area0
     EXPORT     CS_Area1
     EXPORT     CS_Area2
     EXPORT     CS_Area3
     EXPORT     LCD_CMD
     EXPORT     LCD_DATA
     EXPORT     Hard_Reset
     EXPORT     Soft_Reset
     EXPORT     EndOfRam
     EXPORT     abort_me


; interne Resourcen:
; ==================
; 64 K RAM                     ab 40000000h..4000FFFFh
; darin:
; am RAM-Ende 2 Grafik-Puffer für das LCD zu je 2560 Bytes
; darunter diverse Householding-Variablen
; darunter die Stacks
; darunter das Ende des frei nutzbaren RAMs


; externe Resourcen:
; Bank 0 = 1 MByte = EN29LV800 ab 80000000h..800FFFFFh
; Bank 1 = LCD (128x160x2)        81000000h CMD
;                                 81000001h Data
; Bank 2 = 1 MByte = EN29LV800 ab 82000000h..810FFFFFh
; Bank 4 = ?

; zum LCD:
; ========
; Die Breite ist 128 (X also 0..127) und die Höhe ist 160, (Y also 0..159).
; Jedes Pixel hat 2 Bit, die in 2 verschiedenen Bytes angeordnet sind, also
; quasi 2 Ebenen, die jeweils 1 Bit für jedes Pixel halten.

; Es gibt einen ladbaren Adresspointer zum Lesen und Schreiben, der mit
; jedem Lese/Schreibvorgang inkrementiert wird. Dieser Adresspointer hat 7 Bit,
; kann also von 0..127 zählen. Das ist die Displaybreite.

; In Y-Richtung gibt es 22 sogenannte Pages, von denen man eine per Kommando
; wählen kann. 22*8=176 Pixels in Y-Richtung, von denen jedoch nur 160 benutzt werden.
; Jede Page ist 8 Pixel hoch (entsprechend den 8 Bit in einem Byte)

; Man kann per Hardware das LCD in X- und in Y-Richtung getrennt spiegeln.
; Im Normalfalle ist die Orientierung so:
; Pixel[0,0], also genz links oben ist in Page 0, dort im Byte 0, dort in Bit 0 auf beiden
; Ebenen.
; Pixel[127,159], also genz unten rechts ist in Page 19, dort im Byte 127, dort in Bit 7
; auf beiden Ebenen.

; hier im Startup-Code sind 2 Puffer (jeweils 128*160/8=2560 Bytes) definiert, die für das
; GDI den zu beschreibenden Bildspeicher darstellen. Änderungen in diesem müssen anschließend
; in das LCD übertragen werden.



; 4 feste Speicherbänke:
CS_Area0 EQU 0x80000000          ; Flashrom 0, 1 MB, mit Betriebssystem
CS_Area1 EQU 0x81000000          ; LCD-Anschluß, nur 2 Bytes, siehe unten
CS_Area2 EQU 0x82000000          ; Flashrom 1, 1 MB, für sonstwas
CS_Area3 EQU 0x83000000          ; unbenutzt?

LCD_CMD  EQU 0x81000000
LCD_DATA EQU 0x81000003

; Bank Konfigurations-Register
BCFG0    EQU 0xFFE00000
BCFG1    EQU 0xFFE00004
BCFG2    EQU 0xFFE00008
BCFG3    EQU 0xFFE0000C


; Bank Setupwerte
; ===============

; Bank 0 = ROM 0x80000000, 16 Bit, 70 ns
b0_IDCY     EQU  0         ; idles 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
b0_WST1     EQU  0         ; readwaits 0..31 +3 = Read-Waitstates in CCLK's
b0_RBLE     EQU  0         ; ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
b0_WST2     EQU  2         ; writewaits (RAM) 0..31 +1 = Write-Waitstates in CCLK's
b0_wprot    EQU  0         ; 1 = Write protect
b0_burst    EQU  0         ; 1 = Burst-ROM
b0_wide     EQU  1         ; 0=byte, 1=word, 2=dword, 3=verboten

; Bank 1 = LCD 0x81000000, 8 Bit, Speed=?
b1_IDCY     EQU  5         ; 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
b1_WST1     EQU  2         ; 0..31 +3 = Read-Waitstates in CCLK's
b1_RBLE     EQU  1         ; ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
b1_WST2     EQU  2         ; 0..31 +1 = Write-Waitstates in CCLK's
b1_wprot    EQU  0         ; 1 = Write protect
b1_burst    EQU  0         ; 1 = Burst-ROM
b1_wide     EQU  0         ; 0=byte, 1=word, 2=dword, 3=verboten

; Bank 2 = ROM 0x82000000, 16 Bit, 70 ns
b2_IDCY     EQU  0         ; 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
b2_WST1     EQU  0         ; 0..31 +3 = Read-Waitstates in CCLK's
b2_RBLE     EQU  0         ; ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
b2_WST2     EQU  2         ; 0..31 +1 = Write-Waitstates in CCLK's
b2_wprot    EQU  0         ; 1 = Write protect
b2_burst    EQU  0         ; 1 = Burst-ROM
b2_wide     EQU  1         ; 0=byte, 1=word, 2=dword, 3=verboten

; Bank 3 unbenutzt
b3_IDCY     EQU  0         ; 0..15    = mindest CCLK's zwischen Rd und WR Zugriffen
b3_WST1     EQU  0         ; 0..31 +3 = Read-Waitstates in CCLK's
b3_RBLE     EQU  0         ; ByteLanesEnable: 0 = keine BLSx, 1 = BLS0..3 werden aktiviert
b3_WST2     EQU  0         ; 0..31 +1 = Write-Waitstates in CCLK's
b3_wprot    EQU  0         ; 1 = Write protect
b3_burst    EQU  0         ; 1 = Burst-ROM
b3_wide     EQU  0         ; 0=byte, 1=word, 2=dword, 3=verboten

ValForBCFG0 EQU  b0_IDCY :OR: (b0_WST1<<5) :OR: (b0_RBLE<<10) :OR: (b0_WST2<<11) :OR: (b0_wprot<<26) :OR: (b0_burst<<27) :OR: (b0_wide<<28)
ValForBCFG1 EQU  b1_IDCY :OR: (b1_WST1<<5) :OR: (b1_RBLE<<10) :OR: (b1_WST2<<11) :OR: (b1_wprot<<26) :OR: (b1_burst<<27) :OR: (b1_wide<<28)
ValForBCFG2 EQU  b2_IDCY :OR: (b2_WST1<<5) :OR: (b2_RBLE<<10) :OR: (b2_WST2<<11) :OR: (b2_wprot<<26) :OR: (b2_burst<<27) :OR: (b2_wide<<28)
ValForBCFG3 EQU  b3_IDCY :OR: (b3_WST1<<5) :OR: (b3_RBLE<<10) :OR: (b3_WST2<<11) :OR: (b3_wprot<<26) :OR: (b3_burst<<27) :OR: (b3_wide<<28)




; RAM und Stacks:
; ===============
Top_Ram           EQU     0x40010000      ; der interne RAM geht von 40000000 bis 4000FFFF
PixLane2          EQU     Top_Ram - 2560  ; LCD-BWSP Ebene 2
PixLane1          EQU     PixLane2 - 2560 ; LCD-BWSP Ebene 1
DirtyPages        EQU     PixLane1 - 4    ; dword für geänderte LCD-Pages

Errors            EQU     DirtyPages - 4  ; Bitfeld zum Merken von Fehlern etc.
ErrAddr           EQU     Errors - 4

; Stack-Sizes
; ===========
; definierte Stacks sind:
; User und System (benutzen beide den User-Stack),
; Supervisor, Abort, Undefined, FIQ, IRQ
;
UNDEF_SS  EQU    48       ; RealMonitor braucht 48
ABORT_SS  EQU    16       ; RealMonitor braucht 16
FIQ_SS    EQU     4
IRQ_SS    EQU   128
SUPVI_SS  EQU   256       ; SWI Stack...
USER_SS   EQU  1024


; die diversen Stacks
Top_Stack    EQU     ErrAddr - 4
Undef_Stack  EQU     Top_Stack
Abort_Stack  EQU     Undef_Stack - UNDEF_SS
FIQ_Stack    EQU     Abort_Stack - ABORT_SS
IRQ_Stack    EQU     FIQ_Stack   - FIQ_SS
Supvi_Stack  EQU     IRQ_Stack   - IRQ_SS
User_Stack   EQU     Supvi_Stack - SUPVI_SS


StartOfRam   EQU     0x40000000
EndOfRam     EQU     User_Stack - USER_SS


; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs

Mode_USER       EQU     0x10
Mode_FIQ        EQU     0x11
Mode_IRQ        EQU     0x12
Mode_SUPERVISOR EQU     0x13
Mode_ABORT      EQU     0x17
Mode_UNDEF      EQU     0x1B
Mode_SYSTEM     EQU     0x1F

I_Bit           EQU     0x80       ; when I bit is set, IRQ is disabled
F_Bit           EQU     0x40       ; when F bit is set, FIQ is disabled


;----------------------------------------------------------------------
; VPBDIV = Taktteiler zwischen AMBA- und Peripherie-Bus (VPB)
; nach Reset: VPB arbeitet auf 1/4 des AMBA-Taktes

VPBDIV          EQU     0xE01FC100  ; VPBDIV Addresse
VPBDIV_Val      EQU     0x00000002  ; 0 = 1/4; 1 = 1:1; 2 = 1/2

; Phase Locked Loop (PLL) definitions
PLL_BASE        EQU     0xE01FC080  ; PLL Base Address
PLLCON_OFS      EQU     0x00        ; PLL Control Offset
PLLCFG_OFS      EQU     0x04        ; PLL Configuration Offset
PLLSTAT_OFS     EQU     0x08        ; PLL Status Offset
PLLFEED_OFS     EQU     0x0C        ; PLL Feed Offset
PLLCON_PLLE     EQU     (1<<0)      ; PLL Enable
PLLCON_PLLC     EQU     (1<<1)      ; PLL Connect
PLLCFG_MSEL     EQU     (0x1F<<0)   ; PLL Multiplier
PLLCFG_PSEL     EQU     (0x03<<5)   ; PLL Divider
PLLSTAT_PLOCK   EQU     (1<<10)     ; PLL Lock Status

; PLLCFG:    7  6  5    4  3  2  1  0
;            - |PSEL | |____MSEL_____|
; Fcpu = Fquarz * (MSEL+1);
; Fquarz ist hier 10 MHz. Wir wollen erstmal 30 MHz
; original Betty: PLLCFG=0x42; macht PSEL=3 und MSEL=2
; also 30 MHz ist 3*10 MHz, also MSEL = 2 (ergibt Faktor 3)
MSEL            EQU    2     ; Fcpu = 10MHz * 3 = 30 MHz

; Der VCO kann von 156 bis 320 MHz schwingen
; VCO / P --> Prozessortakt CCLK, wobei P sich aus PSEL ergibt:
; PSEL=0 --> P=1
; PSEL=1 --> P=2
; PSEL=2 --> P=4
; PSEL=3 --> P=8
; bei 30 MHz liegt nur PSEL=3 im Rahmen des VCO:
; PSEL=3 --> P=8;  CCLK * 8 = 30MHz*8 --> 240 MHz
; (120 MHz wäre zu wenig)
PSEL            EQU    3     ; ergibt :8

PLLCFG_Val      EQU    (PSEL << 5) + MSEL

; Pin-Funktions-Selektions-Register
PINSEL2         EQU     0xE002C014




; Restart-Gründe
; ==============
istKaltstart      EQU   0
istWarmstart      EQU   1
istRaise          EQU   2
istPrefetchErr    EQU   4
istUndefErr       EQU   8
istWrongSwi       EQU  16
istDabtErr        EQU  32
; alles >= 0x80000000 ist Abort



; Area Definition and Entry Point
; Startup Code must be linked first at Address at which it expects to run.

         AREA    Reset, CODE, READONLY
         ENTRY
         PRESERVE8                      ; 8-Byte aligned Stack
         ARM


; Interrupt-Tafel.
; Die folgenden Befehle nebst den zugehörigen Adress-Literalen
; werden vom Startup-Code in den internen RAM kopiert.
; Interrupt-Trick: für IRQ und FIQ wird per Adressier-Trick
; (negative Adresse zeigt auf die zugehörigen Register im AIC)
; die tatsächlichen Handler-Adressen aus dem AIC ausgelesen
; und dorthin verzweigt.
Vectors         LDR     PC,Reset_Addr          ; 00h  Reset, State: Supervisor, I = F = 1
                LDR     PC,Undef_Addr          ; 04h  Undefined Instruction, State = ? I = F = unchanged
                LDR     PC,SWI_Addr            ; 08h  Software Interrupt, Supervisor, I = 1, F = unchanged
                LDR     PC,Prefetch_Addr       ; 0Ch  Abort, I = 1, F = unchanged
                LDR     PC,DataAbort_Addr      ; 10h  Abort, I = 1, F = unchanged
                NOP                            ; 14h  Signature!, reserved
                LDR     PC,[PC, #-0x0FF0]      ; 18h  IRQ, HandlerAddr-->PC
                LDR     PC,FIQ_Addr            ; 1Ch  FIQ


Reset_Addr      DCD     Hard_Reset
Undef_Addr      DCD     Undef_Handler
SWI_Addr        DCD     SWI_Handler
Prefetch_Addr   DCD     PrefetchAbort_Handler
DataAbort_Addr  DCD     DataAbort_Handler
FIQ_Addr        DCD     FIQ_Handler
; Ende der Interrupt-Tafel.
                DCD     0
		DCD     0


;
Manifest        DCB    "Betty Base 0.03 arm",0
                ALIGN


; Einstellwert für PINSEL2: mit CS1 und P3.0=A0
wf_PINSEL2      EQU   0xDE049D4

;----------------------------------------------------------------------
; Hier geht es nach dem Reset los.
Hard_Reset
     LDR     R0, =PLL_BASE          ; Configure and Enable PLL
     MOV     R1, #0xAA
     MOV     R2, #0x55
     MOV     R3, #PLLCFG_Val
     STR     R3, [R0, #PLLCFG_OFS]
     MOV     R3, #PLLCON_PLLE
     STR     R3, [R0, #PLLCON_OFS]
     STR     R1, [R0, #PLLFEED_OFS]
     STR     R2, [R0, #PLLFEED_OFS]

PLL_Loop                            ; Wait until PLL Locked
     LDR     R3, [R0, #PLLSTAT_OFS]
     ANDS    R3, R3, #PLLSTAT_PLOCK
     BEQ     PLL_Loop

; Switch to PLL Clock
     MOV     R3, #(PLLCON_PLLE  :OR: PLLCON_PLLC)
     STR     R3, [R0, #PLLCON_OFS]
     STR     R1, [R0, #PLLFEED_OFS]
     STR     R2, [R0, #PLLFEED_OFS]

; die allernötigsten Einstellungen an PINSEL und Bank-Config
     LDR     R0, =PINSEL2
     LDR     R1, =wf_PINSEL2
     STR     R1, [R0]

     LDR     R1, =ValForBCFG0
     LDR     R0, =BCFG0
     STR     R1, [R0]

     LDR     R1, =ValForBCFG1
     LDR     R0, =BCFG1
     STR     R1, [R0]

     LDR     R1, =ValForBCFG2
     LDR     R0, =BCFG2
     STR     R1, [R0]

     ; Bank 3 ist unbenutzt


; internen RAM ablöschen
     LDR     R0, =StartOfRam
     MOV     R1, #0
     LDR     R2, =Top_Ram
iloop
     STRB    R1, [R0], #1
     CMP     R0, R2                 ; RAM, Stacks und Kommandozeile
     BLT     iloop

; hier werden die Stacks für die versch. Modi aufgesetzt.
     LDR     R0, =Top_Stack
                                    ;  Enter Undefined Instruction Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_UNDEF :OR: I_Bit :OR: F_Bit
     MOV     SP, R0
     SUB     R0, R0, #UNDEF_SS

                                    ;  Enter Abort Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_ABORT :OR: I_Bit :OR: F_Bit
     MOV     SP, R0
     SUB     R0, R0, #ABORT_SS

                                    ;  Enter FIQ Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_FIQ :OR: I_Bit :OR: F_Bit
     MOV     SP, R0
     SUB     R0, R0, #FIQ_SS

                                    ;  Enter IRQ Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_IRQ :OR: I_Bit :OR: F_Bit
     MOV     SP, R0
     SUB     R0, R0, #IRQ_SS

                                    ;  Enter Supervisor Mode and set its Stack Pointer
     MSR     CPSR_c, #Mode_SUPERVISOR :OR: I_Bit :OR: F_Bit
     MOV     SP, R0
     SUB     R0, R0, #SUPVI_SS

                                    ; Fehler beim Kaltstart löschen
     LDR     R0, =Errors
     SUB     R1, R1, R1
     STR     R1, [R0]               ;  Fehlerbits löschen

     B       Restart


; Wiedereintrittspunkt für Soft-Reset
Soft_Reset
     MOV     R1, #istWarmstart

; Error-Bit in R1
Restart
     LDR     R0, =ErrAddr
     STR     LR,[R0]
     LDR     R0, =Errors
     LDR     R2,[R0]
     ORR     R2,R2,R1
     STR     R2,[R0]


; Übergang in 'User'-Mode mit freigegebenem IRQ und FIQ
UserMode
     LDR     R0, =User_Stack
     MSR     CPSR_c, #Mode_USER
     MOV     SP, R0


; ab hier im User-Mode. F- und I-Bits sind hier nicht mehr veränderbar.
; Enter the C code
_main
__main
       EXPORT _main
       EXPORT __main
       EXPORT  __raise
       EXPORT  _sys_exit

       IMPORT  main
       LDR     R0, =main
       BX      R0

_sys_exit
       B        Soft_Reset

;=============================================================================

VICVectAddr    EQU 0xFFFFF030     ; R=Vektoradresse, W=INT löschen


; Interrupt-Behandlungsroutinen.
; ==============================

; Unbekannter Maschinenbefehl. Die CPU hat sich an einem Opcode verschluckt,
; den sie nicht versteht.
Undef_Handler
             MOV     R1, #istUndefErr   ; Fehler-Bit für 'Errors' in R1 laden
             B       Restart

; Prefetch-Abort, wir sind auf eine Adresse gesprungen, die außerhalb aller
; definierten Chipselect-Bereiche liegt, bzw. versuchen einen Maschinenbefehl
; auszuführen, der nicht ladbar ist
PrefetchAbort_Handler
            MOV     R1, #istPrefetchErr ; Fehler-Bit für 'Errors' in R1 laden
            B       Restart


; Data-Abort, wir haben auf eine Adresse außerhalb aller definierten
; Chipselect-Bereiche zugegriffen
; Was machen wir? nen Error setzen und Warmstart...
DataAbort_Handler
            MOV     R1, #istDabtErr
            B       Restart



; Software-Interrupt.
; Achtung! Die aufgerufenen Teile laufen im Supervisor-Modus und dürfen
; ihrerseits KEINE Software-Interrupts verwenden!!
; SWI-Handler a la Keil
T_Bit           EQU     0x20


                EXPORT  SWI_Handler

SWI_Handler
                STMFD   SP!, {R12, LR}         ; Store R12, LR
                MRS     R12, SPSR              ; Get SPSR
                STMFD   SP!, {R8, R12}         ; Store R8, SPSR
                TST     R12, #T_Bit            ; Check Thumb Bit
                LDRNEH  R12, [LR,#-2]          ; Thumb: Load Halfword
                BICNE   R12, R12, #0xFF00      ;        Extract SWI Number
                LDREQ   R12, [LR,#-4]          ; ARM:   Load Word
                BICEQ   R12, R12, #0xFF000000  ;        Extract SWI Number

                LDR     R8, SWI_Count
                CMP     R12, R8
                BHS     SWI_Dead               ; Overflow

                ADR     R8, SWI_Table
                LDR     R12, [R8,R12,LSL #2]   ; Load SWI Function Address
                MOV     LR, PC                 ; Return Address
                BX      R12                    ; Call SWI Function

                LDMFD   SP!, {R8, R12}         ; Load R8, SPSR
                MSR     SPSR_cxsf, R12         ; Set SPSR
                LDMFD   SP!, {R12, PC}^        ; Restore R12 and Return

SWI_Dead
		MOV     R1, #istWrongSwi       ; None Existing SWI
                B       Restart


SWI_Cnt         EQU    (SWI_End-SWI_Table)/4
SWI_Count       DCD     SWI_Cnt

SWI_Table
                DCD  SWI_Dead                   ; 0   die ersten werden freigehalten
                DCD  SWI_Dead                   ; 1   wegen evtl. RTOS
                DCD  SWI_Dead                   ; 2
                DCD  SWI_Dead                   ; 3
                DCD  SWI_Dead                   ; 4
                DCD  SWI_Dead                   ; 5
                DCD  SWI_Dead                   ; 6
                DCD  SWI_Dead                   ; 7

; ab hier OS-Funktionen
                DCD  Soft_Reset                 ; 8 --> Restart

; Importe aus dem GDI
                IMPORT    FillLanes
                DCD       FillLanes             ; 9

                IMPORT    LichtAus
                DCD       LichtAus              ; 10

                IMPORT    LichtEin
                DCD       LichtEin              ; 11

                IMPORT    FlipDisplay
                DCD       FlipDisplay           ; 12

                IMPORT    ScrBlt
                DCD       ScrBlt                ; 13

                IMPORT    CgPixel_at
                DCD       CgPixel_at            ; 14

                IMPORT    MoveTo
                DCD       MoveTo                ; 15

                IMPORT    LineTo
                DCD       LineTo                ; 16

                IMPORT    CgFillRect
                DCD       CgFillRect            ; 17

                IMPORT    CgCh_at
                DCD       CgCh_at               ; 18

                IMPORT    CgStr_at
                DCD       CgStr_at              ; 19

                IMPORT    StringWidth
                DCD       StringWidth           ; 20

                IMPORT    Get_dY
                DCD       Get_dY                ; 21

                IMPORT    Get_Ascent
                DCD       Get_Ascent            ; 22

                IMPORT    Get_Descent
                DCD       Get_Descent           ; 23

                IMPORT    Get_dX
                DCD       Get_dX                ; 24

                IMPORT    Get_Font
                DCD       Get_Font              ; 25

                IMPORT    DispatchEvent
                DCD       DispatchEvent         ; 26

                IMPORT    LocalToScreen
                DCD       LocalToScreen         ; 27

                IMPORT    Umrande
                DCD       Umrande               ; 28

                IMPORT    PanelKeyHandler
                DCD       PanelKeyHandler       ; 29

                IMPORT    PanelEventHandler
                DCD       PanelEventHandler     ; 30

                IMPORT    PanelDrawProc
                DCD       PanelDrawProc         ; 31

                IMPORT    ButtonDrawProc
                DCD       ButtonDrawProc        ; 32


                IMPORT    Messagebox
                DCD       Messagebox            ; 33

                IMPORT    GetSetMenu
                DCD       GetSetMenu            ; 34

                IMPORT    V24_Init
                DCD       V24_Init              ; 35

                IMPORT    V24_Txfree
                DCD       V24_Txfree            ; 36

                IMPORT    V24_CharOut
                DCD       V24_CharOut           ; 37

                IMPORT    V24_StrOut
                DCD       V24_StrOut            ; 38

                IMPORT    V24_CRLF
                DCD       V24_CRLF		; 39

                IMPORT    V24_CharAvail
                DCD       V24_CharAvail		; 40

                IMPORT    V24_CharIn
                DCD       V24_CharIn		; 41

                IMPORT    IsKeyAvailable
                DCD       IsKeyAvailable	; 42

                IMPORT    IsKeyPressed
                DCD       IsKeyPressed		; 43

                IMPORT    GetKey
                DCD       GetKey		; 44

                IMPORT    TranslateKeynum
                DCD       TranslateKeynum	; 45

                IMPORT    TastenZustand
                DCD       TastenZustand		; 46

                IMPORT    CgPicture_at
                DCD       CgPicture_at          ; 47

                IMPORT    CgCircle_at
                DCD       CgCircle_at           ; 48

                IMPORT    Ich_selected
                DCD       Ich_selected          ; 49

                IMPORT    StringCopy
                DCD       StringCopy            ; 50

                IMPORT    StringAdd
                DCD       StringAdd             ; 51

                IMPORT    Add_Delayed_Event
                DCD       Add_Delayed_Event     ; 52


SWI_End




; NixTun-Handler für Interrupts
                EXPORT  IRQ_HandlerDummy
IRQ_HandlerDummy
                STMFD   SP!,{R0}         ; 'PUSH' R0
                LDR     R0, =VICVectAddr ; Int löschen
		STR     R0, [R0]
		LDMFD   SP!,{R0}         ; 'POP' R0
                SUBS    PC,LR,#4



; Handler für den FIQ:
; Für den FIQ hat es eine Bank mit separaten Registern R8 ... R14
; wenn man nur den separaten Registersatz benutzt,
; braucht man keine Register auf dem Stack zu retten
; dieser Handler macht erstmal nix.

FIQ_Handler

                LDR     R12, =VICVectAddr ; Int löschen
		STR     R11, [R12]

fiq_done	SUBS    PC,LR,#4          ; return from FIQ
		LTORG


; nur zum Export. Wird von mir nicht aktiv benutzt.
__raise
       MOV      R1, #istRaise
       B        Restart

abort_me
       ORR      R1,R0,#0x80000000      ; Param nach R1
       B        Restart

       LTORG

       END
