OpenCores
URL https://opencores.org/ocsvn/rtf65002/rtf65002/trunk

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [bootrom.asm] - Diff between revs 18 and 26

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 18 Rev 26
Line 33... Line 33...
CTRLS   EQU     0x13
CTRLS   EQU     0x13
CTRLX   EQU     0x18
CTRLX   EQU     0x18
XON             EQU     0x11
XON             EQU     0x11
XOFF    EQU     0x13
XOFF    EQU     0x13
 
 
 
; error codes
 
E_Ok            =               0x00
 
E_Arg           =               0x01
 
E_BadMbx        =               0x04
 
E_QueFull       =               0x05
 
E_NoThread      =               0x06
 
E_NotAlloc      =               0x09
 
E_NoMsg         =               0x0b
 
E_Timeout       =               0x10
 
E_BadAlarm      =               0x11
 
E_NotOwner      =               0x12
 
; resource errors
 
E_NoMoreMbx     =               0x40
 
E_NoMoreMsgBlks =       0x41
 
E_NoMoreAlarmBlks       =0x44
 
E_NoMoreTCBs    =       0x45
 
 
 
; task status
 
TS_NONE     =0
 
TS_TIMEOUT      =1
 
TS_WAITMSG      =2
 
TS_PREEMP       =4
 
TS_RUNNING      =8
 
TS_READY        =16
 
TS_WAITFOCUS    = 32
 
 
 
 
 
; message queuing strategy
 
MQS_UNLIMITED   =0      ; unlimited queue size
 
MQS_NEWEST              =1      ; buffer queue size newest messages
 
MQS_OLDEST              =2      ; buffer queue size oldest messages
 
 
 
 
TEXTSCR         EQU             0xFFD00000
TEXTSCR         EQU             0xFFD00000
COLORSCR        EQU             0xFFD10000
COLORSCR        EQU             0xFFD10000
TEXTREG         EQU             0xFFDA0000
TEXTREG         EQU             0xFFDA0000
TEXT_COLS       EQU             0x0
TEXT_COLS       EQU             0x0
TEXT_ROWS       EQU             0x1
TEXT_ROWS       EQU             0x1
TEXT_CURPOS     EQU             11
TEXT_CURPOS     EQU             11
KEYBD           EQU             0xFFDC0000
KEYBD           EQU             0xFFDC0000
KEYBDCLR        EQU             0xFFDC0001
KEYBDCLR        EQU             0xFFDC0001
PIC                     EQU             0xFFDC0FF0
PIC                     EQU             0xFFDC0FF0
PIC_IE          EQU             0xFFDC0FF1
PIC_IE          EQU             0xFFDC0FF1
 
TASK_SELECT     EQU             0xFFDD0008
 
RQ_SEMA         EQU             0xFFDB0000
 
TO_SEMA         EQU             0xFFDB0010
 
SERIAL_SEMA     EQU             0xFFDB0020
 
KEYBD_SEMA      EQU             0xFFDB0030
 
IOF_LIST_SEMA   EQU     0xFFDB0040
 
MBX_SEMA        EQU             0xFFDB0050
 
 
SPIMASTER       EQU             0xFFDC0500
SPIMASTER       EQU             0xFFDC0500
SPI_MASTER_VERSION_REG  EQU     0x00
SPI_MASTER_VERSION_REG  EQU     0x00
SPI_MASTER_CONTROL_REG  EQU     0x01
SPI_MASTER_CONTROL_REG  EQU     0x01
SPI_TRANS_TYPE_REG      EQU             0x02
SPI_TRANS_TYPE_REG      EQU             0x02
Line 75... Line 115...
SPI_READ_NO_ERROR       EQU             0x00
SPI_READ_NO_ERROR       EQU             0x00
SPI_WRITE_NO_ERROR      EQU             0x00
SPI_WRITE_NO_ERROR      EQU             0x00
RW_READ_SD_BLOCK        EQU             0x02
RW_READ_SD_BLOCK        EQU             0x02
RW_WRITE_SD_BLOCK       EQU             0x03
RW_WRITE_SD_BLOCK       EQU             0x03
 
 
BITMAPSCR       EQU             0x04000000
UART            EQU             0xFFDC0A00
SECTOR_BUF      EQU             0x05FFEC00
UART_LS         EQU             0xFFDC0A01
 
UART_MS         EQU             0xFFDC0A02
 
UART_IS         EQU             0xFFDC0A03
 
UART_IE         EQU             0xFFDC0A04
 
UART_MC         EQU             0xFFDC0A06
 
UART_CM1        EQU             0xFFDC0A09
 
UART_CM2        EQU             0xFFDC0A0A
 
UART_CM3        EQU             0xFFDC0A0B
 
txempty         EQU             0x40
 
rxfull          EQU             0x01
 
 
 
CONFIGREC       EQU             0xFFDCFFF0
 
CR_CLOCK        EQU             0xFFDCFFF4
 
GACCEL          EQU             0xFFDAE000
 
 
 
ETHMAC          EQU             0xFFDC2000
 
ETH_MODER               EQU             0x00
 
ETH_INT_SOURCE  EQU             0x01
 
ETH_INT_MASK    EQU             0x02
 
ETH_IPGT                EQU             0x03
 
ETH_IPGR1               EQU             0x04
 
ETH_IPGR2               EQU             0x05
 
ETH_PACKETLEN   EQU             0x06
 
ETH_COLLCONF    EQU             0x07
 
ETH_TX_BD_NUM   EQU             0x08
 
ETH_CTRLMODER   EQU             0x09
 
ETH_MIIMODER    EQU             0x0A
 
ETH_MIICOMMAND  EQU             0x0B
 
ETH_MIIADDRESS  EQU             0x0C
 
ETH_MIITX_DATA  EQU             0x0D
 
ETH_MIIRX_DATA  EQU             0x0E
 
ETH_MIISTATUS   EQU             0x0F
 
ETH_MAC_ADDR0   EQU             0x10
 
ETH_MAC_ADDR1   EQU             0x11
 
ETH_HASH0_ADDR  EQU             0x12
 
ETH_HASH1_ADDR  EQU             0x13
 
ETH_TXCTRL              EQU             0x14
 
 
 
SPRITEREGS      EQU             0xFFDAD000
 
SPRRAM          EQU             0xFFD80000
 
 
 
THRD_AREA       EQU             0x04000000      ; threading area 0x04000000-0x40FFFFF
 
BITMAPSCR       EQU             0x04100000
 
SECTOR_BUF      EQU             0x05FBEC00
 
BIOS_STACKS     EQU             0x05FC0000      ; room for 256 1kW stacks
 
BIOS_SCREENS    EQU     0x05C00000      ; 0x05C00000 to 0x05DFFFFF
 
 
BYTE_SECTOR_BUF EQU     SECTOR_BUF<<2
BYTE_SECTOR_BUF EQU     SECTOR_BUF<<2
PROG_LOAD_AREA  EQU             0x4080000<<2
PROG_LOAD_AREA  EQU             0x4180000<<2
 
INPUT_FOCUS             EQU             0x05FBE000
 
OUTPUT_FOCUS    EQU             0x05FBE001
 
 
 
eth_rx_buffer   EQU             0x5F80000
 
eth_tx_buffer   EQU             0x5F84000
 
 
 
; Mailboxes, room for 2048
 
MBX_LINK        EQU             0x05F90000
 
MBX_TQ_HEAD     EQU             0x05F90800
 
MBX_TQ_TAIL     EQU             0x05F91000
 
MBX_MQ_HEAD     EQU             0x05F91800
 
MBX_MQ_TAIL     EQU             0x05F92000
 
MBX_TQ_COUNT    EQU     0x05F92800
 
MBX_MQ_SIZE     EQU             0x05F93000
 
MBX_MQ_COUNT    EQU     0x05F93800
 
MBX_MQ_MISSED   EQU     0x05F94000
 
MBX_OWNER               EQU     0x05F94800
 
MBX_MQ_STRATEGY EQU     0x05F95000
 
MBX_RESV                EQU     0x05F95800
 
 
 
; Messages, room for 8kW (8,192) messages
 
MSG_LINK        EQU             0x05FA0000
 
MSG_D1          EQU             0x05FA2000
 
MSG_D2          EQU             0x05FA4000
 
MSG_TYPE        EQU             0x05FA6000
 
 
 
; Task control blocks, room for 256 tasks
 
TCB_NxtRdy              EQU             0x05FBE100      ; next task on ready / timeout list
 
TCB_PrvRdy              EQU             0x05FBE200      ; previous task on ready / timeout list
 
TCB_NxtTCB              EQU             0x05FBE300
 
TCB_Timeout             EQU             0x05FBE400
 
TCB_Priority    EQU             0x05FBE500
 
TCB_MSGPTR_D1   EQU             0x05FBE600
 
TCB_MSGPTR_D2   EQU             0x05FBE700
 
TCB_hJCB                EQU             0x05FBE800
 
TCB_Status              EQU             0x05FBE900
 
TCB_SP8Save             EQU             0x500           ; TCB_SP8Save area $500 to $5FF
 
TCB_SPSave              EQU             0x600           ; TCB_SPSave area $600 to $6FF
 
TCB_CursorRow   EQU             0x05FBD100
 
TCB_CursorCol   EQU             0x05FBD200
 
TCB_hWaitMbx    EQU             0x05FBD300      ; handle of mailbox task is waiting at
 
TCB_mbq_next    EQU             0x05FBD400      ; mailbox queue next
 
TCB_mbq_prev    EQU             0x05FBD500      ; mailbox queue previous
 
 
 
KeybdHead       EQU             0x05FBEA00
 
KeybdTail       EQU             0x05FBEB00
 
KeybdEcho       EQU             0x05FBEC00
 
KeybdBad        EQU             0x05FBED00
 
KeybdAck        EQU             0x05FBEE00
 
KeybdLocks      EQU             0x05FBEF00
 
KeybdBuffer     EQU             0x05FBF000      ; buffer is 16 chars
 
 
macro m_lsr8
IOFocusList     EQU             0x05FBD000
lsr
 
lsr
 
lsr
 
lsr
 
lsr
 
lsr
 
lsr
 
lsr
 
endm
 
 
 
macro m_asl8
 
asl
 
asl
 
asl
 
asl
 
asl
 
asl
 
asl
 
asl
 
endm
 
 
 
; BIOS vars at the top of the 8kB scratch memory
; BIOS vars at the top of the 8kB scratch memory
;
;
 
NmiBase         EQU             0xDC
 
IrqBase         EQU             0xDF
 
 
 
 
 
 
 
 
 
; TinyBasic AREA = 0x700 to 0x77F
 
 
 
HeadRdy0        EQU             0x780
 
HeadRdy1        EQU             HeadRdy0+1
 
HeadRdy2        EQU             HeadRdy1+1
 
HeadRdy3        EQU             HeadRdy2+1
 
HeadRdy4        EQU             HeadRdy3+1
 
TailRdy0        EQU             HeadRdy4+1
 
TailRdy1        EQU             TailRdy0+1
 
TailRdy2        EQU             TailRdy1+1
 
TailRdy3        EQU             TailRdy2+1
 
TailRdy4        EQU             TailRdy3+1
 
FreeTCB         EQU             TailRdy4+1
 
TimeoutList     EQU             FreeTCB+1
 
RunningTCB              EQU             TimeoutList+1
 
FreeMbx         EQU             RunningTCB + 1
 
nMailbox        EQU             FreeMbx + 1
 
FreeMsg         EQU             nMailbox + 1
 
nMsgBlk         EQU             FreeMsg + 1
 
 
 
IrqSource       EQU             0x798
 
 
JMPTMP          EQU             0x7A0
JMPTMP          EQU             0x7A0
SP8Save         EQU             0x7AE
 
SRSave          EQU             0x7AF
SRSave          EQU             0x7AF
R1Save          EQU             0x7B0
R1Save          EQU             0x7B0
R2Save          EQU             0x7B1
R2Save          EQU             0x7B1
R3Save          EQU             0x7B2
R3Save          EQU             0x7B2
R4Save          EQU             0x7B3
R4Save          EQU             0x7B3
Line 122... Line 267...
R11Save         EQU             0x7BA
R11Save         EQU             0x7BA
R12Save         EQU             0x7BB
R12Save         EQU             0x7BB
R13Save         EQU             0x7BC
R13Save         EQU             0x7BC
R14Save         EQU             0x7BD
R14Save         EQU             0x7BD
R15Save         EQU             0x7BE
R15Save         EQU             0x7BE
SPSave          EQU             0x7BF
 
 
 
CharColor       EQU             0x7C0
CharColor       EQU             0x7C0
ScreenColor     EQU             0x7C1
ScreenColor     EQU             0x7C1
CursorRow       EQU             0x7C2
CursorRow       EQU             0x7C2
CursorCol       EQU             0x7C3
CursorCol       EQU             0x7C3
CursorFlash     EQU             0x7C4
CursorFlash     EQU             0x7C4
Milliseconds    EQU             0x7C5
Milliseconds    EQU             0x7C5
IRQFlag         EQU             0x7C6
IRQFlag         EQU             0x7C6
 
RdyQueTick      EQU             0x7C7
KeybdHead       EQU             0x7D0
eth_unique_id   EQU             0x7C8
KeybdTail       EQU             0x7D1
LineColor       EQU             0x7C9
KeybdEcho       EQU             0x7D2
 
KeybdBad        EQU             0x7D3
Uart_rxfifo             EQU             0x05FBC000
KeybdAck        EQU             0x7D4
Uart_rxhead             EQU             0x7D0
KeybdBuffer     EQU             0x7D5   ; buffer is 16 chars
Uart_rxtail             EQU             0x7D1
KeybdLocks      EQU             0x7E5
Uart_ms                 EQU             0x7D2
 
Uart_rxrts              EQU             0x7D3
 
Uart_rxdtr              EQU             0x7D4
 
Uart_rxxon              EQU             0x7D5
 
Uart_rxflow             EQU             0x7D6
 
Uart_fon                EQU             0x7D7
 
Uart_foff               EQU             0x7D8
 
Uart_txrts              EQU             0x7D9
 
Uart_txdtr              EQU             0x7DA
 
Uart_txxon              EQU             0x7DB
 
Uart_txxonoff   EQU             0x7DC
 
 
startSector     EQU             0x7F0
startSector     EQU             0x7F0
 
 
 
 
        cpu             rtf65002
        cpu             rtf65002
        code
        code
 
 
 
message "jump table"
        ; jump table of popular BIOS routines
        ; jump table of popular BIOS routines
        org             $FFFFC000
        org             $FFFFC000
        dw      DisplayChar
        dw      DisplayChar
        dw      KeybdCheckForKeyDirect
        dw      KeybdCheckForKeyDirect
        dw      KeybdGetCharDirect
        dw      KeybdGetCharDirect
 
        dw      KeybdGetChar
 
        dw      KeybdCheckForKey
 
        dw      RequestIOFocus
 
        dw      ReleaseIOFocus
 
        dw      ClearScreen
 
        dw      HomeCursor
 
        dw      ExitTask
 
        dw      SetKeyboardEcho
 
 
        org             $FFFFC200               ; leave room for 128 vectors
        org             $FFFFC200               ; leave room for 128 vectors
 
message "cold start point"
KeybdRST
KeybdRST
start
start
        sei                                             ; disable interrupts
        sei                                             ; disable interrupts
        cld                                             ; disable decimal mode
        cld                                             ; disable decimal mode
        ldx             #$05FFFFF8              ; setup stack pointer top of memory
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer top of memory
        txs
        txs
        trs             r0,dp                   ; set direct page register
        trs             r0,dp                   ; set direct page register
        trs             r0,dp8                  ; and 8 bit mode direct page
        trs             r0,dp8                  ; and 8 bit mode direct page
        trs             r0,abs8                 ; and 8 bit mode absolute address offset
        trs             r0,abs8                 ; and 8 bit mode absolute address offset
 
 
        ; setup interrupt vectors
        ; setup interrupt vectors
        ldx             #$05FFF001              ; interrupt vector table from $5FFF000 to $5FFF1FF
        ldx             #$05FB0001              ; interrupt vector table from $5FB0000 to $5FB01FF
                                                        ; also sets nmoi policy (native mode on interrupt)
                                                        ; also sets nmoi policy (native mode on interrupt)
        trs             r2,vbr
        trs             r2,vbr
        dex
        dex
        lda             #brk_rout
        lda             #brk_rout
        sta             (x)
        sta             (x)
Line 180... Line 344...
        sta             448+2,x
        sta             448+2,x
        lda             #p100Hz
        lda             #p100Hz
        sta             448+3,x
        sta             448+3,x
        lda             #KeybdIRQ
        lda             #KeybdIRQ
        sta             448+15,x
        sta             448+15,x
 
        lda             #SerialIRQ
 
        sta             448+8,x
 
        lda             #bus_err_rout
 
        sta             508,x
 
        sta             509,x
 
 
 
        emm
 
        cpu             W65C02
 
        ldx             #$FF                    ; set 8 bit stack pointer
 
        txs
 
        nat
 
        cpu             rtf65002
 
 
 
        ldx             #0
 
        stz             IrqBase                 ; support for EhBASIC's interrupt mechanism
 
        stz             NmiBase
 
        ; Initialize the BIOS task
 
        lda             #TS_RUNNING|TS_READY
 
        sta             TCB_Status
 
        stz             TCB_Priority    ; set task#0 priority
 
        lda             #-1
 
        sta             TCB_NxtRdy              ; set task#0 next and previous fields
 
        sta             TCB_PrvRdy
 
        stz             TCB_Timeout
 
        stz             RunningTCB              ; the BIOS task is the running task
 
 
 
        sta             TimeoutList             ; no entries in timeout list
 
        stz             HeadRdy0                ; task zero (the BIOS task) is always present
 
        sta             HeadRdy1
 
        sta             HeadRdy2
 
        sta             HeadRdy3
 
        sta             HeadRdy4
 
        stz             TailRdy0
 
        sta             TailRdy1
 
        sta             TailRdy2
 
        sta             TailRdy3
 
        sta             TailRdy4
 
 
 
        ; Initialize IO Focus List
 
        ;
 
        ldx             #0
 
st5:
 
        stz             IOFocusList,x
 
        inx
 
        cpx             #8
 
        bne             st5
 
 
 
        ; Initialize free message list
 
        lda             #8192
 
        sta             nMsgBlk
 
        stz             FreeMsg
 
        ldx             #0
 
        lda             #1
 
st4:
 
        sta             MSG_LINK,x
 
        ina
 
        inx
 
        cpx             #8192
 
        bne             st4
 
        lda             #-1
 
        sta             MBX_LINK+8191
 
 
 
        ; Initialize free mailbox list
 
        lda             #2048
 
        sta             nMailbox
 
 
 
        stz             FreeMbx
 
        ldx             #0
 
        lda             #1
 
st3:
 
        sta             MBX_LINK,x
 
        ina
 
        inx
 
        cpx             #2048
 
        bne             st3
 
        lda             #-1
 
        sta             MBX_LINK+2047
 
 
 
        ; Initialize the FreeTCB list
 
        lda             #1                              ; the next available TCB
 
        sta             FreeTCB
 
        ldx             #1
 
        lda             #2
 
st2:
 
        sta             TCB_NxtTCB,x
 
        ina
 
        inx
 
        cpx             #256
 
        bne             st2
 
        lda             #-1
 
        sta             TCB_NxtTCB+255
 
 
 
        stz             INPUT_FOCUS
 
        stz             OUTPUT_FOCUS
 
        lda             #1
 
        sta             MBX_SEMA
 
        sta             IOF_LIST_SEMA
 
        sta             RQ_SEMA                 ; set ready queue semaphore
 
        sta             TO_SEMA                 ; set timeout list semaphore
 
        jsr             RequestIOFocus          ; Get the IO focus for the BIOS (must be after semaphore is initialized)
 
        lda             #$CE                    ; CE =blue on blue FB = grey on grey
 
        sta             ScreenColor
 
        sta             CharColor
 
        sta             CursorFlash
 
        jsr             ClearScreen
 
        jsr             ClearBmpScreen
 
        lda             #$3FFF                  ; turn on sprites
 
        sta             SPRITEREGS+120
 
        jsr             RandomizeSprram
 
        jsr             HomeCursor
 
        lda             #msgStart
 
        jsr             DisplayStringB
 
        jsr             KeybdInit
 
        lda             #1
 
        sta             KeybdEcho
 
        ; 19200 * 16
 
        ;-------------
 
        ; 25MHz / 2^32
 
        lda             #$03254E6E              ; constant for 19,200 baud at 25MHz
 
;       jsr             SerialInit
 
        lda             #4
 
        ldx             #0
 
        ldy             #IdleTask
 
        jsr             StartTask
 
        jsr             PICInit
 
        cli                                             ; enable interrupts
 
        jmp             Monitor
 
st1
 
        jsr             KeybdGetCharDirect
 
        bra             st1
 
        stp
 
        bra             start
 
 
 
msgStart
 
        db              "RTF65002 system starting.",$0d,$0a,00
 
 
 
;----------------------------------------------------------
 
; Initialize programmable interrupt controller (PIC)
 
;  0 = nmi (parity error)
 
;  1 = keyboard reset
 
;  2 = 1000Hz pulse (context switcher)
 
;  3 = 100Hz pulse (cursor flash)
 
;  4 = ethmac
 
;  8 = uart
 
; 13 = raster interrupt
 
; 15 = keyboard char
 
;----------------------------------------------------------
 
message "PICInit"
 
PICInit:
 
        ; enable: raster irq,
 
        lda             #$810F                  ; enable nmi,kbd_rst,and kbd_irq
 
        ; A10F enable serial IRQ
 
        sta             PIC_IE
 
PICret:
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
;------------------------------------------------------------------------------
 
message "DumpTaskList"
 
DumpTaskList:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
        lda             #msgTaskList
 
        jsr             DisplayStringB
 
        ldy             #0
 
        php
 
        sei
 
dtl2:
 
        lda             HeadRdy0,y
 
        ld              r4,r1
 
        bmi             dtl1
 
dtl3:
 
        ldx             #3
 
        tya
 
        jsr             PRTNUM
 
        lda             #' '
 
        jsr             DisplayChar
 
        ld              r1,r4
 
        ldx             #3
 
        jsr             PRTNUM
 
        lda             #' '
 
        jsr             DisplayChar
 
        jsr             DisplayChar
 
        jsr             DisplayChar
 
        ld              r1,r4
 
        lda             TCB_Status,r1
 
        jsr             DisplayByte
 
        lda             #' '
 
        jsr             DisplayChar
 
        ldx             #3
 
        lda             TCB_PrvRdy,r4
 
        jsr             PRTNUM
 
        lda             #' '
 
        jsr             DisplayChar
 
        ldx             #3
 
        lda             TCB_NxtRdy,r4
 
        jsr             PRTNUM
 
        lda             #' '
 
        jsr             DisplayChar
 
        lda             TCB_Timeout,r4
 
        jsr             DisplayWord
 
        jsr             CRLF
 
        ld              r4,TCB_NxtRdy,r4
 
        bpl             dtl3
 
dtl1:
 
        iny
 
        cpy             #5
 
        bne             dtl2
 
        plp
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rts
 
 
 
msgTaskList:
 
        db      CR,LF,"Pri Task Stat Prv Nxt Timeout",CR,LF,0
 
 
 
;------------------------------------------------------------------------------
 
; IdleTask is a low priority task that is always running. It runs when there
 
; is nothing else to run.
 
;------------------------------------------------------------------------------
 
IdleTask:
 
        inc             TEXTSCR+167             ; increment IDLE active flag
 
        cli                                             ; enable interrupts
 
        wai                                             ; wait for one to happen
 
        bra             IdleTask
 
 
 
;------------------------------------------------------------------------------
 
; r1 = task priority
 
; r2 = start flags
 
; r3 = start address
 
;------------------------------------------------------------------------------
 
message "StartTask"
 
StartTask:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        push    r8
 
        tsr             sp,r4                           ; save off current stack pointer
 
        ld              r6,r1                           ; r6 = task priority
 
        ld              r8,r2
 
 
 
        ; get a free TCB
 
        ;
 
        sei
 
        lda             FreeTCB                         ; get free tcb list pointer
 
        bmi             stask1
 
        tax
 
        lda             TCB_NxtTCB,x
 
        sta             FreeTCB                         ; update the FreeTCB list pointer
 
        cli
 
        txa
 
 
 
        ; setup the stack for the task
 
        ld              r7,r2
 
        asl             r2,r2,#10                       ; 1kW stack per task
 
        add             r2,r2,#BIOS_STACKS+0x3ff        ; add in stack base
 
        txs
 
        ldx             #$FF
 
        stx             TCB_SP8Save,r7
 
        st              r6,TCB_Priority,r7
 
        stz             TCB_Status,r7
 
        stz             TCB_Timeout,r7
 
 
 
        ; setup the initial stack image for the task
 
        ; Cause a return to the ExitTask routine when the task does a
 
        ; final rts.
 
        ; fake an IRQ call by stacking the return address and processor
 
        ; flags on the stack
 
        ldx             #ExitTask                       ; save the address of the task exit routine
 
        phx
 
        phy                                                     ; save start address on stack
 
        push    r8                                      ; save processor status reg on stack
 
 
 
        ; now fake pushing the register set onto the stack. Registers start up
 
        ; in an undefined state.
 
        sub             sp,#15                          ; 15 registers
 
        tsx
 
        stx             TCB_SPSave,r7
 
 
 
        ; now restore the current stack pointer
 
        trs             r4,sp
 
 
 
        ; Insert the task into the ready list
 
        jsr             AddTaskToReadyList
 
stask2:
 
        pop             r8
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rts
 
stask1:
 
        cli
 
        lda             #msgNoTCBs
 
        jsr             DisplayStringB
 
        bra             stask2
 
 
 
msgNoTCBs:
 
        db              "No more task control blocks available.",CR,LF,0
 
 
 
;------------------------------------------------------------------------------
 
; This routine is called when the task exits with an rts instruction. OR
 
; it may be invoked with a JMP ExitTask.
 
;------------------------------------------------------------------------------
 
message "ExitTask"
 
ExitTask:
 
        sei
 
        ; release any aquired resources
 
        ; - mailboxes
 
        ; - messages
 
        lda             RunningTCB
 
        jsr             RemoveTaskFromReadyList
 
        stz             TCB_Status,r1                           ; set task status to TS_NONE
 
        ldx             FreeTCB
 
        stx             TCB_NxtTCB,r1
 
        sta             FreeTCB
 
        jmp             SelectTaskToRun
 
 
 
;------------------------------------------------------------------------------
 
; AddTaskToReadyList
 
; This subroutine is called from the timer ISR so it must be relatively
 
; fast.
 
; Parameters:
 
; r1 = task number
 
;
 
;------------------------------------------------------------------------------
 
message "AddTaskToReadyList"
 
AddTaskToReadyList:
 
        phx
 
        phy
 
        php
 
        sei
 
        ldy             TCB_Priority,r1 ; make sure the priority value isn't screwy.
 
        cpy             #5
 
        bpl             arl3
 
arl2:
 
        ldx             TCB_Status,r1   ; set the task status to ready
 
        or              r2,r2,#TS_READY
 
        stx             TCB_Status,r1
 
        ldx     TailRdy0,y              ; insert the task at the list tail
 
        sta             TCB_NxtRdy,x
 
        stx             TCB_PrvRdy,r1
 
        sta             TailRdy0,y
 
        ldx             #-1
 
        stx             TCB_NxtRdy,r1
 
        ldx             HeadRdy0,y              ; check if the head of the ready list needs to be updated
 
        bpl             arl3
 
        sta             HeadRdy0,y
 
        ldx             #-1
 
        stx             TCB_PrvRdy,r1
 
arl3:
 
        plp
 
        ply
 
        plx
 
        rts
 
 
 
 
 
;------------------------------------------------------------------------------
 
; RemoveTaskFromReadyList
 
; This subroutine removes a task from the ready list.
 
; This can be called from within an ISR.
 
;
 
; r1 = task number
 
;------------------------------------------------------------------------------
 
message "RemoveTaskFromReadyList"
 
RemoveTaskFromReadyList:
 
        cmp             #0
 
        bmi             rfr9                    ; bad task number, must be >= 0
 
        cmp             #255                    ; and must be <= 255
 
        bpl             rfr9
 
        pha
 
        phy
 
        push    r4
 
        push    r5
 
 
 
        php                                             ; save off interrupt mask state
 
        sei
 
        ld              r4,TCB_NxtRdy,r1        ; Get previous and next fields.
 
        ld              r5,TCB_PrvRdy,r1        ; if there is no previous task, then this is
 
        bmi             rfr1                    ; the head of the list. Update.
 
        st              r4,TCB_NxtRdy,r5
 
        cmp             r4,#0                   ; is there a next task to update ?
 
        bmi             rfr8
 
        st              r5,TCB_PrvRdy,r4
 
        ld              r5,#-1
 
        st              r5,TCB_NxtRdy,r1
 
        st              r5,TCB_PrvRdy,r1
 
        bra             rfr8
 
 
 
        ; Update the head of the list
 
rfr1:
 
        ldy             TCB_Priority,r1
 
        st              r4,HeadRdy0,y
 
        cmp             r4,#0                   ; did we empty the list ?
 
        bmi             rfr8
 
        ld              r5,#-1                  ; flag no previous task for head of list
 
        st              r5,TCB_PrvRdy,r4
 
        st              r5,TCB_NxtRdy,r1
 
        st              r5,TCB_PrvRdy,r1
 
rfr8:
 
        plp
 
        pop             r5
 
        pop             r4
 
        ply
 
        pla
 
rfr9:
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; r1 = task
 
; r2 = timeout value
 
;------------------------------------------------------------------------------
 
message "AddToTimeoutList"
 
AddToTimeoutList:
 
        phx
 
        push    r4
 
        push    r5
 
        php
 
        sei
 
 
 
        ld              r5,#-1
 
        ld              r4,TimeoutList  ; are there any tasks on the timeout list ?
 
        bmi             attl1
 
attl_check_next:
 
        sub             r2,r2,TCB_Timeout,r4    ; is this timeout > next
 
        bmi             attl_insert_before
 
        ld              r5,r4
 
        ld              r4,TCB_NxtRdy,r4
 
        bpl             attl_check_next
 
 
 
        ; Here we scanned until the end of the timeout list and didn't find a
 
        ; timeout of a greater value. So we add the task to the end of the list.
 
attl_add_at_end:
 
        st              r4,TCB_NxtRdy,r1        ; r4 was = -1
 
        st              r1,TCB_NxtRdy,r5
 
        st              r5,TCB_PrvRdy,r1
 
        st              r2,TCB_Timeout,r1
 
        bra             attl_exit
 
 
 
attl_insert_before:
 
        cmp             r5,#-1
 
        beq             attl2
 
        st              r4,TCB_NxtRdy,r1        ; next on list goes after this task
 
        st              r5,TCB_PrvRdy,r1        ; set previous link
 
        st              r1,TCB_NxtRdy,r5
 
        st              r1,TCB_PrvRdy,r4
 
        bra             attl3
 
 
 
        ; Here there is no previous entry in the timeout list
 
        ; Add at start
 
attl2:
 
        sta             TCB_PrvRdy,r4
 
        st              r5,TCB_PrvRdy,r1        ; r5 = -1
 
        st              r4,TCB_NxtRdy,r1
 
        sta             TimeoutList             ; update the head pointer
 
attl3:
 
        add             r2,r2,TCB_Timeout,r4    ; get back timeout
 
        stx             TCB_Timeout,r1
 
        ld              r5,TCB_Timeout,r4       ; adjust the timeout of the next task
 
        sub             r5,r5,r2
 
        st              r5,TCB_Timeout,r4
 
        bra             attl_exit
 
 
 
        ; Here there were no tasks on the timeout list, so we add at the
 
        ; head of the list.
 
attl1:
 
        sta             TimeoutList             ; set the head of the timeout list
 
        stx             TCB_Timeout,r1
 
        ldx             #-1                             ; flag no more entries in timeout list
 
        stx             TCB_NxtRdy,r1           ; no next entries
 
        stx             TCB_PrvRdy,r1           ; and no prev entries
 
attl_exit:
 
        plp
 
        pop             r5
 
        pop             r4
 
        plx
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; This subroutine is called from within the timer ISR and already has the
 
; timeout list locked. Any other caller must lock the timeout list first
 
; before calling this routine.
 
;
 
; r1 = task number
 
;------------------------------------------------------------------------------
 
message "RemoveFromTimeoutList"
 
RemoveFromTimeoutList:
 
        pha
 
        phx
 
        push    r4
 
        push    r5
 
        php
 
        sei
 
 
 
        ld              r4,TCB_PrvRdy,r1                ; adjust the links of the next and previous
 
        bmi             rftl2
 
        ld              r5,TCB_NxtRdy,r1                ; tasks on the list to point around the task
 
        st              r5,TCB_NxtRdy,r4
 
        bmi             rftl1
 
        st              r4,TCB_PrvRdy,r5
 
        ldx             TCB_Timeout,r1                  ; update the timeout of the next on list
 
        add             r2,r2,TCB_Timeout,r5    ; with any remaining timeout in the task
 
        stx             TCB_Timeout,r5                  ; removed from the list
 
 
 
        ; Here there is no next item on the list
 
rftl1:
 
        bra             rftl3
 
 
 
        ; Here there is no previous item on the list, so update the head of
 
        ; the list.
 
rftl2:
 
        ld              r5,TCB_NxtRdy,r1
 
        st              r5,TimeoutList          ; store next field into list head
 
        bmi             rftl3
 
        lda             #-1                                     ; there is no previous item to the head
 
        sta             TCB_PrvRdy,r5
 
 
 
        ; Here there is no previous or next items in the list, so the list
 
        ; will be empty once this task is removed from it.
 
rftl3:
 
        plp
 
        pop             r5
 
        pop             r4
 
        plx
 
        pla
 
        rts
 
;------------------------------------------------------------------------------
 
; Allocate a mailbox
 
; r1 = pointer to place to store handle
 
;------------------------------------------------------------------------------
 
message "AllocMbx"
 
AllocMbx:
 
        cmp             #0
 
        beq             ambx1
 
        phx
 
        phy
 
        push    r4
 
        ld              r4,r1
 
        php
 
        sei
 
        lda             FreeMbx                 ; Get mailbox off of free mailbox list
 
        sta             (r4)                    ; store off the mailbox number
 
        bmi             ambx2
 
        ldx             MBX_LINK,r1             ; and update the head of the list
 
        stx             FreeMbx
 
        dec             nMailbox                ; decrement number of available mailboxes
 
        tax
 
        ldy             RunningTCB                      ; set the mailbox owner
 
        lda             TCB_hJCB,y
 
        sta             MBX_OWNER,x
 
        lda             #-1                             ; initialize the head and tail of the queues
 
        sta             MBX_TQ_HEAD,x
 
        sta             MBX_TQ_TAIL,x
 
        sta             MBX_MQ_HEAD,x
 
        sta             MBX_MQ_TAIL,x
 
        stz             MBX_TQ_COUNT,x  ; initialize counts to zero
 
        stz             MBX_MQ_COUNT,x
 
        stz             MBX_MQ_MISSED,x
 
        lda             #8                              ; set the max queue size
 
        sta             MBX_MQ_SIZE,x   ; and
 
        lda             #MQS_NEWEST             ; queueing strategy
 
        sta             MBX_MQ_STRATEGY,x
 
        plp
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_Ok
 
        rts
 
ambx1:
 
        lda             #E_Arg
 
        rts
 
ambx2:
 
        plp
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_NoMoreMbx
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; r1 = message
 
; r2 = mailbox
 
;------------------------------------------------------------------------------
 
message "QueueMsgAtMbx"
 
QueueMsgAtMbx:
 
        pha
 
        phx
 
        phy
 
        php
 
        sei
 
        ldy             MBX_MQ_TAIL,x
 
        bmi             qmam1
 
        sta             MBX_LINK,y
 
        bra             qmam2
 
qmam1:
 
        sta             MBX_MQ_HEAD,x
 
qmam2:
 
        sta             MBX_MQ_TAIL,x
 
        inc             MBX_MQ_COUNT,x          ; increase the queued message count
 
        ldx             #-1
 
        stx             MSG_LINK,r1
 
        plp
 
        ply
 
        plx
 
        pla
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; Returns
 
; r1 = message number
 
;------------------------------------------------------------------------------
 
message "DequeueMsgFromMbx"
 
DequeueMsgFromMbx:
 
        phx
 
        phy
 
        php
 
        sei
 
        tax                                             ; x = mailbox index
 
        lda             MBX_MQ_COUNT,x          ; are there any messages available ?
 
        beq             dmfm1
 
        dea
 
        sta             MBX_MQ_COUNT,x          ; update the message count
 
        lda             MBX_MQ_HEAD,x           ; Get the head of the list, this should not be -1
 
        bmi             dmfm1                   ; since the message count > 0
 
        ldy             MSG_LINK,r1             ; get the link to the next message
 
        sty             MBX_MQ_HEAD,x           ; update the head of the list
 
        bpl             dmfm2                   ; if there was no more messages then update the
 
        sty             MBX_MQ_TAIL,x           ; tail of the list as well.
 
dmfm2:
 
        sta             MSG_LINK,r1             ; point the link to the messahe itself to indicate it's dequeued
 
dmfm1:
 
        plp
 
        ply
 
        plx
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
;------------------------------------------------------------------------------
 
DequeueThreadFromMbx:
 
        cpx             #0
 
        beq             dtfm1
 
        php
 
        sei
 
        push    r4
 
        ld              r4,MBX_TQ_HEAD,r1
 
        bpl             dtfm2
 
                pop             r4
 
                stz             (x)
 
                plp
 
                lda             #E_NoThread
 
                rts
 
dtfm2:
 
        push    r5
 
        dec             MBX_TQ_COUNT,r1
 
        st              r4,(x)
 
        ld              r4,TCB_mbq_next,r4
 
        st              r4,MBX_TQ_HEAD,r1
 
        bmi             dtfm3
 
                ld              r5,#-1
 
                st              r5,TCB_mbq_prev,r4
 
                bra             dtfm4
 
dtfm3:
 
                ld              r5,#-1
 
                st              r5,MBX_TQ_TAIL,r1
 
dtfm4:
 
        stz             MBX_SEMA+1
 
        ld              r5,(x)
 
        lda             TCB_Status,r5
 
        bit             #TS_TIMEOUT
 
        beq             dtfm5
 
                ld              r1,r5
 
                jsr             RemoveFromTimeoutList
 
dtfm5:
 
        ld              r4,#-1
 
        st              r4,TCB_mbq_next,r5
 
        st              r4,TCB_mbq_prev,r5
 
        stz             TCB_hWaitMbx,r5
 
        lda             TCB_Status,r5
 
        and             #~TS_WAITMSG
 
        sta             TCB_Status,r5
 
        pop             r5
 
        pop             r4
 
        plp
 
        lda             #E_Ok
 
        rts
 
dtfm1:
 
        lda             #E_Arg
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; r1 = handle to mailbox
 
; r2 = message D1
 
; r3 = message D2
 
;------------------------------------------------------------------------------
 
message "SendMsg"
 
SendMsg:
 
        cmp             #0                                              ; check the mailbox number to make sure
 
        bmi             smsg1                                   ; that it's sensible
 
        cmp             #2047
 
        bpl             smsg1
 
        push    r4
 
        push    r5
 
        push    r6
 
        php
 
        sei
 
        ld              r4,MBX_OWNER,r1
 
        bmi             smsg2                                   ; error: no owner
 
        pha
 
        phx
 
        jsr             DequeueThreadFromMbx    ; r1=mbx, r2=thread (returned)
 
        ld              r6,r2                                   ; r6 = thread
 
        plx
 
        pla
 
        cmp             r6,#0
 
        bpl             smsg3
 
                ; Here there was no thread waiting at the mailbox, so a message needs to
 
                ; be allocated
 
                ld              r4,FreeMsg
 
                bmi             smsg4           ; no more messages available
 
                ld              r5,MSG_LINK,r4
 
                st              r5,FreeMsg
 
                dec             nMsgBlk         ; decrement the number of available messages
 
                stx             MSG_D1,r4
 
                sty             MSG_D2,r4
 
                pha
 
                phx
 
                tax                                             ; x = mailbox
 
                ld              r1,r4                   ; acc = message
 
                jsr             QueueMsgAtMbx
 
                plx
 
                pla
 
                cmp             r6,#0                   ; check if there is a thread waiting for a message
 
                bmi             smsg5
 
smsg3:
 
        ld              r5,TCB_MSGPTR_D1,r6
 
        beq             smsg6
 
        stx             (r5)
 
smsg6:
 
        ld              r5,TCB_MSGPTR_D2,r6
 
        beq             smsg7
 
        sty             (r5)
 
smsg7:
 
        ld              r5,TCB_Status,r6
 
        and             r5,r5,#TS_TIMEOUT
 
        beq             smsg8
 
        ld              r1,r6
 
        jsr             RemoveFromTimeoutList
 
smsg8:
 
        ld              r1,r6
 
        jsr             AddTaskToReadyList
 
smsg5:
 
        plp
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        lda             #E_Ok
 
        rts
 
smsg1:
 
        lda             #E_BadMbx
 
        rts
 
smsg2:
 
        plp
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        lda             #E_NotAlloc
 
        rts
 
smsg4:
 
        plp
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        lda             #E_NoMsg
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; WaitMsg
 
; Wait at a mailbox for a message to arrive. This subroutine will block the
 
; task until a message is available or the task times out on the timeout
 
; list.
 
;
 
; Parameters
 
;       r1=mailbox
 
;       r2=pointer to D1
 
;       r3=pointer to D2
 
;       r4=timeout
 
; Returns:
 
;       r1=E_Ok                 if everything is ok
 
;       r1=E_BadMbx             for a bad mailbox number
 
;       r1=E_NotAlloc   for a mailbox that isn't allocated
 
;------------------------------------------------------------------------------
 
WaitMsg:
 
        cmp             #0                                              ; check the mailbox number to make sure
 
        bmi             wmsg1                                   ; that it's sensible
 
        cmp             #2047
 
        bpl             wmsg1
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        ld              r6,r1
 
        php
 
        sei
 
        ld              r5,MBX_OWNER,r1
 
        bmi             wmsg2                                   ; error: no owner
 
        jsr             DequeueMsgFromMbx
 
        cmp             #0
 
        bpl             wmsg3
 
 
 
        ; Here there was no message available, remove the task from
 
        ; the ready list, and optionally add it to the timeout list.
 
        ; Queue the task at the mailbox.
 
        lda             RunningTCB                              ; remove the task from the ready list
 
        jsr             RemoveTaskFromReadyList
 
        ld              r7,TCB_Status,r1                        ; set task status to waiting
 
        or              r7,r7,#TS_WAITMSG
 
        st              r7,TCB_Status,r1
 
        st              r6,TCB_hWaitMbx,r1                      ; set which mailbox is waited for
 
        ld              r7,#-1
 
        st              r7,TCB_mbq_next,r1                      ; adding at tail, so there is no next
 
        stx             TCB_MSGPTR_D1,r1                        ; save off the message pointers
 
        sty             TCB_MSGPTR_D2,r1
 
        ld              r7,MBX_TQ_HEAD,r1                       ; is there a task que setup at the mailbox ?
 
        bmi             wmsg6
 
        ld              r7,MBX_TQ_TAIL,r6
 
        st              r7,TCB_mbq_prev,r1
 
        sta             TCB_mbq_next,r7
 
        sta             MBX_TQ_TAIL,r6
 
        inc             MBX_TQ_COUNT,r6                         ; increment number of tasks queued
 
wmsg7:
 
        cmp             r4,#0                                           ; check for a timeout
 
        beq             wmsg10
 
        ld              r2,r4
 
        jsr             AddToTimeoutList
 
wmsg10:
 
        ld              r2,#wmsg8                                       ; save the return address
 
        phx
 
        php                                                                     ; save status register
 
        pha                                                                     ; and save the register set
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        push    r8
 
        push    r9
 
        push    r10
 
        push    r11
 
        push    r12
 
        push    r13
 
        push    r14
 
        push    r15
 
        jmp             SelectTaskToRun
 
 
 
        ; Here there were no prior tasks queued at the mailbox
 
wmsg6:
 
        ld              r7,#-1
 
        st              r7,TCB_mbq_prev,r1              ; no previous tasks
 
        st              r7,TCB_mbq_next,r1
 
        sta             MBX_TQ_HEAD,r6                  ; set both head and tail indexes
 
        sta             MBX_TQ_TAIL,r6
 
        ld              r7,#1
 
        st              r7,MBX_TQ_COUNT,r6              ; one task queued
 
        bra             wmsg7                                   ; check for a timeout value
 
 
 
        ; Store message D1 to pointer
 
wmsg3:
 
        cpx             #0
 
        beq             wmsg4
 
        ld              r7,MSG_D1,r1
 
        st              r7,(x)
 
        ; Store message D2 to pointer
 
wmsg4:
 
        cpy             #0
 
        beq             wmsg5
 
        ld              r7,MSG_D2,r1
 
        st              r7,(y)
 
        ; Add the newly dequeued message to the free messsage list
 
wmsg5:
 
        ld              r7,FreeMsg
 
        st              r7,MSG_LINK,r1
 
        sta             FreeMsg
 
        inc             nMsgBlk
 
wmsg8:
 
        plp
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_Ok
 
        rts
 
wmsg1:
 
        lda             #E_BadMbx
 
        rts
 
wmsg2:
 
        plp
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_NotAlloc
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; CheckMsg
 
; Check for a message at a mailbox. Does not block.
 
;
 
; Parameters
 
;       r1=mailbox
 
;       r2=pointer to D1
 
;       r3=pointer to D2
 
;       r4=remove from queue if present
 
; Returns:
 
;       r1=E_Ok                 if everything is ok
 
;       r1=E_NoMsg              if no message is available
 
;       r1=E_BadMbx             for a bad mailbox number
 
;       r1=E_NotAlloc   for a mailbox that isn't allocated
 
;------------------------------------------------------------------------------
 
CheckMsg:
 
        cmp             #0                                              ; check the mailbox number to make sure
 
        bmi             cmsg1                                   ; that it's sensible
 
        cmp             #2047
 
        bpl             cmsg1
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        php
 
        sei
 
        ld              r5,MBX_OWNER,r1
 
        bmi             cmsg2                                   ; error: no owner
 
        cmp             r4,#0                                   ; are we to dequeue the message ?
 
        beq             cmsg3
 
        jsr             DequeueMsgFromMbx
 
        bra             cmsg4
 
cmsg3:
 
        lda             MBX_MQ_HEAD,r1
 
cmsg4:
 
        cmp             #0
 
        bmi             cmsg5
 
        cpx             #0
 
        beq             cmsg6
 
        ld              r5,MSG_D1,r1
 
        st              r5,(x)
 
cmsg6:
 
        cpy             #0
 
        beq             cmsg7
 
        ld              r5,MSG_D2,r1
 
        st              r5,(y)
 
cmsg7:
 
        cmp             r4,#0
 
        beq             cmsg8
 
        ld              r5,FreeMsg
 
        st              r5,MSG_LINK,r1
 
        sta             FreeMsg
 
        inc             nMsgBlk
 
cmsg8:
 
        plp
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_Ok
 
        rts
 
cmsg1:
 
        lda             #E_BadMbx
 
        rts
 
cmsg2:
 
        plp
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_NotAlloc
 
        rts
 
cmsg5:
 
        plp
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        lda             #E_NoMsg
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; r1 = task number
 
; r2 = timeout
 
;------------------------------------------------------------------------------
 
PutTaskToSleep:
 
        jsr             RemoveTaskFromReadyList
 
        jsr             AddToTimeoutList
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; The I/O focus list is an array indicating which tasks are requesting the
 
; I/O focus. The I/O focus is user controlled by pressing ALT-TAB on the
 
; keyboard.
 
;------------------------------------------------------------------------------
 
message "RequestIOFocus"
 
RequestIOFocus:
 
        pha
 
        phx
 
        phy
 
        php
 
        sei
 
        ldx             RunningTCB
 
        and             r1,r2,#$1F              ; get bit index 0 to 31
 
        ldy             #1
 
        asl             r3,r3,r1                ; shift bit to proper place
 
        lsr             r2,r2,#5                ; get word index /32 bits per word
 
        lda             IOFocusList,x
 
        or              r1,r1,r3
 
        sta             IOFocusList,x
 
        plp
 
        ply
 
        plx
 
        pla
 
        rts
 
 
        emm
message "ReleaseIOFocus"
        cpu             W65C02
ReleaseIOFocus:
        ldx             #$FF                    ; set 8 bit stack pointer
        pha
        txs
        phx
        nat
        phy
        cpu             rtf65002
        php
        lda             #$CE                    ; CE =blue on blue FB = grey on grey
        sei
        sta             ScreenColor
        ldx             RunningTCB
        sta             CharColor
        and             r1,r2,#$1F              ; get bit index 0 to 31
        jsr             ClearScreen
        ldy             #1
        jsr             ClearBmpScreen
        asl             r3,r3,r1                ; shift bit to proper place
        stz             CursorRow
        eor             r3,r3,#-1               ; invert bit mask
        stz             CursorCol
        lsr             r2,r2,#5                ; get word index /32 bits per word
        lda             #msgStart
        lda             IOFocusList,x
        jsr             DisplayStringB
        and             r1,r1,r3
        jsr             KeybdInit
        sta             IOFocusList,x
        lda             #1
        plp
        sta             KeybdEcho
        ply
        jsr             PICInit
        plx
        cli                                             ; enable interrupts
        pla
        jmp             Monitor
        rts
st1
 
        jsr             KeybdGetCharDirect
 
        bra             st1
 
        stp
 
        bra             start
 
 
 
msgStart
;------------------------------------------------------------------------------
        db              "RTF65002 system starting.",$0d,$0a,00
;------------------------------------------------------------------------------
 
GetScreenLocation:
 
        lda             RunningTCB
 
        cmp             OUTPUT_FOCUS
 
        beq             gsl1
 
        asl             r1,r1,#13                       ; 8192 words per screen
 
        add             r1,r1,#BIOS_SCREENS
 
        rts
 
gsl1:
 
        lda             #TEXTSCR
 
        rts
 
 
;----------------------------------------------------------
GetColorCodeLocation:
; Initialize programmable interrupt controller (PIC)
        lda             RunningTCB
;  0 = nmi (parity error)
        cmp             OUTPUT_FOCUS
;  1 = keyboard reset
        beq             gccl1
;  2 = 1000Hz pulse (context switcher)
        asl             r1,r1,#13                       ; 8192 words per screen
;  3 = 100Hz pulse (cursor flash)
        add             r1,r1,#BIOS_SCREENS+4096
;  4 = ethmac
        rts
;  8 = uart
gccl1:
; 13 = raster interrupt
        lda             #TEXTSCR+$10000
; 15 = keyboard char
        rts
;----------------------------------------------------------
 
PICInit:
;------------------------------------------------------------------------------
        ; enable: raster irq,
;------------------------------------------------------------------------------
        lda             #$000F                  ; enable nmi,kbd_rst,and kbd_irq
message "CopyVirtualScreenToScreen"
        ; A10F enable serial IRQ
CopyVirtualScreenToScreen
        sta             PIC_IE
        pha
PICret:
        phx
 
        phy
 
        lda             #4095                           ; number of words to copy-1
 
        ldx             OUTPUT_FOCUS            ; compute virtual screen location
 
        asl             r2,r2,#13                       ; 8192 words per screen
 
        add             r2,r2,#BIOS_SCREENS     ; add in screens array base address
 
        ldy             #TEXTSCR
 
;       mvn
 
cvss1:
 
        ld              r4,(x)
 
        st              r4,(y)
 
        inx
 
        iny
 
        dea
 
        bne             cvss1
 
        ; now copy the color codes
 
        lda             #4095
 
        ldx             OUTPUT_FOCUS
 
        asl             r2,r2,#13
 
        add             r2,r2,#BIOS_SCREENS+4096        ; virtual char color array
 
        ldy             #TEXTSCR+$10000
 
cvss2:
 
        ld              r4,(x)
 
        st              r4,(y)
 
        inx
 
        iny
 
        dea
 
        bne             cvss2
 
        ply
 
        plx
 
        pla
 
        rts
 
message "CopyScreenToVirtualScreen"
 
CopyScreenToVirtualScreen
 
        pha
 
        phx
 
        phy
 
        lda             #4095
 
        ldx             #TEXTSCR
 
        ldy             OUTPUT_FOCUS
 
        asl             r3,r3,#13
 
        add             r3,r3,#BIOS_SCREENS
 
csvs1:
 
        ld              r4,(x)
 
        st              r4,(y)
 
        inx
 
        iny
 
        dea
 
        bne             csvs1
 
        lda             #4095
 
        ldx             #TEXTSCR+$10000
 
        ldy             OUTPUT_FOCUS
 
        asl             r3,r3,#13
 
        add             r3,r3,#BIOS_SCREENS+4096
 
csvs2:
 
        ld              r4,(x)
 
        st              r4,(y)
 
        inx
 
        iny
 
        dea
 
        bne             csvs2
 
        ply
 
        plx
 
        pla
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Clear the screen and the screen color memory
; Clear the screen and the screen color memory
; We clear the screen to give a visual indication that the system
; We clear the screen to give a visual indication that the system
; is working at all.
; is working at all.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "ClearScreen"
ClearScreen:
ClearScreen:
        pha                                                     ; holds a space character
        pha                                                     ; holds a space character
        phx                                                     ; loop counter
        phx                                                     ; loop counter
        phy                                                     ; memory addressing
        phy                                                     ; memory addressing
        push    r4                                      ; holds the screen color
        push    r4                                      ; holds the screen color
 
        push    r5
        lda             TEXTREG+TEXT_COLS       ; calc number to clear
        lda             TEXTREG+TEXT_COLS       ; calc number to clear
        ldx             TEXTREG+TEXT_ROWS
        ldx             TEXTREG+TEXT_ROWS
        mul             r2,r1,r2                        ; r2 = # chars to clear
        mul             r2,r1,r2                        ; r2 = # chars to clear
 
        jsr             GetScreenLocation
 
        tay
 
        jsr             GetColorCodeLocation
 
        ld              r5,r1
        lda             #' '                            ; space char
        lda             #' '                            ; space char
        ld              r4,ScreenColor
        ld              r4,ScreenColor
        jsr             AsciiToScreen
        jsr             AsciiToScreen
        ldy             #TEXTSCR                        ; text screen address
 
csj4:
csj4:
        sta             (y)
        sta             (y)
        st              r4,$10000,y                     ; color screen is 0x10000 higher
 
        iny
        iny
 
        st              r4,(r5)
 
        inc             r5
        dex
        dex
        bne             csj4
        bne             csj4
 
        pop             r5
        pop             r4
        pop             r4
        ply
        ply
        plx
        plx
        pla
        pla
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Scroll text on the screen upwards
; Scroll text on the screen upwards
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "ScrollUp"
ScrollUp:
ScrollUp:
        pha
        pha
        phx
        phx
        phy
        phy
        push    r4
        push    r4
        push    r5
        push    r5
 
        push    r6
        lda             TEXTREG+TEXT_COLS       ; acc = # text columns
        lda             TEXTREG+TEXT_COLS       ; acc = # text columns
        ldx             TEXTREG+TEXT_ROWS
        ldx             TEXTREG+TEXT_ROWS
        mul             r2,r1,r2                        ; calc number of chars to scroll
        mul             r2,r1,r2                        ; calc number of chars to scroll
        sub             r2,r2,r1                        ; one less row
        sub             r2,r2,r1                        ; one less row
        ldy             #TEXTSCR
        pha
 
        jsr             GetScreenLocation
 
        tay
 
        jsr             GetColorCodeLocation
 
        ld              r6,r1
 
        pla
scrup1:
scrup1:
        add             r5,r3,r1
        add             r5,r3,r1
        ld              r4,(r5)                         ; move character
        ld              r4,(r5)                         ; move character
        st              r4,(y)
        st              r4,(y)
        ld              r4,$10000,r5            ; and move color code
        add             r5,r6,r1
        st              r4,$10000,y
        ld              r4,(r5)                         ; and move color code
 
        st              r4,(r6)
        iny
        iny
 
        inc             r6
        dex
        dex
        bne             scrup1
        bne             scrup1
        lda             TEXTREG+TEXT_ROWS
        lda             TEXTREG+TEXT_ROWS
        dea
        dea
        jsr             BlankLine
        jsr             BlankLine
 
        pop             r6
        pop             r5
        pop             r5
        pop             r4
        pop             r4
        ply
        ply
        plx
        plx
        pla
        pla
Line 303... Line 1588...
;
;
BlankLine:
BlankLine:
        pha
        pha
        phx
        phx
        phy
        phy
 
        push    r4
        ldx             TEXTREG+TEXT_COLS       ; x = # chars to blank out from video controller
        ldx             TEXTREG+TEXT_COLS       ; x = # chars to blank out from video controller
        mul             r3,r2,r1                        ; y = screen index (row# * #cols)
        mul             r3,r2,r1                        ; y = screen index (row# * #cols)
        add             r3,r3,#TEXTSCR          ; y = screen address
        pha
 
        jsr             GetScreenLocation
 
        ld              r4,r1
 
        pla
 
        add             r3,r3,r4                ; y = screen address
        lda             #' '
        lda             #' '
 
        jsr             AsciiToScreen
blnkln1:
blnkln1:
        sta             (y)
        sta             (y)
        iny
        iny
        dex
        dex
        bne             blnkln1
        bne             blnkln1
 
        pop             r4
        ply
        ply
        plx
        plx
        pla
        pla
        rts
        rts
 
 
Line 350... Line 1642...
        add             #$60
        add             #$60
stasc1:
stasc1:
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
; HomeCursor
 
; Set the cursor location to the top left of the screen.
 
;------------------------------------------------------------------------------
 
HomeCursor:
 
        phx
 
        ldx             RunningTCB
 
        stz             TCB_CursorRow,x
 
        stz             TCB_CursorCol,x
 
        plx
 
        rts
 
 
 
;------------------------------------------------------------------------------
; Calculate screen memory location from CursorRow,CursorCol.
; Calculate screen memory location from CursorRow,CursorCol.
; Also refreshes the cursor location.
; Also refreshes the cursor location.
; Returns:
; Returns:
; r1 = screen location
; r1 = screen location
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
CalcScreenLoc:
CalcScreenLoc:
        phx
        phx
        lda             CursorRow
        push    r4
 
        ld              r4,RunningTCB
 
        lda             TCB_CursorRow,r4
        ldx             TEXTREG+TEXT_COLS
        ldx             TEXTREG+TEXT_COLS
        mul             r2,r2,r1
        mul             r2,r2,r1
        add             r2,r2,CursorCol
        add             r2,r2,TCB_CursorCol,r4
 
        cmp             r4,OUTPUT_FOCUS                 ; update cursor position in text controller
 
        bne             csl1                                    ; only for the task with the output focus
        stx             TEXTREG+TEXT_CURPOS
        stx             TEXTREG+TEXT_CURPOS
        add             r1,r2,#TEXTSCR  ; r1 = screen location
csl1:
 
        jsr             GetScreenLocation
 
        add             r1,r2,r1
 
csl2:
 
        pop             r4
        plx
        plx
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Display a character on the screen
; Display a character on the screen.
 
; If the task doesn't have the I/O focus then the character is written to
 
; the virtual screen.
; r1 = char to display
; r1 = char to display
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "DisplayChar"
DisplayChar:
DisplayChar:
 
        push    r4
 
        ld              r4,RunningTCB
 
        and             #$FF                            ; mask off any higher order bits (called from eight bit mode).
        cmp             #'\r'                           ; carriage return ?
        cmp             #'\r'                           ; carriage return ?
        bne             dccr
        bne             dccr
        stz             CursorCol                       ; just set cursor column to zero on a CR
        stz             TCB_CursorCol,r4        ; just set cursor column to zero on a CR
        jsr             CalcScreenLoc
        jsr             CalcScreenLoc
 
        pop             r4
        rts
        rts
dccr:
dccr:
        cmp             #$91                            ; cursor right ?
        cmp             #$91                            ; cursor right ?
        bne             dcx6
        bne             dcx6
        pha
        pha
        lda             CursorCol
        lda             TCB_CursorCol,r4
        cmp             #83
        cmp             #83
        bcs             dcx7
        bcs             dcx7
        ina
        ina
        sta             CursorCol
        sta             TCB_CursorCol,r4
dcx7:
dcx7:
        jsr             CalcScreenLoc
        jsr             CalcScreenLoc
        pla
        pla
 
        pop             r4
        rts
        rts
dcx6:
dcx6:
        cmp             #$90                            ; cursor up ?
        cmp             #$90                            ; cursor up ?
        bne             dcx8
        bne             dcx8
        pha
        pha
        lda             CursorRow
        lda             TCB_CursorRow,r4
        beq             dcx7
        beq             dcx7
        dea
        dea
        sta             CursorRow
        sta             TCB_CursorRow,r4
        bra             dcx7
        bra             dcx7
dcx8:
dcx8:
        cmp             #$93                            ; cursor left ?
        cmp             #$93                            ; cursor left ?
        bne             dcx9
        bne             dcx9
        pha
        pha
        lda             CursorCol
        lda             TCB_CursorCol,r4
        beq             dcx7
        beq             dcx7
        dea
        dea
        sta             CursorCol
        sta             TCB_CursorCol,r4
        bra             dcx7
        bra             dcx7
dcx9:
dcx9:
        cmp             #$92                            ; cursor down ?
        cmp             #$92                            ; cursor down ?
        bne             dcx10
        bne             dcx10
        pha
        pha
        lda             CursorRow
        lda             TCB_CursorRow,r4
        cmp             #46
        cmp             #46
        beq             dcx7
        beq             dcx7
        ina
        ina
        sta             CursorRow
        sta             TCB_CursorRow,r4
        bra             dcx7
        bra             dcx7
dcx10:
dcx10:
        cmp             #$94                            ; cursor home ?
        cmp             #$94                            ; cursor home ?
        bne             dcx11
        bne             dcx11
        pha
        pha
        lda             CursorCol
        lda             TCB_CursorCol,r4
        beq             dcx12
        beq             dcx12
        stz             CursorCol
        stz             TCB_CursorCol,r4
        bra             dcx7
        bra             dcx7
dcx12:
dcx12:
        stz             CursorRow
        stz             TCB_CursorRow,r4
        bra             dcx7
        bra             dcx7
dcx11:
dcx11:
        pha
        pha
        phx
        phx
        phy
        phy
        cmp             #$99                            ; delete ?
        cmp             #$99                            ; delete ?
        bne             dcx13
        bne             dcx13
        jsr             CalcScreenLoc
        jsr             CalcScreenLoc
        tay                                                     ; y = screen location
        tay                                                     ; y = screen location
        lda             CursorCol                       ; acc = cursor column
        lda             TCB_CursorCol,r4        ; acc = cursor column
        bra             dcx5
        bra             dcx5
dcx13
dcx13
        cmp             #CTRLH                          ; backspace ?
        cmp             #CTRLH                          ; backspace ?
        bne             dcx3
        bne             dcx3
        lda             CursorCol
        lda             TCB_CursorCol,r4
        beq             dcx4
        beq             dcx4
        dea
        dea
        sta             CursorCol
        sta             TCB_CursorCol,r4
        jsr             CalcScreenLoc           ; acc = screen location
        jsr             CalcScreenLoc           ; acc = screen location
        tay                                                     ; y = screen location
        tay                                                     ; y = screen location
        lda             CursorCol
        lda             TCB_CursorCol,r4
dcx5:
dcx5:
        ldx             $4,y
        ldx             $4,y
        stx             (y)
        stx             (y)
        iny
        iny
        ina
        ina
Line 471... Line 1791...
        jsr     CalcScreenLoc   ; acc = screen location
        jsr     CalcScreenLoc   ; acc = screen location
        tay                                             ; y = screen location
        tay                                             ; y = screen location
        txa                                             ; restore r1
        txa                                             ; restore r1
        jsr             AsciiToScreen   ; convert ascii char to screen char
        jsr             AsciiToScreen   ; convert ascii char to screen char
        sta             (y)
        sta             (y)
 
        jsr             GetScreenLocation
 
        sub             r3,r3,r1                ; make y an index into the screen
 
        jsr             GetColorCodeLocation
 
        add             r3,r3,r1
        lda             CharColor
        lda             CharColor
        sta             $10000,y
        sta             (y)
        jsr             IncCursorPos
        jsr             IncCursorPos
        bra             dcx4
        bra             dcx4
dclf:
dclf:
        jsr             IncCursorRow
        jsr             IncCursorRow
dcx4:
dcx4:
        ply
        ply
        plx
        plx
        pla
        pla
 
        pop             r4
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Increment the cursor position, scroll the screen if needed.
; Increment the cursor position, scroll the screen if needed.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
IncCursorPos:
IncCursorPos:
        pha
        pha
        phx
        phx
        lda             CursorCol
        push    r4
 
        ld              r4,RunningTCB
 
        lda             TCB_CursorCol,r4
        ina
        ina
        sta             CursorCol
        sta             TCB_CursorCol,r4
        ldx             TEXTREG+TEXT_COLS
        ldx             TEXTREG+TEXT_COLS
        cmp             r1,r2
        cmp             r1,r2
        bcc             icc1
        bcc             icc1
        stz             CursorCol               ; column = 0
        stz             TCB_CursorCol,r4                ; column = 0
        bra             icr1
        bra             icr1
IncCursorRow:
IncCursorRow:
        pha
        pha
        phx
        phx
 
        push    r4
 
        ld              r4,RunningTCB
icr1:
icr1:
        lda             CursorRow
        lda             TCB_CursorRow,r4
        ina
        ina
        sta             CursorRow
        sta             TCB_CursorRow,r4
        ldx             TEXTREG+TEXT_ROWS
        ldx             TEXTREG+TEXT_ROWS
        cmp             r1,r2
        cmp             r1,r2
        bcc             icc1
        bcc             icc1
        beq             icc1
        beq             icc1
        dex                                                     ; backup the cursor row, we are scrolling up
        dex                                                     ; backup the cursor row, we are scrolling up
        stx             CursorRow
        stx             TCB_CursorRow,r4
        jsr             ScrollUp
        jsr             ScrollUp
icc1:
icc1:
        jsr             CalcScreenLoc
        jsr             CalcScreenLoc
 
        pop             r4
        plx
        plx
        pla
        pla
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
Line 579... Line 1909...
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
; set #2 (the most common one). Also sets up the keyboard buffer and
; set #2 (the most common one). Also sets up the keyboard buffer and
; initializes the keyboard semaphore.
; initializes the keyboard semaphore.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "KeybdInit"
KeybdInit:
KeybdInit:
        lda             #1                      ; setup semaphore
        lda             #1                      ; setup semaphore
;       sta             KEYBD_SEMA
        sta             KEYBD_SEMA
        stz             KeybdHead               ; setup keyboard buffer
        ldx             #0
        stz             KeybdTail
kbdi1:
 
        stz             KeybdHead,x             ; setup keyboard buffer
 
        stz             KeybdTail,x
        lda             #1                      ; turn on keyboard echo
        lda             #1                      ; turn on keyboard echo
        sta             KeybdEcho
        sta             KeybdEcho,x
        stz             KeybdBad
        stz             KeybdBad,x
 
        inx
 
        cpx             #256
 
        bne             kbdi1
 
 
        lda             #$ff            ; issue keyboard reset
        lda             #$ff            ; issue keyboard reset
        jsr             SendByteToKeybd
        jsr             SendByteToKeybd
        lda             #1000000                ; delay a bit
        lda             #1000000                ; delay a bit
kbdi5:
kbdi5:
Line 609... Line 1945...
 
 
msgBadKeybd:
msgBadKeybd:
        db              "Keyboard not responding.",0
        db              "Keyboard not responding.",0
 
 
SendByteToKeybd:
SendByteToKeybd:
 
        phx
 
        ldx             RunningTCB
        sta             KEYBD
        sta             KEYBD
        tsr             TICK,r3
        tsr             TICK,r3
kbdi4:                                          ; wait for transmit complete
kbdi4:                                          ; wait for transmit complete
        tsr             TICK,r4
        tsr             TICK,r4
        sub             r4,r4,r3
        sub             r4,r4,r3
Line 621... Line 1959...
        lda             KEYBD+3
        lda             KEYBD+3
        bit             #64
        bit             #64
        beq             kbdi4
        beq             kbdi4
        bra             sbtk1
        bra             sbtk1
kbdbad:
kbdbad:
        lda             KeybdBad
        lda             KeybdBad,x
        bne             sbtk1
        bne             sbtk1
        lda             #1
        lda             #1
        sta             KeybdBad
        sta             KeybdBad,x
        lda             #msgBadKeybd
        lda             #msgBadKeybd
        jsr             DisplayStringCRLFB
        jsr             DisplayStringCRLFB
sbtk1:
sbtk1:
 
        plx
        rts
        rts
 
 
; Wait for keyboard to respond with an ACK (FA)
; Wait for keyboard to respond with an ACK (FA)
;
;
WaitForKeybdAck:
WaitForKeybdAck:
Line 653... Line 1992...
; This routine picks up the ack status left by the
; This routine picks up the ack status left by the
; keyboard IRQ routine.
; keyboard IRQ routine.
; r2 = 0xFA (could also be 0xEE for echo command)
; r2 = 0xFA (could also be 0xEE for echo command)
;
;
WaitForKeybdAck2:
WaitForKeybdAck2:
        lda             KeybdAck
        phx
 
        ldx             RunningTCB
 
WaitForKeybdAck2a:
 
        lda             KeybdAck,x
        cmp             r1,r2
        cmp             r1,r2
        bne             WaitForKeybdAck2
        bne             WaitForKeybdAck2a
        stz             KeybdAck
        stz             KeybdAck,x
 
        plx
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Normal keyboard interrupt, the lowest priority interrupt in the system.
; Normal keyboard interrupt, the lowest priority interrupt in the system.
; Grab the character from the keyboard device and store it in a buffer.
; Grab the character from the keyboard device and store it in a buffer.
; Doesn't use the stack.
; The buffer of the task with the input focus is updated.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "KeybdIRQ"
KeybdIRQ:
KeybdIRQ:
 
        cld
        pha
        pha
        phx
        phx
        phy
        phy
 
        push    r4
 
 
 
        ; support EhBASIC's IRQ functionality
 
        ; code derived from minimon.asm
 
        lda             #15                             ; Keyboard is IRQ #15
 
        sta             IrqSource
 
        lb              r1,IrqBase              ; get the IRQ flag byte
 
;       or              #$20                    ; set the pending bit
 
        lsr             r2,r1
 
        or              r1,r1,r2
 
        and             #$E0
 
        sb              r1,IrqBase              ; save the new IRQ flag byte
 
 
 
        ld              r4,INPUT_FOCUS  ; get the task with the input focus
 
 
        ldx             KEYBD                           ; get keyboard character
        ldx             KEYBD                           ; get keyboard character
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
        txy                                                     ; check for a keyboard ACK code
        txy                                                     ; check for a keyboard ACK code
        and             r3,r3,#$ff
        and             r3,r3,#$ff
        cmp             r3,#$FA
        cmp             r3,#$FA
        bne             KeybdIrq1
        bne             KeybdIrq1
        sty             KeybdAck
        sty             KeybdAck,r4
        bra             KeybdIRQc
        bra             KeybdIRQc
KeybdIrq1:
KeybdIrq1:
        bit             r2,#$800                                ; test bit #11
        bit             r2,#$800                                ; test bit #11
        bne             KeybdIRQc                               ; ignore keyup messages for now
        bne             KeybdIRQc                               ; ignore keyup messages for now
        lda             KeybdHead
KeybdIrq2:
 
        lda             KeybdHead,r4
        ina                                                             ; increment head pointer
        ina                                                             ; increment head pointer
        and             #$f                                             ; limit
        and             #$f                                             ; limit
        ldy             KeybdTail                               ; check for room in the keyboard buffer
        ldy             KeybdTail,r4                    ; check for room in the keyboard buffer
        cmp             r1,r3
        cmp             r1,r3
        beq             KeybdIRQc                               ; if no room, the newest char will be lost
        beq             KeybdIRQc                               ; if no room, the newest char will be lost
        sta             KeybdHead
        sta             KeybdHead,r4
        dea
        dea
        and             #$f
        and             #$f
 
        stx             KeybdLocks,r4
 
        asl             r4,r4,#4                                        ; * 16
 
        add             r1,r1,r4
        stx             KeybdBuffer,r1                  ; store character in buffer
        stx             KeybdBuffer,r1                  ; store character in buffer
        stx             KeybdLocks
 
KeybdIRQc:
KeybdIRQc:
 
        pop             r4
        ply
        ply
        plx
        plx
        pla
        pla
        rti
        rti
 
 
KeybdRstIRQ:
KeybdRstIRQ:
        jmp             ColdStart
        jmp             start
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; r1 0=echo off, non-zero = echo on
; r1 0=echo off, non-zero = echo on
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
SetKeyboardEcho:
SetKeyboardEcho:
        sta             KeybdEcho
        phx
 
        ldx             RunningTCB
 
        sta             KeybdEcho,x
 
        plx
        rts
        rts
 
 
;-----------------------------------------
;------------------------------------------------------------------------------
 
; Get a bit from the I/O focus table.
 
;------------------------------------------------------------------------------
 
GetIOFocusBit:
 
        phx
 
        phy
 
        tax
 
        and             r1,r1,#$1F              ; get bit index into word
 
        lsr             r2,r2,#5                ; get word index into table
 
        ldy             IOFocusList,x
 
        lsr             r3,r3,r1                ; extract bit
 
        and             r1,r3,#1
 
        ply
 
        plx
 
        rts
 
 
 
;------------------------------------------------------------------------------
 
; SwitchIOFocus
 
; Switches the IO focus to the next task requesting the I/O focus.
 
; Destroys acc,x,y
 
;------------------------------------------------------------------------------
 
;
 
SwitchIOFocus:
 
        phx
 
        ; Copy the current task's screen to it's virtual screen buffer.
 
        jsr             CopyScreenToVirtualScreen
 
 
 
        ldy             INPUT_FOCUS
 
        lda             TCB_Status,y
 
        or              r1,r1,#TS_WAITFOCUS
 
        sta             TCB_Status,y
 
        tya
 
        jsr             RemoveTaskFromReadyList
 
 
 
        ; Cycle through the focus list to find the next task
 
        ; requesting the IO Focus
 
        ldx             #257                    ; we want to cycle all the way around
 
        ldy             INPUT_FOCUS             ; back to the original INPUT_FOCUS
 
        bra             kgc9                    ; enter the loop at the next possible requester
 
kgc5:
 
        tya
 
        jsr             GetIOFocusBit   ; get the focus request status
 
        cmp             #0
 
        bne             kgc6                    ; if requesting focus, break loop
 
kgc9:
 
        iny                                             ; move to test in array
 
        and             r3,r3,#$FF              ; limit y to 0 to 255 array elements
 
        dex
 
        bne             kgc5
 
        ldy             INPUT_FOCUS             ; We cycled through the whole list and there wasn't another
 
;                                                       ; task requesting focus, so stick with the same task.
 
kgc6:
 
        sty             INPUT_FOCUS
 
        sty             OUTPUT_FOCUS
 
        lda             TCB_Status,y
 
        and             #~TS_WAITFOCUS
 
        sta             TCB_Status,y
 
        tya
 
        jsr             AddTaskToReadyList
 
 
 
        ; Copy the virtual screen of the task recieving the I/O focus to the
 
        ; text screen.
 
        jsr             CopyVirtualScreenToScreen
 
        plx
 
        rts
 
 
 
;------------------------------------------------------------------------------
; Get character from keyboard buffer
; Get character from keyboard buffer
; return character in acc or -1 if no
; return character in acc or -1 if no
; characters available
; characters available.
;-----------------------------------------
; Also check for ALT-TAB and switch the I/O focus.
 
;------------------------------------------------------------------------------
 
message "KeybdGetChar"
KeybdGetChar:
KeybdGetChar:
        phx
        phx
        ldx             KeybdTail       ; if keybdTail==keybdHead then there are no
        push    r4
        lda             KeybdHead       ; characters in the keyboard buffer
        php
 
        sei
 
        ld              r4,RunningTCB
 
        ldx             KeybdTail,r4    ; if keybdTail==keybdHead then there are no
 
        lda             KeybdHead,r4    ; characters in the keyboard buffer
        cmp             r1,r2
        cmp             r1,r2
        beq             nochar
        beq             nochar
 
        asl             r4,r4,#4                        ; * 16
 
        phx
 
        add             r2,r2,r4
        lda             KeybdBuffer,x
        lda             KeybdBuffer,x
 
        plx
 
        bit             #$200                                   ; check for ALT-tab
 
        beq             kgc4
 
        and             #$FF
 
        cmp             #TAB                                    ; if we find an ALT-tab
 
        bne             kgc4
 
        jsr             SwitchIOFocus
 
        ; Now eat up the ALT-TAB character
 
        inx                                             ; increment index
 
        and             r2,r2,#$0f
 
        lsr             r4,r4,#4                        ; / 16
 
        stx             KeybdTail,r4
 
        bra             nochar
 
kgc4:
        and             r1,r1,#$ff              ; mask off control bits
        and             r1,r1,#$ff              ; mask off control bits
        inx                                             ; increment index
        inx                                             ; increment index
        and             r2,r2,#$0f
        and             r2,r2,#$0f
        stx             KeybdTail
        lsr             r4,r4,#4                        ; / 16
        ldx             KeybdEcho
        stx             KeybdTail,r4
 
        ldx             KeybdEcho,r4
        beq             kgc3
        beq             kgc3
        cmp             #CR
        cmp             #CR
        bne             kgc2
        bne             kgc8
        jsr             CRLF                    ; convert CR keystroke into CRLF
        jsr             CRLF                    ; convert CR keystroke into CRLF
        bra             kgc3
        bra             kgc3
kgc2:
kgc8:
        jsr             DisplayChar
        jsr             DisplayChar
        bra             kgc3
        bra             kgc3
nochar:
nochar:
        lda             #-1
        lda             #-1
kgc3:
kgc3:
 
        plp
 
        pop             r4
        plx
        plx
        rts
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Check if there is a keyboard character available in the keyboard buffer.
; Check if there is a keyboard character available in the keyboard buffer.
 
; Returns
 
; r1 = 1, Z=0 if there is a key available, otherwise
 
; r1 = 0, Z=1 if there is not a key available
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "KeybdCheckForKey"
KeybdCheckForKey:
KeybdCheckForKey:
        phx
        phx
        lda             KeybdTail
        push    r4
        ldx             KeybdHead
        php
 
        sei
 
        ld              r4,RunningTCB
 
        lda             KeybdTail,r4
 
        ldx             KeybdHead,r4
        sub             r1,r1,r2
        sub             r1,r1,r2
        bne             kcfk1
        bne             kcfk1
 
        plp
 
        pop             r4
        plx
        plx
 
        lda             #0
        rts
        rts
kcfk1
kcfk1
        lda             #1
        plp
 
        pop             r4
        plx
        plx
 
        lda             #1
        rts
        rts
message "668"
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Check if there is a keyboard character available. If so return true (1)
; Check if there is a keyboard character available. If so return true (1)
; otherwise return false (0) in r1.
; otherwise return false (0) in r1.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "KeybdCheckForKeyDirect"
KeybdCheckForKeyDirect:
KeybdCheckForKeyDirect:
        lda             KEYBD
        lda             KEYBD
        and             #$8000
        and             #$8000
        beq             kcfkd1
        beq             kcfkd1
        lda             #1
        lda             #1
Line 782... Line 2254...
        bit             #$8000
        bit             #$8000
        beq             kgc1
        beq             kgc1
        ld              r0,KEYBD+1              ; clear keyboard strobe
        ld              r0,KEYBD+1              ; clear keyboard strobe
        bit             #$800                   ; is it a keydown event ?
        bit             #$800                   ; is it a keydown event ?
        bne             kgc1
        bne             kgc1
 
        bit             #$200                           ; check for ALT-tab
 
        bne             kgc2
 
        and             r2,r1,#$7f
 
        cmp             r2,#TAB                                 ; if we find an ALT-tab
 
        bne             kgc2
 
        jsr             SwitchIOFocus
 
        bra             kgc1
 
kgc2:
        and             #$ff                    ; remove strobe bit
        and             #$ff                    ; remove strobe bit
        ldx             KeybdEcho               ; is keyboard echo on ?
        ldx             KeybdEcho               ; is keyboard echo on ?
        beq             gk1
        beq             gk1
        cmp             #CR
        cmp             #CR
        bne             gk2                             ; convert CR keystroke into CRLF
        bne             gk2                             ; convert CR keystroke into CRLF
Line 796... Line 2276...
gk1:
gk1:
        plx
        plx
        rts
        rts
 
 
 
 
 
;==============================================================================
 
; Serial port
 
;==============================================================================
 
;------------------------------------------------------------------------------
 
; Initialize the serial port
 
; r1 = low 28 bits = baud rate
 
; r2 = other settings
 
; The desired baud rate must fit in 28 bits or less.
 
;------------------------------------------------------------------------------
 
;
 
SerialInit:
 
;       asl             r1,r1,#4                        ; * 16
 
;       shlui   r1,r1,#32                       ; * 2^32
 
;       inhu    r2,CR_CLOCK                     ; get clock frequency from config record
 
;       divu    r1,r1,r2                        ; / clock frequency
 
 
 
        lsr             r1,r1,#8                        ; drop the lowest 8 bits
 
        sta             UART_CM1                        ; set LSB
 
        lsr             r1,r1,#8
 
        sta             UART_CM2                        ; set middle bits
 
        lsr             r1,r1,#8
 
        sta             UART_CM3                        ; set MSB
 
        stz             Uart_rxhead                     ; reset buffer indexes
 
        stz             Uart_rxtail
 
        lda             #0x1f0
 
        sta             Uart_foff                       ; set threshold for XOFF
 
        lda             #0x010
 
        sta             Uart_fon                        ; set threshold for XON
 
        lda             #1
 
        sta             UART_IE                         ; enable receive interrupt only
 
        stz             Uart_rxrts                      ; no RTS/CTS signals available
 
        stz             Uart_txrts                      ; no RTS/CTS signals available
 
        stz             Uart_txdtr                      ; no DTR signals available
 
        stz             Uart_rxdtr                      ; no DTR signals available
 
        lda             #1
 
        sta             Uart_txxon                      ; for now
 
        lda             #1
 
        sta             SERIAL_SEMA
 
        rts
 
 
 
;---------------------------------------------------------------------------------
 
; Get character directly from serial port. Blocks until a character is available.
 
;---------------------------------------------------------------------------------
 
;
 
SerialGetCharDirect:
 
sgc1:
 
        lda             UART_LS         ; uart status
 
        and             #rxfull         ; is there a char available ?
 
        beq             sgc1
 
        lda             UART
 
        rts
 
 
 
;------------------------------------------------
 
; Check for a character at the serial port
 
; returns r1 = 1 if char available, 0 otherwise
 
;------------------------------------------------
 
;
 
SerialCheckForCharDirect:
 
        lda             UART_LS                 ; uart status
 
        and             #rxfull                 ; is there a char available ?
 
        rts
 
 
 
;-----------------------------------------
 
; Put character to serial port
 
; r1 = char to put
 
;-----------------------------------------
 
;
 
SerialPutChar:
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
 
 
        ldx             UART_MC
 
        or              r2,r2,#3                ; assert DTR / RTS
 
        stx             UART_MC
 
        ldx             Uart_txrts
 
        beq             spcb1
 
        ld              r4,Milliseconds
 
        ldy             #1000                   ; delay count (1 s)
 
spcb3:
 
        ldx             UART_MS
 
        and             r2,r2,#$10              ; is CTS asserted ?
 
        bne             spcb1
 
        ld              r5,Milliseconds
 
        cmp             r4,r5
 
        beq             spcb3
 
        ld              r4,r5
 
        dey
 
        bne             spcb3
 
        bra             spcabort
 
spcb1:
 
        ldx             Uart_txdtr
 
        beq             spcb2
 
        ld              r4,Milliseconds
 
        ldy             #1000                   ; delay count
 
spcb4:
 
        ldx             UART_MS
 
        and             r2,r2,#$20              ; is DSR asserted ?
 
        bne             spcb2
 
        ld              r5,Milliseconds
 
        cmp             r4,r5
 
        beq             spcb4
 
        ld              r4,r5
 
        dey
 
        bne             spcb4
 
        bra             spcabort
 
spcb2:
 
        ldx             Uart_txxon
 
        beq             spcb5
 
spcb6:
 
        ldx             Uart_txxonoff
 
        beq             spcb5
 
        ld              r4,UART_MS
 
        and             r4,r4,#0x80                     ; DCD ?
 
        bne             spcb6
 
spcb5:
 
        ld              r4,Milliseconds
 
        ldy             #1000                           ; wait up to 1s
 
spcb8:
 
        ldx             UART_LS
 
        and             r2,r2,#0x20                     ; tx not full ?
 
        bne             spcb7
 
        ld              r5,Milliseconds
 
        cmp             r4,r5
 
        beq             spcb8
 
        ld              r4,r5
 
        dey
 
        bne             spcb8
 
        bra             spcabort
 
spcb7:
 
        sta             UART
 
spcabort:
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
 
 
;-------------------------------------------------
 
; Compute number of characters in recieve buffer.
 
; r4 = number of chars
 
;-------------------------------------------------
 
CharsInRxBuf:
 
        ld              r4,Uart_rxhead
 
        ldx             Uart_rxtail
 
        sub             r4,r4,r2
 
        bpl             cirxb1
 
        ld              r4,#0x200
 
        add             r4,r4,r2
 
        ldx             Uart_rxhead
 
        sub             r4,r4,r2
 
cirxb1:
 
        rts
 
 
 
;----------------------------------------------
 
; Get character from rx fifo
 
; If the fifo is empty enough then send an XON
 
;----------------------------------------------
 
;
 
SerialGetChar:
 
        phx
 
        phy
 
        push    r4
 
 
 
        ldy             Uart_rxhead
 
        ldx             Uart_rxtail
 
        cmp             r2,r3
 
        beq             sgcfifo1                ; is there a char available ?
 
        lda             Uart_rxfifo,x   ; get the char from the fifo into r1
 
        inx                                             ; increment the fifo pointer
 
        and             r2,r2,#$1ff
 
        stx             Uart_rxtail
 
        ldx             Uart_rxflow             ; using flow control ?
 
        beq             sgcfifo2
 
        ldy             Uart_fon                ; enough space in Rx buffer ?
 
        jsr             CharsInRxBuf
 
        cmp             r4,r3
 
        bpl             sgcfifo2
 
        stz             Uart_rxflow             ; flow off
 
        ld              r4,Uart_rxrts
 
        beq             sgcfifo3
 
        ld              r4,UART_MC              ; set rts bit in MC
 
        or              r4,r4,#2
 
        st              r4,UART_MC
 
sgcfifo3:
 
        ld              r4,Uart_rxdtr
 
        beq             sgcfifo4
 
        ld              r4,UART_MC              ; set DTR
 
        or              r4,r4,#1
 
        st              r4,UART_MC
 
sgcfifo4:
 
        ld              r4,Uart_rxxon
 
        beq             sgcfifo5
 
        ld              r4,#XON
 
        st              r4,UART
 
sgcfifo5:
 
sgcfifo2:                                       ; return with char in r1
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
sgcfifo1:
 
        lda             #-1                             ; no char available
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
 
 
 
 
;-----------------------------------------
 
; Serial port IRQ
 
;-----------------------------------------
 
;
 
SerialIRQ:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
 
 
        lda             UART_IS                 ; get interrupt status
 
        bpl             sirq1                   ; no interrupt
 
        and             #0x7f                   ; switch on interrupt type
 
        cmp             #4
 
        beq             srxirq
 
        cmp             #$0C
 
        beq             stxirq
 
        cmp             #$10
 
        beq             smsirq
 
        ; unknown IRQ type
 
sirq1:
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rti
 
 
 
 
 
; Get the modem status and record it
 
smsirq:
 
        lda             UART_MS
 
        sta             Uart_ms
 
        bra             sirq1
 
 
 
stxirq:
 
        bra             sirq1
 
 
 
; Get a character from the uart and store it in the rx fifo
 
srxirq:
 
srxirq1:
 
        lda             UART                            ; get the char (clears interrupt)
 
        ldx             Uart_txxon
 
        beq             srxirq3
 
        cmp             #XOFF
 
        bne             srxirq2
 
        lda             #1
 
        sta             Uart_txxonoff
 
        bra             srxirq5
 
srxirq2:
 
        cmp             #XON
 
        bne             srxirq3
 
        stz             Uart_txxonoff
 
        bra             srxirq5
 
srxirq3:
 
        stz             Uart_txxonoff
 
        ldx             Uart_rxhead
 
        sta             Uart_rxfifo,x           ; store in buffer
 
        inx
 
        and             r2,r2,#$1ff
 
        stx             Uart_rxhead
 
srxirq5:
 
        lda             UART_LS                         ; check for another ready character
 
        and             #rxfull
 
        bne             srxirq1
 
        lda             Uart_rxflow                     ; are we using flow controls?
 
        bne             srxirq8
 
        jsr             CharsInRxBuf
 
        lda             Uart_foff
 
        cmp             r4,r1
 
        bmi             srxirq8
 
        lda             #1
 
        sta             Uart_rxflow
 
        lda             Uart_rxrts
 
        beq             srxirq6
 
        lda             UART_MC
 
        and             #$FD                    ; turn off RTS
 
        sta             UART_MC
 
srxirq6:
 
        lda             Uart_rxdtr
 
        beq             srxirq7
 
        lda             UART_MC
 
        and             #$FE                    ; turn off DTR
 
        sta             UART_MC
 
srxirq7:
 
        lda             Uart_rxxon
 
        beq             srxirq8
 
        lda             #XOFF
 
        sta             UART
 
srxirq8:
 
        bra             sirq1
 
 
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Display nybble in r1
; Display nybble in r1
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
DisplayNybble:
DisplayNybble:
Line 882... Line 2664...
        jsr             DisplayWord
        jsr             DisplayWord
        inx
        inx
        jsr             CRLF
        jsr             CRLF
        pla
        pla
        rts
        rts
message "845"
 
 
message "Monitor"
;==============================================================================
;==============================================================================
; System Monitor Program
; System Monitor Program
 
; The system monitor is task#0
;==============================================================================
;==============================================================================
;
;
Monitor:
Monitor:
        ldx             #$05FFFFF8              ; setup stack pointer top of memory
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer
        txs
        txs
        stz             KeybdEcho               ; turn off keyboard echo
        ldx             RunningTCB
 
        stz             KeybdEcho,x             ; turn off keyboard echo
PromptLn:
PromptLn:
        jsr             CRLF
        jsr             CRLF
        lda             #'$'
        lda             #'$'
        jsr             DisplayChar
        jsr             DisplayChar
 
 
; Get characters until a CR is keyed
; Get characters until a CR is keyed
;
;
Prompt3:
Prompt3:
;       lw              r1,#2                   ; get keyboard character
;       lw              r1,#2                   ; get keyboard character
;       syscall #417
;       syscall #417
        jsr             KeybdCheckForKeyDirect
;       jsr             KeybdCheckForKeyDirect
        cmp             #0
;       cmp             #0
 
        jsr             KeybdGetChar
 
        cmp             #-1
        beq             Prompt3
        beq             Prompt3
        jsr             KeybdGetCharDirect
;       jsr             KeybdGetCharDirect
        cmp             #CR
        cmp             #CR
        beq             Prompt1
        beq             Prompt1
        jsr             DisplayChar
        jsr             DisplayChar
        bra             Prompt3
        bra             Prompt3
 
 
; Process the screen line that the CR was keyed on
; Process the screen line that the CR was keyed on
;
;
Prompt1:
Prompt1:
        stz             CursorCol               ; go back to the start of the line
        ldx             RunningTCB
 
        stz             TCB_CursorCol,x ; go back to the start of the line
        jsr             CalcScreenLoc   ; r1 = screen memory location
        jsr             CalcScreenLoc   ; r1 = screen memory location
        tay
        tay
        lda             (y)
        lda             (y)
        iny
        iny
        jsr             ScreenToAscii
        jsr             ScreenToAscii
Line 945... Line 2733...
        cmp             #'F'
        cmp             #'F'
        beq             FillMem
        beq             FillMem
Prompt7:
Prompt7:
        cmp             #'B'                    ; $B - start tiny basic
        cmp             #'B'                    ; $B - start tiny basic
        bne             Prompt4
        bne             Prompt4
        jsr             CSTART
        lda             #3
 
        ldy             #CSTART
 
        ldx             #0
 
        jsr             StartTask
 
;       jsr             CSTART
        bra             Monitor
        bra             Monitor
Prompt4:
Prompt4:
        cmp             #'b'
        cmp             #'b'
        bne             Prompt5
        bne             Prompt5
 
        lda             #3                              ; priority level 3
 
        ldy             #$C000                  ; start address $C000
 
        ldx             #$20000000              ; flags: emmulation mode set
 
        jsr             StartTask
 
        bra             Monitor
        emm
        emm
        cpu             W65C02
        cpu             W65C02
        jml             $0C000
        jml             $0C000
        cpu             rtf65002
        cpu             rtf65002
Prompt5:
Prompt5:
        cmp             #'J'                    ; $J - execute code
        cmp             #'J'                    ; $J - execute code
        beq             ExecuteCode
        beq             ExecuteCode
        cmp             #'L'                    ; $L - load S19 file
        cmp             #'L'                    ; $L - load dector
        bne             Prompt9
        beq             LoadSector
        jmp             LoadSector
        cmp             #'W'
 
        beq             WriteSector
Prompt9:
Prompt9:
        cmp             #'?'                    ; $? - display help
        cmp             #'?'                    ; $? - display help
        bne             Prompt10
        bne             Prompt10
        lda             #HelpMsg
        lda             #HelpMsg
        jsr             DisplayStringB
        jsr             DisplayStringB
        jmp             Monitor
        jmp             Monitor
Prompt10:
Prompt10:
        cmp             #'C'                    ; $C - clear screen
        cmp             #'C'                    ; $C - clear screen
        beq             TestCLS
        beq             TestCLS
        cmp             #'R'
        cmp             #'r'
        bne             Prompt12
        bne             Prompt12
        jmp             RandomLinesCall
        lda             #4                              ; priority level 4
 
        ldx             #0                              ; zero all flags at startup
 
        ldy             #RandomLines    ; task address
 
        jsr             (y)
 
;       jsr             StartTask
 
        jmp             Monitor
 
;       jmp             RandomLinesCall
Prompt12:
Prompt12:
Prompt13:
Prompt13:
        cmp             #'P'
        cmp             #'P'
        bne             Prompt14
        bne             Prompt14
        jmp             Piano
        jmp             Piano
Prompt14:
Prompt14:
        cmp             #'T'
        cmp             #'T'
        bne             Prompt15
        bne             Prompt15
        call    tmp_read
        jsr             DumpTaskList
 
        jmp             Monitor
Prompt15:
Prompt15:
        cmp             #'S'
        cmp             #'S'
        bne             Prompt16
        bne             Prompt16
        jsr             spi_init
        jsr             spi_init
        cmp             #0
        cmp             #0
Line 996... Line 2801...
        cmp             #0
        cmp             #0
        bne             Monitor
        bne             Monitor
        jsr             loadBootFile
        jsr             loadBootFile
        jmp             Monitor
        jmp             Monitor
Prompt16:
Prompt16:
 
        cmp             #'e'
 
        bne             Prompt17
 
        jsr             eth_main
 
Prompt17:
 
        cmp             #'R'
 
        bne             Monitor
 
        lda             (y)
 
        iny
 
        jsr             ScreenToAscii
 
        cmp             #'S'
 
        beq             ReadSector
 
        dey
 
        bra             SetRegValue
        jmp             Monitor
        jmp             Monitor
message "Prompt16"
message "Prompt16"
RandomLinesCall:
RandomLinesCall:
        jsr             RandomLines
;       jsr             RandomLines
        jmp             Monitor
        jmp             Monitor
 
 
TestCLS:
TestCLS:
        lda             (y)
        lda             (y)
        iny
        iny
Line 1014... Line 2832...
        iny
        iny
        jsr             ScreenToAscii
        jsr             ScreenToAscii
        cmp             #'S'
        cmp             #'S'
        bne             Monitor
        bne             Monitor
        jsr     ClearScreen
        jsr     ClearScreen
        stz             CursorCol
        ldx             RunningTCB
        stz             CursorRow
        stz             TCB_CursorCol,x
 
        stz             TCB_CursorRow,x
        jsr             CalcScreenLoc
        jsr             CalcScreenLoc
        jmp             Monitor
        jmp             Monitor
 
message "HelpMsg"
HelpMsg:
HelpMsg:
        db      "? = Display help",CR,LF
        db      "? = Display help",CR,LF
        db      "CLS = clear screen",CR,LF
        db      "CLS = clear screen",CR,LF
        db      "S = Boot from SD Card",CR,LF
        db      "S = Boot from SD Card",CR,LF
        db      ": = Edit memory bytes",CR,LF
        db      ": = Edit memory bytes",CR,LF
        db      "L = Load S19 file",CR,LF
        db      "L = Load sector",CR,LF
 
        db      "W = Write sector",CR,LF
        db  "DR = Dump registers",CR,LF
        db  "DR = Dump registers",CR,LF
        db      "D = Dump memory",CR,LF
        db      "D = Dump memory",CR,LF
        db      "F = Fill memory",CR,LF
        db      "F = Fill memory",CR,LF
        db      "B = start tiny basic",CR,LF
        db      "B = start tiny basic",CR,LF
        db      "b = start EhBasic 6502",CR,LF
        db      "b = start EhBasic 6502",CR,LF
        db      "J = Jump to code",CR,LF
        db      "J = Jump to code",CR,LF
        db      "R[n] = Set register value",CR,LF
        db      "R[n] = Set register value",CR,LF
        db      "T = get temperature",CR,LF
        db      "r = random lines - test bitmap",CR,LF
 
        db      "e = ethernet test",CR,LF
 
        db      "T = Dump task list",CR,LF
        db      "P = Piano",CR,LF,0
        db      "P = Piano",CR,LF,0
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Ignore blanks in the input
; Ignore blanks in the input
; r3 = text pointer
; r3 = text pointer
Line 1073... Line 2895...
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Execute code at the specified address.
; Execute code at the specified address.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
 
message "ExecuteCode"
ExecuteCode:
ExecuteCode:
        jsr             ignBlanks
        jsr             ignBlanks
        jsr             GetHexNumber
        jsr             GetHexNumber
        st              r1,JMPTMP
        st              r1,JMPTMP
        lda             #xcret                  ; push return address so we can do an indirect jump
        lda             #xcret                  ; push return address so we can do an indirect jump
Line 1113... Line 2936...
        st              r12,R12Save
        st              r12,R12Save
        st              r13,R13Save
        st              r13,R13Save
        st              r14,R14Save
        st              r14,R14Save
        st              r15,R15Save
        st              r15,R15Save
        tsr             sp,r1
        tsr             sp,r1
        st              r1,SPSave
        st              r1,TCB_SPSave
        tsr             sp8,r1
        tsr             sp8,r1
        st              r1,SP8Save
        st              r1,TCB_SP8Save
        pla
        pla
        sta             SRSave
        sta             SRSave
        jmp     Monitor
        jmp     Monitor
 
 
LoadSector:
LoadSector:
        jsr             ignBlanks
        jsr             ignBlanks
 
        jsr             GetDecNumber
 
        pha
 
        jsr             ignBlanks
        jsr             GetHexNumber
        jsr             GetHexNumber
        ld              r2,#0x3800
        tax
 
        phx
 
;       ld              r2,#0x3800
 
        jsr             spi_init
 
        plx
 
        pla
        jsr             spi_read_sector
        jsr             spi_read_sector
        jmp             Monitor
        jmp             Monitor
 
 
 
WriteSector:
 
        jsr             ignBlanks
 
        jsr             GetDecNumber
 
        pha
 
        jsr             ignBlanks
 
        jsr             GetHexNumber
 
        tax
 
        phx
 
        jsr             spi_init
 
        plx
 
        pla
 
        jsr             spi_write_sector
 
        jmp             Monitor
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Dump the register set.
; Dump the register set.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
 
message "DumpReg"
DumpReg:
DumpReg:
        ldy             #0
        ldy             #0
DumpReg1:
DumpReg1:
        jsr             CRLF
        jsr             CRLF
        lda             #':'
        lda             #':'
        jsr             DisplayChar
        jsr             DisplayChar
        lda             #'R'
        lda             #'R'
        jsr             DisplayChar
        jsr             DisplayChar
        ldx             #0
        ldx             #1
        tya
        tya
 
        ina
        jsr             PRTNUM
        jsr             PRTNUM
        lda             #' '
        lda             #' '
        jsr             DisplayChar
        jsr             DisplayChar
        lda             R1Save,y
        lda             R1Save,y
        jsr             DisplayWord
        jsr             DisplayWord
Line 1157... Line 3004...
        jsr             DisplayChar
        jsr             DisplayChar
        lda             #'P'
        lda             #'P'
        jsr             DisplayChar
        jsr             DisplayChar
        lda             #' '
        lda             #' '
        jsr             DisplayChar
        jsr             DisplayChar
        lda             SPSave
        lda             TCB_SPSave
        jsr             DisplayWord
        jsr             DisplayWord
        jsr             CRLF
        jsr             CRLF
        rts
        jmp             Monitor
 
;------------------------------------------------------------------------------
 
;------------------------------------------------------------------------------
 
SetRegValue:
 
        jsr             GetDecNumber
 
        cmp             #15
 
        bpl             Monitor
 
        pha
 
        jsr             ignBlanks
 
        jsr             GetHexNumber
 
        ply
 
        sta             R1Save,y
 
        jmp             Monitor
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Do a memory dump of the requested location.
; Do a memory dump of the requested location.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
Line 1187... Line 3046...
        bne             DumpmemW
        bne             DumpmemW
        jmp             Monitor
        jmp             Monitor
 
 
 
 
        bra             Monitor
        bra             Monitor
 
message "FillMem"
FillMem:
FillMem:
        jsr             ignBlanks
        jsr             ignBlanks
        jsr             GetHexNumber    ; get start address of dump
        jsr             GetHexNumber    ; get start address of dump
        tax
        tax
        jsr             ignBlanks
        jsr             ignBlanks
        jsr             GetHexNumber    ; get number of bytes to fill
        jsr             GetHexNumber    ; get number of bytes to fill
        or              r5,r1,r0
        ld              r5,r1
        jsr             ignBlanks
        jsr             ignBlanks
        jsr             GetHexNumber    ; get the fill byte
        jsr             GetHexNumber    ; get the fill byte
FillmemW:
FillmemW:
        sta             (x)
        sta             (x)
        inx
        inx
Line 1233... Line 3092...
        txa
        txa
        pop             r4
        pop             r4
        plx
        plx
        rts
        rts
 
 
 
GetDecNumber:
 
        phx
 
        push    r4
 
        push    r5
 
        ldx             #0
 
        ld              r4,#10
 
        ld              r5,#10
 
gtdcn2:
 
        lda             (y)
 
        iny
 
        jsr             ScreenToAscii
 
        jsr             AsciiToDecNybble
 
        cmp             #-1
 
        beq             gtdcn1
 
        mul             r2,r2,r5
 
        add             r2,r2,r1
 
        dec             r4
 
        bne             gtdcn2
 
gtdcn1:
 
        txa
 
        pop             r5
 
        pop             r4
 
        plx
 
        rts
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Convert ASCII character in the range '0' to '9', 'a' to 'f' or 'A' to 'F'
; Convert ASCII character in the range '0' to '9', 'a' to 'f' or 'A' to 'F'
; to a hex nybble.
; to a hex nybble.
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
Line 1265... Line 3149...
        rts
        rts
gthx3:
gthx3:
        lda             #-1             ; not a hex number
        lda             #-1             ; not a hex number
        rts
        rts
 
 
 
AsciiToDecNybble:
 
        cmp             #'0'
 
        bcc             gtdc3
 
        cmp             #'9'+1
 
        bcs             gtdc3
 
        sub             #'0'
 
        rts
 
gtdc3:
 
        lda             #-1
 
        rts
 
 
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
ClearBmpScreen:
ClearBmpScreen:
        pha
        pha
        phx
        phx
Line 1290... Line 3186...
;==============================================================================
;==============================================================================
;
;
; Initialize the SD card
; Initialize the SD card
; Returns
; Returns
; acc = 0 if successful, 1 otherwise
; acc = 0 if successful, 1 otherwise
 
; Z=1 if successful, otherwise Z=0
;
;
 
message "spi_init"
spi_init
spi_init
        lda             #SPI_INIT_SD
        lda             #SPI_INIT_SD
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
        lda             #SPI_TRANS_START
        lda             #SPI_TRANS_START
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
Line 1310... Line 3208...
        cmp             #SPI_INIT_NO_ERROR
        cmp             #SPI_INIT_NO_ERROR
        bne             spi_error
        bne             spi_error
        lda             #spi_init_ok_msg
        lda             #spi_init_ok_msg
        jsr             DisplayStringB
        jsr             DisplayStringB
        lda             #0
        lda             #0
        bra             spi_init_exit
        rts
spi_error
spi_error
        jsr             DisplayByte
        jsr             DisplayByte
        lda             #spi_init_error_msg
        lda             #spi_init_error_msg
        jsr             DisplayStringB
        jsr             DisplayStringB
        lda             SPIMASTER+SPI_RESP_BYTE1
        lda             SPIMASTER+SPI_RESP_BYTE1
Line 1324... Line 3222...
        lda             SPIMASTER+SPI_RESP_BYTE3
        lda             SPIMASTER+SPI_RESP_BYTE3
        jsr             DisplayByte
        jsr             DisplayByte
        lda             SPIMASTER+SPI_RESP_BYTE4
        lda             SPIMASTER+SPI_RESP_BYTE4
        jsr             DisplayByte
        jsr             DisplayByte
        lda             #1
        lda             #1
spi_init_exit
 
        rts
        rts
 
 
 
spi_delay:
 
        nop
 
        nop
 
        rts
 
 
 
 
; SPI read sector
; SPI read sector
;
;
; r1= sector number to read
; r1= sector number to read
Line 1364... Line 3265...
        lda             #SPI_TRANS_START
        lda             #SPI_TRANS_START
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
        nop
        nop
spi_read_sect1:
spi_read_sect1:
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
        nop                                     ; just a delay between consecutive status reg reads
        jsr             spi_delay                       ; just a delay between consecutive status reg reads
        nop
 
        cmp             #SPI_TRANS_BUSY
        cmp             #SPI_TRANS_BUSY
        beq             spi_read_sect1
        beq             spi_read_sect1
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
        lsr
        lsr
        lsr
        lsr
Line 1466... Line 3366...
        ply
        ply
        plx
        plx
        rts
        rts
 
 
; read the partition table to find out where the boot sector is.
; read the partition table to find out where the boot sector is.
 
; Returns
 
; r1 = 0 everything okay, 1=read error
 
; also Z=1=everything okay, Z=0=read error
;
;
spi_read_part:
spi_read_part:
        phx
        phx
        stz             startSector                                             ; default starting sector
        stz             startSector                                             ; default starting sector
        lda             #0                                                              ; r1 = sector number (#0)
        lda             #0                                                              ; r1 = sector number (#0)
        ldx             #SECTOR_BUF<<2                                  ; r2 = target address (word to byte address)
        ldx             #BYTE_SECTOR_BUF                                ; r2 = target address (word to byte address)
        jsr             spi_read_sector
        jsr             spi_read_sector
        cmp             #0
        cmp             #0
        bne             spi_rp1
        bne             spi_rp1
        lb              r1,BYTE_SECTOR_BUF+$1C9
        lb              r1,BYTE_SECTOR_BUF+$1C9
        asl             r1,r1,#8
        asl             r1,r1,#8
Line 1493... Line 3396...
        lda             #1
        lda             #1
        rts
        rts
 
 
; Read the boot sector from the disk.
; Read the boot sector from the disk.
; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.
; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.
 
; Returns:
 
; r1 = 0 means this card is bootable
 
; r1 = 1 means a read error occurred
 
; r1 = 2 means the card is not bootable
;
;
spi_read_boot:
spi_read_boot:
        phx
        phx
        phy
        phy
        push    r5
        push    r5
        lda             startSector                                     ; r1 = sector number
        lda             startSector                                     ; r1 = sector number
        ldx             #BYTE_SECTOR_BUF                        ; r2 = target address
        ldx             #BYTE_SECTOR_BUF                        ; r2 = target address
        jsr             spi_read_sector
        jsr             spi_read_sector
 
        cmp             #0
 
        bne             spi_read_boot_err
        lb              r1,BYTE_SECTOR_BUF
        lb              r1,BYTE_SECTOR_BUF
        cmp             #$EB
        cmp             #$EB
        beq             spi_read_boot2
        bne             spi_eb_err
spi_read_boot3:
 
        lda             #1                                                      ; r1 = 1 for error
 
        bra             spi_read_boot4
 
spi_read_boot2:
spi_read_boot2:
        lda             #msgFoundEB
        lda             #msgFoundEB
        jsr             DisplayStringB
        jsr             DisplayStringB
        lb              r1,BYTE_SECTOR_BUF+$1FE         ; check for 0x55AA signature
        lb              r1,BYTE_SECTOR_BUF+$1FE         ; check for 0x55AA signature
        cmp             #$55
        cmp             #$55
        bne             spi_read_boot3
        bne             spi_eb_err
        lb              r1,BYTE_SECTOR_BUF+$1FF         ; check for 0x55AA signature
        lb              r1,BYTE_SECTOR_BUF+$1FF         ; check for 0x55AA signature
        cmp             #$AA
        cmp             #$AA
        bne             spi_read_boot3
        bne             spi_eb_err
 
        pop             r5
 
        ply
 
        plx
        lda             #0                                              ; r1 = 0, for okay status
        lda             #0                                              ; r1 = 0, for okay status
spi_read_boot4:
        rts
 
spi_read_boot_err:
 
        pop             r5
 
        ply
 
        plx
 
        lda             #1
 
        rts
 
spi_eb_err:
 
        lda             #msgNotFoundEB
 
        jsr             DisplayStringB
        pop             r5
        pop             r5
        ply
        ply
        plx
        plx
 
        lda             #2
        rts
        rts
 
 
msgFoundEB:
msgFoundEB:
        db      "Found EB code.",CR,LF,0
        db      "Found EB code.",CR,LF,0
 
msgNotFoundEB:
 
        db      "EB/55AA Code missing.",CR,LF,0
 
 
; Load the root directory from disk
; Load the root directory from disk
; r2 = where to place root directory in memory
; r2 = where to place root directory in memory
;
;
loadBootFile:
loadBootFile:
Line 1572... Line 3492...
        jsr             spi_read_sector
        jsr             spi_read_sector
        inc             r5                                              ; r5 = next sector
        inc             r5                                              ; r5 = next sector
        add             r2,r2,#512
        add             r2,r2,#512
        dec             r3
        dec             r3
        bne             loadBootFile1
        bne             loadBootFile1
        lda             (PROG_LOAD_AREA>>2)+$80 ; make sure it's bootable
        lda             PROG_LOAD_AREA>>2               ; make sure it's bootable
        cmp             #$544F4F42
        cmp             #$544F4F42
        bne             loadBootFile2
        bne             loadBootFile2
        lda             #msgJumpingToBoot
        lda             #msgJumpingToBoot
        jsr             DisplayStringB
        jsr             DisplayStringB
        lda             (PROG_LOAD_AREA>>2)+$81
        lda             (PROG_LOAD_AREA>>2)+$1
        jsr             (r1)
        jsr             (r1)
        jmp             Monitor
        jmp             Monitor
loadBootFile2:
loadBootFile2:
        lda             #msgNotBootable
        lda             #msgNotBootable
        jsr             DisplayStringB
        jsr             DisplayStringB
Line 1599... Line 3519...
spi_init_ok_msg:
spi_init_ok_msg:
        db "SD card initialized okay.",0
        db "SD card initialized okay.",0
spi_init_error_msg:
spi_init_error_msg:
        db      ": error occurred initializing the SD card.",0
        db      ": error occurred initializing the SD card.",0
spi_boot_error_msg:
spi_boot_error_msg:
        db      "SD card boot error",0
        db      "SD card boot error",CR,LF,0
spi_read_error_msg:
spi_read_error_msg:
        db      "SD card read error",0
        db      "SD card read error",CR,LF,0
spi_write_error_msg:
spi_write_error_msg:
        db      "SD card write error",0
        db      "SD card write error",0
 
 
 
;==============================================================================
 
; Ethernet
 
;==============================================================================
 
my_MAC1 EQU     0x00
 
my_MAC2 EQU     0xFF
 
my_MAC3 EQU     0xEE
 
my_MAC4 EQU     0xF0
 
my_MAC5 EQU     0xDA
 
my_MAC6 EQU     0x42
 
 
 
; Initialize the ethmac controller.
 
; Supply a MAC address, set MD clock
 
;
 
message "eth_init"
 
eth_init:
 
        pha
 
        phy
 
        ldy             #ETHMAC
 
        lda             #0x64                           ; 100
 
        sta             ETH_MIIMODER,y
 
        lda             #7                                      ; PHY address
 
        sta             ETH_MIIADDRESS,y
 
        lda             #0xEEF0DA42
 
        sta             ETH_MAC_ADDR0,y         ; MAC0
 
        lda             #0x00FF
 
        sta             ETH_MAC_ADDR1,y         ; MAC1
 
        ply
 
        pla
 
        rts
 
 
 
; Request a packet and display on screen
 
; r1 = address where to put packet
 
;
 
message "eth_request_packet"
 
eth_request_packet:
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        ldy             #ETHMAC
 
        ldx             #4                                      ; clear rx interrupt
 
        stx             ETH_INT_SOURCE,y
 
        sta             0x181,y                         ; storage address
 
        ldx             #0xe000                         ; enable interrupt
 
        stx             0x180,y
 
eth1:
 
        nop
 
        ldx             ETH_INT_SOURCE,y
 
        and             r2,r2,#4                        ; get bit #2
 
        beq             eth1
 
        ldx             0x180,y                         ; get from descriptor
 
        lsr             r2,r2,#16
 
        ldy             #0
 
        ld              r4,#TEXTSCR+3780        ; second last line of screen
 
eth20:
 
        add             r5,r1,r3
 
        ldx             (r5)                            ; get byte
 
        add             r5,r4,r3
 
        stx             (r5)                            ; store to screen
 
        iny
 
        cpy             #83
 
        bne             eth20
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
 
 
; r1 = packet address
 
;
 
message "eth_interpret_packet"
 
eth_interpret_packet:
 
        phx
 
        phy
 
        lb              r2,12,r1
 
        lb              r3,13,r1
 
        cpx             #8                                      ; 0x806 ?
 
        bne             eth2
 
        cpy             #6
 
        bne             eth2
 
        lda             #2                                      ; return r1 = 2 for ARP
 
eth5:
 
        ply
 
        plx
 
        rts
 
eth2:
 
        cpx             #8
 
        bne             eth3                            ; 0x800 ?
 
        cpy             #0
 
        bne             eth3
 
        lb              r2,23,r1
 
        cpx             #1
 
        bne             eth4
 
        lda             #1
 
        bra             eth5                            ; return 1 ICMP
 
eth4:
 
        cpx             #$11
 
        bne             eth6
 
        lda             #3                                      ; return 3 for UDP
 
        bra             eth5
 
eth6:
 
        cpx             #6
 
        bne             eth7
 
        lda             #4                                      ; return 4 for TCP
 
        bra             eth5
 
eth7:
 
eth3:
 
        eor             r1,r1,r1                        ; return zero for unknown
 
        ply
 
        plx
 
        rts
 
 
 
; r1 = address of packet to send
 
; r2 = packet length
 
;
 
message "eth_send_packet"
 
eth_send_packet:
 
        phx
 
        phy
 
        push    r4
 
        ldy             #ETHMAC
 
        ; wait for tx buffer to be clear
 
eth8:
 
        ld              r4,0x100,y
 
        and             r4,r4,#$8000
 
        bne             eth8
 
        ld              r4,#1                   ; clear tx interrupt
 
        st              r4,ETH_INT_SOURCE,y
 
        ; set address
 
        sta             0x101,y
 
        ; set the packet length field and enable interrupts
 
        asl             r2,r2,#16
 
        or              r2,r2,#0xF000
 
        stx             0x100,y
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
 
 
; Only for IP type packets (not ARP)
 
; r1 = rx buffer address
 
; r2 = swap flag
 
; Returns:
 
; r1 = data start index
 
;
 
message "eth_build_packet"
 
eth_build_packet:
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        push    r8
 
        push    r9
 
        push    r10
 
 
 
        lb              r3,6,r1
 
        lb              r4,7,r1
 
        lb              r5,8,r1
 
        lb              r6,9,r1
 
        lb              r7,10,r1
 
        lb              r8,11,r1
 
        ; write to destination header
 
        sb              r3,0,r1
 
        sb              r4,1,r1
 
        sb              r5,2,r1
 
        sb              r6,3,r1
 
        sb              r7,4,r1
 
        sb              r8,5,r1
 
        ; write to source header
 
        ld              r3,#my_MAC1
 
        sb              r3,6,r1
 
        ld              r3,#my_MAC2
 
        sb              r3,7,r1
 
        ld              r3,#my_MAC3
 
        sb              r3,8,r1
 
        ld              r3,#my_MAC4
 
        sb              r3,9,r1
 
        ld              r3,#my_MAC5
 
        sb              r3,10,r1
 
        ld              r3,#my_MAC6
 
        sb              r3,11,r1
 
        cmp             r2,#1
 
        bne             eth16                   ; if (swap)
 
        lb              r3,26,r1
 
        lb              r4,27,r1
 
        lb              r5,28,r1
 
        lb              r6,29,r1
 
        ; read destination
 
        lb              r7,30,r1
 
        lb              r8,31,r1
 
        lb              r9,32,r1
 
        lb              r10,33,r1
 
        ; write to sender
 
        sb              r7,26,r1
 
        sb              r8,27,r1
 
        sb              r9,28,r1
 
        sb              r10,29,r1
 
        ; write destination
 
        sb              r3,30,r1
 
        sb              r4,31,r1
 
        sb              r5,32,r1
 
        sb              r6,33,r1
 
eth16:
 
        ldy             eth_unique_id
 
        iny
 
        sty             eth_unique_id
 
        sb              r3,19,r1
 
        lsr             r3,r3,#8
 
        sb              r3,18,r1
 
        lb              r3,14,r1
 
        and             r3,r3,#0xF
 
        asl             r3,r3,#2                ; *4
 
        add             r1,r3,#14               ; return datastart in r1
 
        pop             r10
 
        pop             r9
 
        pop             r8
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        rts
 
 
 
; Compute IPv4 checksum of header
 
; r1 = packet address
 
; r2 = data start
 
;
 
message "eth_checksum"
 
eth_checksum:
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        ; set checksum to zero
 
        stz             24,r1
 
        stz             25,r1
 
        eor             r3,r3,r3                ; r3 = sum = zero
 
        ld              r4,#14
 
eth15:
 
        ld              r5,r2
 
        dec             r5                              ; r5 = datastart - 1
 
        cmp             r4,r5
 
        bpl             eth14
 
        add             r6,r1,r4
 
        lb              r5,0,r6                 ; shi = [rx_addr+i]
 
        lb              r6,1,r6             ; slo = [rx_addr+i+1]
 
        asl     r5,r5,#8
 
        or              r5,r5,r6                ; shilo
 
        add             r3,r3,r5                ; sum = sum + shilo
 
        add             r4,r4,#2                ; i = i + 2
 
        bra             eth15
 
eth14:
 
        ld              r5,r3                   ; r5 = sum
 
        and             r3,r3,#0xffff
 
        lsr             r5,r5,#16
 
        add             r3,r3,r5
 
        eor             r3,r3,#-1
 
        sb              r3,25,r1                ; low byte
 
        lsr             r3,r3,#8
 
        sb              r3,24,r1                ; high byte
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        rts
 
 
 
; r1 = packet address
 
; returns r1 = 1 if this IP
 
;
 
message "eth_verifyIP"
 
eth_verifyIP:
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        lb              r2,30,r1
 
        lb              r3,31,r1
 
        lb              r4,32,r1
 
        lb              r5,33,r1
 
        ; Check for general broadcast
 
        cmp             r2,#$FF
 
        bne             eth11
 
        cmp             r3,#$FF
 
        bne             eth11
 
        cmp             r4,#$FF
 
        bne             eth11
 
        cmp             r5,#$FF
 
        bne             eth11
 
eth12:
 
        lda             #1
 
eth13:
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        rts
 
eth11:
 
        ld              r1,r2
 
        asl             r1,r1,#8
 
        or              r1,r1,r3
 
        asl             r1,r1,#8
 
        or              r1,r1,r4
 
        asl             r1,r1,#8
 
        or              r1,r1,r5
 
        cmp             #$C0A8012A              ; 192.168.1.42
 
        beq             eth12
 
        eor             r1,r1,r1
 
        bra             eth13
 
 
 
message "eth_main"
 
eth_main:
 
        jsr             eth_init
 
eth_loop:
 
        jsr             KeybdGetChar
 
        cmp             #-1
 
        beq             eth17
 
        cmp             #CTRLC
 
        bne             eth17
 
        rts
 
eth17
 
        lda             #eth_rx_buffer<<2               ; memory address zero
 
        jsr             eth_request_packet
 
        jsr             eth_interpret_packet    ; r1 = packet type
 
 
 
        cmp             #1
 
        bne             eth10
 
        ld              r2,r1                                   ; save off r1, r2 = packet type
 
        lda             #eth_rx_buffer<<2               ; memory address zero
 
        jsr             eth_verifyIP
 
        tay
 
        txa                                                             ; r1 = packet type again
 
        cpy             #1
 
        bne             eth10
 
 
 
        lda             #eth_rx_buffer<<2               ; memory address zero
 
        ldx             #1
 
        jsr             eth_build_packet
 
        tay                                                             ; y = icmpstart
 
        lda             #eth_rx_buffer<<2               ; memory address zero
 
        add             r4,r1,r3
 
        sb              r0,0,r4                                 ; [rx_addr+icmpstart] = 0
 
        lb              r2,17,r1
 
        add             r2,r2,#14                               ; r2 = len
 
        ld              r6,r2                                   ; r6 = len
 
        add             r15,r1,r3
 
        lb              r4,2,r15                                ; shi
 
        lb              r5,3,r15                                ; slo
 
        asl             r4,r4,#8
 
        or              r4,r4,r5                                ; sum = {shi,slo};
 
        eor             r4,r4,#-1                               ; sum = ~sum
 
        sub             r4,r4,#0x800                    ; sum = sum - 0x800
 
        eor             r4,r4,#-1                               ; sum = ~sum
 
        add             r15,r1,r3
 
        sb              r4,3,r15
 
        lsr             r4,r4,#8
 
        sb              r4,2,r15
 
        tyx
 
        jsr             eth_checksum
 
        lda             #eth_rx_buffer<<2               ; memory address zero
 
        ld              r2,r6
 
        jsr             eth_send_packet
 
        jmp             eth_loop
 
eth10:
 
        ; r2 = rx_addr
 
        cmp             #2
 
        bne             eth_loop                ; Do we have ARP ?
 
;       xor             r2,r2,r2                        ; memory address zero
 
        ldx             #eth_rx_buffer<<2
 
        ; get the opcode
 
        lb              r13,21,x
 
        cmp             r13,#1
 
        bne             eth_loop                ; ARP request
 
        ; get destination IP address
 
        lb              r9,38,x
 
        lb              r10,39,x
 
        lb              r11,40,x
 
        lb              r12,41,x
 
        ; set r15 = destination IP
 
        ld              r15,r9
 
        asl             r15,r15,#8
 
        or              r15,r15,r10
 
        asl             r15,r15,#8
 
        or              r15,r15,r11
 
        asl             r15,r15,#8
 
        or              r15,r15,r12
 
        ; Is it our IP ?
 
        cmp             r15,#$C0A8012A  ; //192.168.1.42
 
        bne             eth_loop
 
        ; get source IP address
 
        lb              r5,28,x
 
        lb              r6,29,x
 
        lb              r7,30,x
 
        lb              r8,31,x
 
        ; set r14 = source IP
 
        ld              r14,r5
 
        asl             r14,r14,#8
 
        or              r14,r14,r6
 
        asl             r14,r14,#8
 
        or              r14,r14,r7
 
        asl             r14,r14,#8
 
        or              r14,r14,r8
 
        ; Get the source MAC address
 
        push    r6
 
        push    r7
 
        push    r8
 
        push    r9
 
        push    r10
 
        push    r11
 
        lb              r6,22,x
 
        lb              r7,23,x
 
        lb              r8,24,x
 
        lb              r9,25,x
 
        lb              r10,26,x
 
        lb              r11,27,x
 
        ; write to destination header
 
        sb              r6,0,x
 
        sb              r7,1,x
 
        sb              r8,2,x
 
        sb              r9,3,x
 
        sb              r10,4,x
 
        sb              r11,5,x
 
        ; and write to ARP destination
 
        sb              r6,32,x
 
        sb              r7,33,x
 
        sb              r8,34,x
 
        sb              r9,35,x
 
        sb              r10,36,x
 
        sb              r11,37,x
 
        pop             r11
 
        pop             r10
 
        pop             r9
 
        pop             r8
 
        pop             r7
 
        pop             r6
 
        ; write to source header
 
;       stbc    #0x00,6[r2]
 
;       stbc    #0xFF,7[r2]
 
;       stbc    #0xEE,8[r2]
 
;       stbc    #0xF0,9[r2]
 
;       stbc    #0xDA,10[r2]
 
;       stbc    #0x42,11[r2]
 
        sb              r0,6,x
 
        lda             #0xFF
 
        sb              r1,7,x
 
        lda             #0xEE
 
        sb              r1,8,x
 
        lda             #0xF0
 
        sb              r1,9,x
 
        lda             #0xDA
 
        sb              r1,10,x
 
        lda             #0x42
 
        sb              r1,11,x
 
        ; write to ARP source
 
;       stbc    #0x00,22[r2]
 
;       stbc    #0xFF,23[r2]
 
;       stbc    #0xEE,24[r2]
 
;       stbc    #0xF0,25[r2]
 
;       stbc    #0xDA,26[r2]
 
;       stbc    #0x42,27[r2]
 
        sb              r0,22,x
 
        lda             #0xFF
 
        sb              r1,23,x
 
        lda             #0xEE
 
        sb              r1,24,x
 
        lda             #0xF0
 
        sb              r1,25,x
 
        lda             #0xDA
 
        sb              r1,26,x
 
        lda             #0x42
 
        sb              r1,27,x
 
        ; swap sender / destination IP
 
        ; write sender
 
        sb              r9,28,x
 
        sb              r10,29,x
 
        sb              r11,30,x
 
        sb              r12,31,x
 
        ; write destination
 
        sb              r5,38,x
 
        sb              r6,39,x
 
        sb              r7,40,x
 
        sb              r8,41,x
 
        ; change request to reply
 
;       stbc    #2,21[r2]
 
        lda             #2
 
        sb              r1,21,x
 
        txa                                             ; r1 = packet address
 
        ldx             #0x2A                   ; r2 = packet length
 
        jsr             eth_send_packet
 
        jmp             eth_loop
 
 
 
;--------------------------------------------------------------------------
 
; Initialize sprite image caches with random data.
 
;--------------------------------------------------------------------------
 
RandomizeSprram:
 
        ldx             #SPRRAM
 
        ld              r4,#14336               ; number of chars to initialize
 
rsr1:
 
        tsr             LFSR,r1
 
        sta             (x)
 
        inx
 
        dec             r4
 
        bne             rsr1
 
        rts
 
 
 
;--------------------------------------------------------------------------
 
; Draw random lines on the bitmap screen.
 
;--------------------------------------------------------------------------
 
;
 
RandomLines:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        jsr             RequestIOFocus
 
rl5:
 
        tsr             LFSR,r1
 
        tsr             LFSR,r2
 
        jsr             DrawPixel
 
        tsr             LFSR,r1
 
        sta             LineColor               ; select a random color
 
rl1:                                            ; random X0
 
        tsr             LFSR,r1
 
        ld              r5,#1364
 
        mod             r1,r1,r5
 
rl2:                                            ; random X1
 
        tsr             LFSR,r3
 
        mod             r3,r3,r5
 
rl3:                                            ; random Y0
 
        tsr             LFSR,r2
 
        ld              r5,#768
 
        mod             r2,r2,r5
 
rl4:                                            ; random Y1
 
        tsr             LFSR,r4
 
        ld              r5,#768
 
        mod             r4,r4,r5
 
rl8:
 
        jsr             DrawLine
 
        jsr             KeybdGetChar
 
        cmp             #CTRLC
 
        beq             rl7
 
        bra             rl5
 
rl7:
 
        jsr             ReleaseIOFocus
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rts
 
 
 
DrawPixel:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
        ld              r4,#768
 
        mod             r2,r2,r4
 
        ld              r4,#1364
 
        mod             r1,r1,r4
 
        mul             r2,r2,r4        ; y * 1364
 
        add             r1,r1,r2        ; + x
 
        ldy             LineColor
 
        sb              r3,BITMAPSCR<<2,r1
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rts
 
 
 
;50 REM DRAWLINE
 
;100 dx = ABS(xb-xa)
 
;110 dy = ABS(yb-ya)
 
;120 sx = SGN(xb-xa)
 
;130 sy = SGN(yb-ya)
 
;140 er = dx-dy
 
;150 PLOT xa,ya
 
;160 if xa<>xb goto 200
 
;170 if ya=yb goto 300
 
;200 ee = er * 2
 
;210 if ee <= -dy goto 240
 
;220 er = er - dy
 
;230 xa = xa + sx
 
;240 if ee >= dx goto 270
 
;250 er = er + dx
 
;260 ya = ya + sy
 
;270 GOTO 150
 
;300 RETURN
 
 
 
DrawLine:
 
        pha
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        push    r8
 
        push    r9
 
        push    r10
 
        push    r11
 
 
 
        sub             r5,r3,r1        ; dx = abs(x2-x1)
 
        bpl             dln1
 
        sub             r5,r0,r5
 
dln1:
 
        sub             r6,r4,r2        ; dy = abs(y2-y1)
 
        bpl             dln2
 
        sub             r6,r0,r6
 
dln2:
 
 
 
        sub             r7,r3,r1        ; sx = sgn(x2-x1)
 
        beq             dln5
 
        bpl             dln4
 
        ld              r7,#-1
 
        bra             dln5
 
dln4:
 
        ld              r7,#1
 
dln5:
 
 
 
        sub             r8,r4,r2        ; sy = sgn(y2-y1)
 
        beq             dln8
 
        bpl             dln7
 
        ld              r8,#-1
 
        bra             dln8
 
dln7:
 
        ld              r8,#1
 
 
 
dln8:
 
        sub             r9,r5,r6        ; er = dx-dy
 
dln150:
 
        jsr             DrawPixel
 
        cmp             r1,r3           ; if (xa <> xb)
 
        bne             dln200          ;    goto 200
 
        cmp             r2,r4           ; if (ya==yb)
 
        beq             dln300          ;    goto 300
 
dln200:
 
        asl             r10,r9          ; ee = er * 2
 
        sub             r11,r0,r6       ; r11 = -dy
 
        cmp             r10,r11         ; if (ee <= -dy)
 
        bmi             dln240          ;     goto 240
 
        beq             dln240
 
        sub             r9,r9,r6        ; er = er - dy
 
        add             r1,r1,r7        ; xa = xa + sx
 
dln240:
 
        cmp             r10,r5          ; if (ee >= dx)
 
        bpl             dln150          ;    goto 150
 
        add             r9,r9,r5        ; er = er + dx
 
        add             r2,r2,r8        ; ya = ya + sy
 
        bra             dln150          ; goto 150
 
 
 
dln300:
 
        pop             r11
 
        pop             r10
 
        pop             r9
 
        pop             r8
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        pla
 
        rts
 
 
 
;include "float.asm"
 
 
 
;------------------------------------------------------------------------------
 
; Bus Error Routine
 
; This routine display a message then restarts the BIOS.
 
;------------------------------------------------------------------------------
 
;
 
message "bus_err_rout"
 
bus_err_rout:
 
        cld
 
        pla                                                     ; get rid of the stacked flags
 
        ply                                                     ; get the error PC
 
        ldx             #$05FFFFF8                      ; setup stack pointer top of memory
 
        txs
 
        jsr             CRLF
 
        lda             #msgBusErr
 
        jsr             DisplayStringB
 
        tya
 
        jsr             DisplayWord                     ; display the originating PC address
 
        lda             #msgDataAddr
 
        jsr             DisplayStringB
 
        tsr             #9,r1
 
        jsr             DisplayWord
 
        cli                                                     ; enable interrupts so we can get a char
 
        jsr             KeybdGetChar
 
        jmp             start
 
 
 
msgBusErr:
 
        db              "Bus error at: ",0
 
msgDataAddr:
 
        db              " data address: ",0
 
 
 
strStartQue:
 
        db              1,0,0,0,2,0,0,0,3,1,0,0,4,0,0,0
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; 100 Hz interrupt
; 100 Hz interrupt
; - takes care of "flashing" the cursor
; - takes care of "flashing" the cursor
 
; - switching tasks
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
p100Hz:
p100Hz:
        inc             IRQFlag                 ; support tiny basic's IRQ rout
        ; Handle every other interrupt because 100Hz interrupts may be too fast.
        inc             TEXTSCR+83
        pha
 
        lda             IRQFlag
 
        ina
 
        sta             IRQFlag
 
        ror
 
        bcc             p100Hz11
 
        pla
 
        rti
 
 
 
p100Hz11:
 
 
 
        cld             ; clear extended precision mode
 
 
 
        ; save off regs on the stack
 
        phx
 
        phy
 
        push    r4
 
        push    r5
 
        push    r6
 
        push    r7
 
        push    r8
 
        push    r9
 
        push    r10
 
        push    r11
 
        push    r12
 
        push    r13
 
        push    r14
 
        push    r15
 
        ldx             RunningTCB
 
        and             r2,r2,#$FF
 
        tsa                                             ; save off the stack pointer
 
        sta             TCB_SPSave,x
 
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
 
        sta             TCB_SP8Save,x
 
 
 
        ; support EhBASIC's IRQ functionality
 
        ; code derived from minimon.asm
 
        lda             #3                              ; Timer is IRQ #3
 
        sta             IrqSource               ; stuff a byte indicating the IRQ source for PEEK()
 
        lb              r1,IrqBase              ; get the IRQ flag byte
 
;       ora             #$20                    ; set IRQ pending bit
 
        lsr             r2,r1
 
        or              r1,r1,r2
 
        and             #$E0
 
        sb              r1,IrqBase
 
 
 
 
 
        inc             TEXTSCR+83              ; update IRQ live indicator on screen
        stz             0xFFDCFFFC              ; clear interrupt
        stz             0xFFDCFFFC              ; clear interrupt
 
 
 
        ; flash the cursor
 
        lda             CursorFlash             ; test if we want a flashing cursor
 
        beq             p100Hz1a
 
        jsr             CalcScreenLoc   ; compute cursor location in memory
 
        tay
 
        lda             $10000,y                ; get color code $10000 higher in memory
 
        ldx             IRQFlag                 ; get counter
 
        lsr             r2,r2
 
        and             r2,r2,#$0F              ; limit to low order nybble
 
        and             #$F0                    ; prepare to or in new value, mask off foreground color
 
        or              r1,r1,r2                ; set new foreground color for cursor
 
        sta             $10000,y                ; store the color code back to memory
 
p100Hz1a
 
 
 
        ; Check the timeout list to see if there are items ready to be removed from
 
        ; the list. Also decrement the timeout of the item at the head of the list.
 
 
 
p100Hz15:
 
        ldx             TimeoutList
 
        bmi             p100Hz12                                ; are there any entries in the timeout list ?
 
        lda             TCB_Timeout,x
 
        bne             p100Hz14                                ; has this entry timed out ?
 
        txa
 
        jsr             RemoveFromTimeoutList
 
        jsr             AddTaskToReadyList
 
        bra             p100Hz15                                ; go back and see if there's another task to be removed
 
 
 
p100Hz14:
 
        dea                                                             ; decrement the entries timeout
 
        sta             TCB_Timeout,x
 
 
 
p100Hz12:
 
SelectTaskToRun:
 
        ; Search the ready queues for a ready task.
 
        ; The search is occasionally started at a lower priority queue in order
 
        ; to prevent starvation of lower priority tasks. This is managed by
 
        ; using a tick count as an index to a string containing the start que.
 
 
 
        ld              r6,#5                   ; number of queues to search
 
        ldy             IRQFlag                 ; use the IRQFlag as a buffer index
 
        lsr             r3,r3,#1                ; the LSB is always the same
 
        and             r3,r3,#$0F              ; counts from 0 to 15
 
        lb              r3,strStartQue,y        ; get the queue to start search at
 
p100Hz2:
 
        lda             HeadRdy0,y
 
        bmi             p100Hz1
 
        ; Move the head of the ready queue to the tail
 
        jsr             RemoveTaskFromReadyList ; remove task
 
        jsr             AddTaskToReadyList              ; add it back (automatically goes to tail spot)
 
        ldx             TCB_Status,r1           ; the task is no longer running
 
        and             r2,r2,#~TS_RUNNING
 
        stx             TCB_Status,r1
 
        lda             HeadRdy0,y
 
        sta             RunningTCB
 
        ldx             TCB_Status,r1           ; flag the task as the running task
 
        or              r2,r2,#TS_RUNNING
 
        stx             TCB_Status,r1
 
        bra             p100Hz3
 
p100Hz1:
 
        iny
 
        cpy             #5
 
        bne             p100Hz5
 
        ldy             #0
 
p100Hz5
 
        dec             r6
 
        bne             p100Hz2
 
 
 
        ; here there were no tasks ready
 
        stz             RunningTCB                      ; select BIOS task
 
        ldx             TCB_Status              ; flag the task as the running task
 
        or              r2,r2,#TS_RUNNING
 
        stx             TCB_Status
 
p100Hz3:
 
p100Hz10
 
        ldx             RunningTCB
 
        and             r2,r2,#$FF
 
        lda             TCB_SP8Save,x           ; get back eight bit stack pointer
 
        trs             r1,sp8
 
        ldx             TCB_SPSave,x            ; get back stack pointer
 
        txs
 
        ; restore registers
 
        pop             r15
 
        pop             r14
 
        pop             r13
 
        pop             r12
 
        pop             r11
 
        pop             r10
 
        pop             r9
 
        pop             r8
 
        pop             r7
 
        pop             r6
 
        pop             r5
 
        pop             r4
 
        ply
 
        plx
 
        pla
        rti
        rti
 
 
 
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; 1000 Hz interrupt
; 1000 Hz interrupt
; This IRQ must be fast.
; This IRQ must be fast.
; Increments the millisecond counter, and switches to the next context
; Increments the millisecond counter
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;
;
p1000Hz:
p1000Hz:
        stz             0xFFDCFFFD                              ; acknowledge interrupt
        stz             0xFFDCFFFD                              ; acknowledge interrupt
        inc             Milliseconds                    ; increment milliseconds count
        inc             Milliseconds                    ; increment milliseconds count

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.