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

Subversion Repositories rtf65002

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /rtf65002
    from Rev 27 to Rev 28
    Reverse comparison

Rev 27 → Rev 28

/trunk/software/asm/bootrom.asm
56,7 → 56,7
TS_NONE =0
TS_TIMEOUT =1
TS_WAITMSG =2
TS_PREEMP =4
TS_PREEMPT =4
TS_RUNNING =8
TS_READY =16
TS_WAITFOCUS = 32
132,6 → 132,12
CONFIGREC EQU 0xFFDCFFF0
CR_CLOCK EQU 0xFFDCFFF4
GACCEL EQU 0xFFDAE000
AC97 EQU 0xFFDC1000
PSG EQU 0xFFD50000
PSGFREQ0 EQU 0xFFD50000
PSGPW0 EQU 0xFFD50001
PSGCTRL0 EQU 0xFFD50002
PSGADSR0 EQU 0xFFD50003
 
ETHMAC EQU 0xFFDC2000
ETH_MODER EQU 0x00
167,9 → 173,8
 
BYTE_SECTOR_BUF EQU SECTOR_BUF<<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
 
203,13 → 208,15
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
TCB_iof_next EQU 0x05FBD600
TCB_iof_prev EQU 0x05FBD700
TCB_SP8Save EQU 0x05FBD800 ; TCB_SP8Save area
TCB_SPSave EQU 0x05FBD900 ; TCB_SPSave area
 
KeybdHead EQU 0x05FBEA00
KeybdTail EQU 0x05FBEB00
219,20 → 226,20
KeybdLocks EQU 0x05FBEF00
KeybdBuffer EQU 0x05FBF000 ; buffer is 16 chars
 
IOFocusList EQU 0x05FBD000
; Bitmap of tasks requesting the I/O focus
;
IOFocusTbl EQU 0x05FBD000
 
 
; BIOS vars at the top of the 8kB scratch memory
; EhBASIC vars:
;
NmiBase EQU 0xDC
IrqBase EQU 0xDF
 
; BIOS vars at the top of the 8kB scratch memory
;
; TinyBasic AREA = 0xF00 to 0xF7F
 
 
 
; TinyBasic AREA = 0x700 to 0x77F
 
HeadRdy0 EQU 0x780
HeadRdy0 EQU 0xF80
HeadRdy1 EQU HeadRdy0+1
HeadRdy2 EQU HeadRdy1+1
HeadRdy3 EQU HeadRdy2+1
250,53 → 257,59
FreeMsg EQU nMailbox + 1
nMsgBlk EQU FreeMsg + 1
 
IrqSource EQU 0x798
; The IO focus list is a doubly linked list formed into a ring.
;
IOFocusNdx EQU nMsgBlk + 1
 
JMPTMP EQU 0x7A0
SRSave EQU 0x7AF
R1Save EQU 0x7B0
R2Save EQU 0x7B1
R3Save EQU 0x7B2
R4Save EQU 0x7B3
R5Save EQU 0x7B4
R6Save EQU 0x7B5
R7Save EQU 0x7B6
R8Save EQU 0x7B7
R9Save EQU 0x7B8
R10Save EQU 0x7B9
R11Save EQU 0x7BA
R12Save EQU 0x7BB
R13Save EQU 0x7BC
R14Save EQU 0x7BD
R15Save EQU 0x7BE
IrqSource EQU 0xF98
 
CharColor EQU 0x7C0
ScreenColor EQU 0x7C1
CursorRow EQU 0x7C2
CursorCol EQU 0x7C3
CursorFlash EQU 0x7C4
Milliseconds EQU 0x7C5
IRQFlag EQU 0x7C6
RdyQueTick EQU 0x7C7
eth_unique_id EQU 0x7C8
LineColor EQU 0x7C9
JMPTMP EQU 0xFA0
SP8Save EQU 0xFAE
SRSave EQU 0xFAF
R1Save EQU 0xFB0
R2Save EQU 0xFB1
R3Save EQU 0xFB2
R4Save EQU 0xFB3
R5Save EQU 0xFB4
R6Save EQU 0xFB5
R7Save EQU 0xFB6
R8Save EQU 0xFB7
R9Save EQU 0xFB8
R10Save EQU 0xFB9
R11Save EQU 0xFBA
R12Save EQU 0xFBB
R13Save EQU 0xFBC
R14Save EQU 0xFBD
R15Save EQU 0xFBE
SPSave EQU 0xFBF
 
CharColor EQU 0xFC0
ScreenColor EQU 0xFC1
CursorRow EQU 0xFC2
CursorCol EQU 0xFC3
CursorFlash EQU 0xFC4
Milliseconds EQU 0xFC5
IRQFlag EQU 0xFC6
RdyQueTick EQU 0xFC7
eth_unique_id EQU 0xFC8
LineColor EQU 0xFC9
 
Uart_rxfifo EQU 0x05FBC000
Uart_rxhead EQU 0x7D0
Uart_rxtail EQU 0x7D1
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
Uart_rxhead EQU 0xFD0
Uart_rxtail EQU 0xFD1
Uart_ms EQU 0xFD2
Uart_rxrts EQU 0xFD3
Uart_rxdtr EQU 0xFD4
Uart_rxxon EQU 0xFD5
Uart_rxflow EQU 0xFD6
Uart_fon EQU 0xFD7
Uart_foff EQU 0xFD8
Uart_txrts EQU 0xFD9
Uart_txdtr EQU 0xFDA
Uart_txxon EQU 0xFDB
Uart_txxonoff EQU 0xFDC
 
startSector EQU 0x7F0
startSector EQU 0xFF0
 
 
cpu rtf65002
316,6 → 329,7
dw HomeCursor
dw ExitTask
dw SetKeyboardEcho
dw Sleep
 
org $FFFFC200 ; leave room for 128 vectors
message "cold start point"
373,6 → 387,7
stz RunningTCB ; the BIOS task is the running task
 
sta TimeoutList ; no entries in timeout list
sta IOFocusNdx
stz HeadRdy0 ; task zero (the BIOS task) is always present
sta HeadRdy1
sta HeadRdy2
388,11 → 403,20
;
ldx #0
st5:
stz IOFocusList,x
stz IOFocusTbl,x
inx
cpx #8
bne st5
 
ldx #0
lda #-1
st9:
sta TCB_iof_next,x
sta TCB_iof_prev,x
inx
cpx #256
bne st9
 
; Initialize free message list
lda #8192
sta nMsgBlk
438,8 → 462,6
lda #-1
sta TCB_NxtTCB+255
 
stz INPUT_FOCUS
stz OUTPUT_FOCUS
lda #1
sta MBX_SEMA
sta IOF_LIST_SEMA
452,9 → 474,13
sta CursorFlash
jsr ClearScreen
jsr ClearBmpScreen
lda CONFIGREC ; do we have sprites ?
bit #1
beq st8
lda #$3FFF ; turn on sprites
sta SPRITEREGS+120
jsr RandomizeSprram
st8:
jsr HomeCursor
lda #msgStart
jsr DisplayStringB
461,11 → 487,15
jsr KeybdInit
lda #1
sta KeybdEcho
lda CONFIGREC ; do we have a serial port ?
bit #32
beq st7
; 19200 * 16
;-------------
; 25MHz / 2^32
lda #$03254E6E ; constant for 19,200 baud at 25MHz
; jsr SerialInit
jsr SerialInit
st7:
lda #4
ldx #0
ldy #IdleTask
472,6 → 502,15
jsr StartTask
jsr PICInit
cli ; enable interrupts
; The following must be after interrupts are enabled.
; The AC97 setup uses the millisecond counter and the
; keyboard.
lda CONFIGREC ; do we have a sound generator ?
bit #4
beq st6
jsr SetupAC97
jsr Beep
st6:
jmp Monitor
st1
jsr KeybdGetCharDirect
567,6 → 606,48
db CR,LF,"Pri Task Stat Prv Nxt Timeout",CR,LF,0
 
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
message "DumpIOFocusList"
DumpIOFocusList:
pha
phx
phy
php
sei
lda #msgIOFocusList
jsr DisplayStringB
lda IOFocusNdx
diofl2:
bmi diofl1
tay
ldx #3
jsr PRTNUM
lda #' '
jsr DisplayChar
lda TCB_iof_prev,y
ldx #3
jsr PRTNUM
lda #' '
jsr DisplayChar
lda TCB_iof_next,y
ldx #3
jsr PRTNUM
jsr CRLF
lda TCB_iof_next,y
cmp IOFocusNdx
bne diofl2
diofl1:
plp
ply
plx
pla
rts
msgIOFocusList:
db CR,LF,"Task Prv Nxt",CR,LF,0
;------------------------------------------------------------------------------
; IdleTask is a low priority task that is always running. It runs when there
; is nothing else to run.
;------------------------------------------------------------------------------
659,7 → 740,8
 
;------------------------------------------------------------------------------
; This routine is called when the task exits with an rts instruction. OR
; it may be invoked with a JMP ExitTask.
; it may be invoked with a JMP ExitTask. In either case the task must be
; running so it can't be on the timeout list.
;------------------------------------------------------------------------------
message "ExitTask"
ExitTask:
670,7 → 752,8
lda RunningTCB
jsr RemoveTaskFromReadyList
stz TCB_Status,r1 ; set task status to TS_NONE
ldx FreeTCB
jsr ReleaseIOFocus
ldx FreeTCB ; add the task control block to the free list
stx TCB_NxtTCB,r1
sta FreeTCB
jmp SelectTaskToRun
685,6 → 768,7
;------------------------------------------------------------------------------
message "AddTaskToReadyList"
AddTaskToReadyList:
pha
phx
phy
php
694,26 → 778,34
bpl arl3
arl2:
ldx TCB_Status,r1 ; set the task status to ready
bit r2,#TS_READY ; is the task already on the ready list ?
bne arl3
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
bmi arl1 ; if no tail, then either the list is screwed up, or no tasks are on it.
sta TCB_NxtRdy,x ; add as next ready on tail
arl4:
stx TCB_PrvRdy,r1 ; the old tail is the previous task on the list now.
sta TailRdy0,y ; update with new tail
ldx #-1
stx TCB_NxtRdy,r1
stx TCB_NxtRdy,r1 ; There is no next ready task to the tail.
ldx HeadRdy0,y ; check if the head of the ready list needs to be updated
bpl arl3
sta HeadRdy0,y
ldx #-1
sta HeadRdy0,y ; Update the head of the ready list.
ldx #-1 ; There is no previous task at the head.
stx TCB_PrvRdy,r1
arl3:
plp
ply
plx
pla
rts
; Here the tail of the ready list needed to be updated. Flag no prior task.
arl1:
ldx #-1
bra arl4
 
 
;------------------------------------------------------------------------------
; RemoveTaskFromReadyList
; This subroutine removes a task from the ready list.
728,6 → 820,7
cmp #255 ; and must be <= 255
bpl rfr9
pha
phx
phy
push r4
push r5
734,6 → 827,9
 
php ; save off interrupt mask state
sei
ld r4,TCB_Status,r1 ; check if the task is even on the ready list
bit r4,#TS_READY
beq rfr2 ; not on ready list, then we're done
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.
741,6 → 837,7
cmp r4,#0 ; is there a next task to update ?
bmi rfr8
st r5,TCB_PrvRdy,r4
rfr4:
ld r5,#-1
st r5,TCB_NxtRdy,r1
st r5,TCB_PrvRdy,r1
751,26 → 848,44
ldy TCB_Priority,r1
st r4,HeadRdy0,y
cmp r4,#0 ; did we empty the list ?
bmi rfr8
bmi rfr3
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:
ldx TCB_Status,r1 ; set the task status to no longer ready.
and r2,r2,#~TS_READY
stx TCB_Status,r1
rfr2:
plp
pop r5
pop r4
ply
plx
pla
rfr9:
rts
rfr3:
st r4,TailRdy0,y ;
bra rfr4
 
;------------------------------------------------------------------------------
; r1 = task
; r2 = timeout value
; AddToTimeoutList
; AddToTimeoutList adds a task to the timeout list. The task is placed in the
; list depending on it's timeout value.
;
; Parameters:
; r1 = task
; r2 = timeout value
;------------------------------------------------------------------------------
message "AddToTimeoutList"
AddToTimeoutList:
cmp #0 ; quickly validate the task number
bmi attl4 ; must be between 0 and 255
cmp #255
bpl attl4
 
phx
push r4
push r5
829,21 → 944,29
stx TCB_NxtRdy,r1 ; no next entries
stx TCB_PrvRdy,r1 ; and no prev entries
attl_exit:
ldx TCB_Status,r1 ; set the task's status as timing out
or r2,r2,#TS_TIMEOUT
stx TCB_Status,r1
plp
pop r5
pop r4
plx
attl4:
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.
; This subroutine is called from within the timer ISR when the task's
; timeout expires.
;
; r1 = task number
;------------------------------------------------------------------------------
message "RemoveFromTimeoutList"
RemoveFromTimeoutList:
cmp #0 ; quickly validate the task number
bmi rft4 ; must be between 0 and 255
cmp #255
bpl rft4
 
pha
phx
push r4
871,19 → 994,44
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
ld r4,TCB_Timeout,r1 ; add any remaining timeout to the timeout
add r4,r4,TCB_Timeout,r5 ; of the next task on the list.
st r4,TCB_Timeout,r5
ld r4,#-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:
ldx TCB_Status,r1 ; set the task status to not timing out
and r2,r2,#~TS_TIMEOUT
stx TCB_Status,r1
plp
pop r5
pop r4
plx
pla
rft4:
rts
 
;------------------------------------------------------------------------------
; Parameters:
; r1 = time duration in centi-seconds
;------------------------------------------------------------------------------
Sleep:
tax
sei
lda RunningTCB
jsr RemoveTaskFromReadyList
jsr AddToTimeoutList
ldx #SleepRet ; The scheduler will be returning to this
jmp PushRegsAndRunTask ; task eventually, once the timeout expires,
; so fake an interrupt call
SleepRet:
cli
rts
 
;------------------------------------------------------------------------------
; Allocate a mailbox
; r1 = pointer to place to store handle
;------------------------------------------------------------------------------
1195,6 → 1343,7
jsr AddToTimeoutList
wmsg10:
ld r2,#wmsg8 ; save the return address
PushRegsAndRunTask:
phx
php ; save status register
pha ; and save the register set
1300,7 → 1449,7
jsr DequeueMsgFromMbx
bra cmsg4
cmsg3:
lda MBX_MQ_HEAD,r1
lda MBX_MQ_HEAD,r1 ; peek the message at the head of the messages queue
cmsg4:
cmp #0
bmi cmsg5
1349,12 → 1498,15
rts
 
;------------------------------------------------------------------------------
; r1 = task number
; r2 = timeout
;------------------------------------------------------------------------------
PutTaskToSleep:
jsr RemoveTaskFromReadyList
jsr AddToTimeoutList
SetIOFocusBit:
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 IOFocusTbl,x
or r1,r1,r3
sta IOFocusTbl,x
rts
 
;------------------------------------------------------------------------------
1369,20 → 1521,55
phy
php
sei
ldx RunningTCB
ldy IOFocusNdx ; Is the focus list empty ?
bmi riof2
cpx IOFocusNdx ; does the task already have the focus ?
beq riof4
lda TCB_Status,x ; update the task status to waiting for focus
or #TS_WAITFOCUS
sta TCB_Status,x
riof4:
lda TCB_iof_next,x ; is the task already in the IO focus list ?
bpl riof3
lda IOFocusNdx ; Expand the list
ldy TCB_iof_prev,r1
stx TCB_iof_prev,r1
sta TCB_iof_next,x
sty TCB_iof_prev,x
stx TCB_iof_next,y
riof3:
jsr SetIOFocusBit
 
; If the task doesn't have the I/O focus, then remove it
; from the ready list.
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
cpx IOFocusNdx
beq riof5
txa
jsr RemoveTaskFromReadyList
riof5:
plp
ply
plx
pla
rts
 
; Here, the IO focus list was empty. So expand it.
; Update pointers to loop back to self.
riof2:
stx IOFocusNdx
stx TCB_iof_next,x
stx TCB_iof_prev,x
lda TCB_Status,x
and #~TS_WAITFOCUS
sta TCB_Status,x
bra riof3
 
;------------------------------------------------------------------------------
; Releasing the I/O focus causes the focus to switch if the running task
; had the I/O focus.
;------------------------------------------------------------------------------
message "ReleaseIOFocus"
ReleaseIOFocus:
pha
1390,15 → 1577,39
phy
php
sei
ldx RunningTCB
ldx RunningTCB
phx
lda TCB_Status,x ; set the task status as no longer waiting for
and r1,r1,#~TS_WAITFOCUS ; focus
sta TCB_Status,x
ldy #1
and r1,r2,#$1F ; get bit index 0 to 31
ldy #1
asl r3,r3,r1 ; shift bit to proper place
eor r3,r3,#-1 ; invert bit mask
lsr r2,r2,#5 ; get word index /32 bits per word
lda IOFocusList,x
lda IOFocusTbl,x
and r1,r1,r3
sta IOFocusList,x
sta IOFocusTbl,x
plx
cpx IOFocusNdx ; Does the running task have the I/O focus ?
bne rliof1
jsr SwitchIOFocus ; If so, then switch the focus.
rliof1:
lda TCB_iof_next,x ; get next and previous fields.
bmi rliof2 ; Is the task on the list ?
ldy TCB_iof_prev,x
sta TCB_iof_next,y ; prev->next = current->next
sty TCB_iof_prev,r1 ; next->prev = current->prev
cmp r1,r3 ; Check if the IO focus list is collapsing.
bne rliof2 ; If the list just points back to the task
cmp r1,r2 ; being removed, then it's the last task
bne rliof2 ; removed from the list, so the list is being
lda #-1 ; emptied.
sta IOFocusNdx
rliof2:
lda #-1 ; Update the next and prev fields to indicate
sta TCB_iof_next,x ; the task is no longer on the list.
sta TCB_iof_prev,x
plp
ply
plx
1409,7 → 1620,7
;------------------------------------------------------------------------------
GetScreenLocation:
lda RunningTCB
cmp OUTPUT_FOCUS
cmp IOFocusNdx
beq gsl1
asl r1,r1,#13 ; 8192 words per screen
add r1,r1,#BIOS_SCREENS
1420,7 → 1631,7
 
GetColorCodeLocation:
lda RunningTCB
cmp OUTPUT_FOCUS
cmp IOFocusNdx
beq gccl1
asl r1,r1,#13 ; 8192 words per screen
add r1,r1,#BIOS_SCREENS+4096
1436,8 → 1647,10
pha
phx
phy
push r4
lda #4095 ; number of words to copy-1
ldx OUTPUT_FOCUS ; compute virtual screen location
ldx IOFocusNdx ; compute virtual screen location
bmi cvss3
asl r2,r2,#13 ; 8192 words per screen
add r2,r2,#BIOS_SCREENS ; add in screens array base address
ldy #TEXTSCR
1451,7 → 1664,7
bne cvss1
; now copy the color codes
lda #4095
ldx OUTPUT_FOCUS
ldx IOFocusNdx
asl r2,r2,#13
add r2,r2,#BIOS_SCREENS+4096 ; virtual char color array
ldy #TEXTSCR+$10000
1462,6 → 1675,15
iny
dea
bne cvss2
cvss3:
; reset the cursor position in the text controller
ldy IOFocusNdx
ldx TCB_CursorRow,y
lda TEXTREG+TEXT_COLS
mul r2,r2,r1
add r2,r2,TCB_CursorCol,y
stx TEXTREG+TEXT_CURPOS
pop r4
ply
plx
pla
1471,9 → 1693,11
pha
phx
phy
push r4
lda #4095
ldx #TEXTSCR
ldy OUTPUT_FOCUS
ldy IOFocusNdx
bmi csvs3
asl r3,r3,#13
add r3,r3,#BIOS_SCREENS
csvs1:
1485,7 → 1709,7
bne csvs1
lda #4095
ldx #TEXTSCR+$10000
ldy OUTPUT_FOCUS
ldy IOFocusNdx
asl r3,r3,#13
add r3,r3,#BIOS_SCREENS+4096
csvs2:
1495,6 → 1719,8
iny
dea
bne csvs2
csvs3:
pop r4
ply
plx
pla
1670,7 → 1896,7
ldx TEXTREG+TEXT_COLS
mul r2,r2,r1
add r2,r2,TCB_CursorCol,r4
cmp r4,OUTPUT_FOCUS ; update cursor position in text controller
cmp r4,IOFocusNdx ; update cursor position in text controller
bne csl1 ; only for the task with the output focus
stx TEXTREG+TEXT_CURPOS
csl1:
2023,13 → 2249,12
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
ld r4,IOFocusNdx ; get the task with the input focus
 
ldx KEYBD ; get keyboard character
ld r0,KEYBD+1 ; clear keyboard strobe (turns off the IRQ)
2085,7 → 2310,7
tax
and r1,r1,#$1F ; get bit index into word
lsr r2,r2,#5 ; get word index into table
ldy IOFocusList,x
ldy IOFocusTbl,x
lsr r3,r3,r1 ; extract bit
and r1,r3,#1
ply
2094,52 → 2319,59
;------------------------------------------------------------------------------
; SwitchIOFocus
; Switches the IO focus to the next task requesting the I/O focus.
; Destroys acc,x,y
; Switches the IO focus to the next task requesting the I/O focus. This
; routine may be called when a task releases the I/O focus as well as when
; the user presses ALT-TAB on the keyboard.
;------------------------------------------------------------------------------
;
SwitchIOFocus:
pha
phx
; Copy the current task's screen to it's virtual screen buffer.
jsr CopyScreenToVirtualScreen
phy
 
ldy INPUT_FOCUS
lda TCB_Status,y
; First check if it's even possible to switch the focus to another
; task. The I/O focus list could be empty or there may be only a
; single task in the list. In either case it's not possible to
; switch.
ldy IOFocusNdx ; Get the task at the head of the list.
bmi siof3 ; Is the list empty ?
lda TCB_iof_next,y ; Get the next task on the list.
cmp r1,r3 ; Will the list head change ?
beq siof3 ; If not then no switch will occur
; Check if outgoing task still wants the focus. If the task doesn't
; want the focus there's no reason to set the status as waiting or
; remove it from the ready list.
tya
jsr GetIOFocusBit ; don't set the 'waiting for focus' status
cmp #0 ; if not.
beq siof1
lda TCB_Status,y ; Set outgoing task status to 'waiting for focus'
or r1,r1,#TS_WAITFOCUS
sta TCB_Status,y
tya
tya ; The outgoing task will now be waiting for the focus
jsr RemoveTaskFromReadyList
siof1:
; Copy the current task's screen to it's virtual screen buffer.
jsr CopyScreenToVirtualScreen
 
; 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
lda TCB_iof_next,y ; Get the next task on the list.
sta IOFocusNdx ; Make task the new head of list.
tay
lda TCB_Status,y
beq siof2 ; Check: task is exiting (status==0) so don't add it back
and #~TS_WAITFOCUS ; to the ready list.
sta TCB_Status,y
tya
jsr AddTaskToReadyList
 
siof2:
; Copy the virtual screen of the task recieving the I/O focus to the
; text screen.
jsr CopyVirtualScreenToScreen
siof3:
ply
plx
pla
rts
;------------------------------------------------------------------------------
2171,10 → 2403,10
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
; Flush the keyboard buffer
lsr r4,r4,#4
stz KeybdTail,r4
stz KeybdHead,r4
bra nochar
kgc4:
and r1,r1,#$ff ; mask off control bits
2676,8 → 2908,9
Monitor:
ldx #BIOS_STACKS+0x03FF ; setup stack pointer
txs
ldx RunningTCB
stz KeybdEcho,x ; turn off keyboard echo
lda #0 ; turn off keyboard echo
jsr SetKeyboardEcho
jsr RequestIOFocus
PromptLn:
jsr CRLF
lda #'$'
2686,6 → 2919,7
; Get characters until a CR is keyed
;
Prompt3:
jsr RequestIOFocus
; lw r1,#2 ; get keyboard character
; syscall #417
; jsr KeybdCheckForKeyDirect
2731,7 → 2965,17
bra DumpMem
Prompt8:
cmp #'F'
beq FillMem
bne Prompt7
lda (y)
iny
jsr ScreenToAscii
cmp #'L'
bne Prompt8a
jsr DumpIOFocusList
jmp Monitor
Prompt8a:
dey
bra FillMem
Prompt7:
cmp #'B' ; $B - start tiny basic
bne Prompt4
2791,6 → 3035,17
Prompt15:
cmp #'S'
bne Prompt16
lda (y)
iny
jsr ScreenToAscii
cmp #'P'
bne Prompt18
jsr ignBlanks
jsr GetHexNumber
sta SPSave
jmp Monitor
Prompt18:
dey
jsr spi_init
cmp #0
bne Monitor
2813,7 → 3068,7
iny
jsr ScreenToAscii
cmp #'S'
beq ReadSector
beq LoadSector
dey
bra SetRegValue
jmp Monitor
2850,6 → 3105,7
db "DR = Dump registers",CR,LF
db "D = Dump memory",CR,LF
db "F = Fill memory",CR,LF
db "FL = Dump I/O Focus List",CR,LF
db "B = start tiny basic",CR,LF
db "b = start EhBasic 6502",CR,LF
db "J = Jump to code",CR,LF
2938,9 → 3194,9
st r14,R14Save
st r15,R15Save
tsr sp,r1
st r1,TCB_SPSave
st r1,SPSave
tsr sp8,r1
st r1,TCB_SP8Save
st r1,SP8Save
pla
sta SRSave
jmp Monitor
3184,7 → 3440,183
 
;==============================================================================
;==============================================================================
;--------------------------------------------------------------------------
; Setup the AC97/LM4550 audio controller. Check keyboard for a CTRL-C
; interrupt which may be necessary if the audio controller isn't
; responding.
;--------------------------------------------------------------------------
;
SetupAC97:
pha
phx
phy
push r4
ld r4,Milliseconds
sac974:
stz AC97+0x26 ; trigger a read of register 26 (status reg)
sac971: ; wait for status to register 0xF (all ready)
ld r3,Milliseconds
sub r3,r3,r4
cmp r3,#1000
bpl sac97Abort
jsr KeybdGetChar ; see if we needed to CTRL-C
cmp #CTRLC
beq sac973
lda AC97+0x68 ; wait for dirty bit to clear
bne sac971
lda AC97+0x26 ; check status at reg h26, wait for
and #0x0F ; analogue to be ready
cmp #$0F
bne sac974
sac973:
stz AC97+2 ; master volume, 0db attenuation, mute off
stz AC97+4 ; headphone volume, 0db attenuation, mute off
stz AC97+0x18 ; PCM gain (mixer) mute off, no attenuation
stz AC97+0x0A ; mute PC beep
lda #0x8000 ; bypass 3D sound
sta AC97+0x20
ld r4,Milliseconds
sac972:
ld r3,Milliseconds
sub r3,r3,r4
cmp r3,#1000
bpl sac97Abort
jsr KeybdGetChar
cmp #CTRLC
beq sac975
lda AC97+0x68 ; wait for dirty bits to clear
bne sac972 ; wait a while for the settings to take effect
sac975:
pop r4
ply
plx
pla
rts
sac97Abort:
lda #msgAC97bad
jsr DisplayStringCRLFB
pop r4
ply
plx
pla
rts
 
msgAC97bad:
db "The AC97 controller is not responding.",CR,LF,0
 
;--------------------------------------------------------------------------
; Sound a 800 Hz beep
;--------------------------------------------------------------------------
;
Beep:
pha
lda #15 ; master volume to max
sta PSG+128
lda #13422 ; 800Hz
sta PSGFREQ0
; decay (16.384 ms)2
; attack (8.192 ms)1
; release (1.024 s)A
; sustain level C
lda #0xCA12
sta PSGADSR0
lda #0x1104 ; gate, output enable, triangle waveform
sta PSGCTRL0
lda #2500000 ; delay about 1s
beep1:
dea
bne beep1
lda #0x0104 ; gate off, output enable, triangle waveform
sta PSGCTRL0
lda #2500000 ; delay about 1s
beep2:
dea
bne beep2
lda #0x0000 ; gate off, output enable off, no waveform
sta PSGCTRL0
pla
rts
 
;--------------------------------------------------------------------------
;--------------------------------------------------------------------------
;
Piano:
lda #15 ; master volume to max
sta PSG+128
playnt:
jsr KeybdGetChar
cmp #CTRLC
beq Monitor
cmp #'a'
beq playnt1a
cmp #'b'
beq playnt1b
cmp #'c'
beq playnt1c
cmp #'d'
beq playnt1d
cmp #'e'
beq playnt1e
cmp #'f'
beq playnt1f
cmp #'g'
beq playnt1g
bra playnt
 
playnt1a:
lda #7217
jsr Tone
bra playnt
playnt1b:
lda #8101
jsr Tone
bra playnt
playnt1c:
lda #4291
jsr Tone
bra playnt
playnt1d:
lda #4817
jsr Tone
bra playnt
playnt1e:
lda #5407
jsr Tone
bra playnt
playnt1f:
lda #5728
jsr Tone
bra playnt
playnt1g:
lda #6430
jsr Tone
bra playnt
 
Tone:
pha
sta PSGFREQ0
; decay (16.384 ms)2
; attack (8.192 ms)1
; release (1.024 s)A
; sustain level C
lda #0xCA12
sta PSGADSR0
lda #0x1104 ; gate, output enable, triangle waveform
sta PSGCTRL0
lda #1 ; delay about 10ms
jsr Sleep
lda #0x0104 ; gate off, output enable, triangle waveform
sta PSGCTRL0
lda #1 ; delay about 10ms
jsr Sleep
lda #0x0000 ; gate off, output enable off, no waveform
sta PSGCTRL0
pla
rts
 
;==============================================================================
;==============================================================================
;
; Initialize the SD card
; Returns
; acc = 0 if successful, 1 otherwise
3367,6 → 3799,30
plx
rts
 
; SPI write multiple sector
;
; r1= sector number to write
; r2= address to get data from
; r3= number of sectors to write
;
; Returns:
; r1 = 0 if successful
;
spi_write_multiple:
push r4
spi_wm1:
pha
jsr spi_write_sector
add r4,r4,r1 ; accumulate an error count
add r2,r2,#512 ; 512 bytes per sector
pla
ina
dey
bne spi_wm1
ld r1,r4
pop r4
rts
; read the partition table to find out where the boot sector is.
; Returns
; r1 = 0 everything okay, 1=read error
4079,10 → 4535,15
pla
rts
 
;--------------------------------------------------------------------------
; Draw a pixel on the bitmap screen.
; r1 = x coordinate
; r2 = y coordinate
; r3 = color
;--------------------------------------------------------------------------
DrawPixel:
pha
phx
phy
push r4
ld r4,#768
mod r2,r2,r4
4090,14 → 4551,15
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
 
;--------------------------------------------------------------------------
; Draw a line on the bitmap screen.
;--------------------------------------------------------------------------
;50 REM DRAWLINE
;100 dx = ABS(xb-xa)
;110 dy = ABS(yb-ya)
4159,7 → 4621,10
dln8:
sub r9,r5,r6 ; er = dx-dy
dln150:
phy
ldy LineColor
jsr DrawPixel
ply
cmp r1,r3 ; if (xa <> xb)
bne dln200 ; goto 200
cmp r2,r4 ; if (ya==yb)
4217,7 → 4682,10
tsr #9,r1
jsr DisplayWord
cli ; enable interrupts so we can get a char
ber1:
jsr KeybdGetChar
cmp #-1
beq ber1
jmp start
msgBusErr:
4242,6 → 4710,7
sta IRQFlag
ror
bcc p100Hz11
stz 0xFFDCFFFC ; clear interrupt
pla
rti
 
4270,6 → 4739,10
sta TCB_SPSave,x
tsr sp8,r1 ; and the eight bit mode stack pointer
sta TCB_SP8Save,x
lda TCB_Status,x ; set the task status to PREEMPT
and r1,r1,#~TS_RUNNING
or r1,r1,#TS_PREEMPT
sta TCB_Status,x
 
; support EhBASIC's IRQ functionality
; code derived from minimon.asm
4276,7 → 4749,6
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
4341,7 → 4813,8
lda HeadRdy0,y
sta RunningTCB
ldx TCB_Status,r1 ; flag the task as the running task
or r2,r2,#TS_RUNNING
or r2,r2,#TS_RUNNING ; task is now running and not preempt
and r2,r2,#~TS_PREEMPT
stx TCB_Status,r1
bra p100Hz3
p100Hz1:
4357,6 → 4830,7
stz RunningTCB ; select BIOS task
ldx TCB_Status ; flag the task as the running task
or r2,r2,#TS_RUNNING
and r2,r2,#~TS_PREEMPT
stx TCB_Status
p100Hz3:
p100Hz10
/trunk/software/asm/TinyBasic65002.asm
48,34 → 48,32
XON EQU 0x11
XOFF EQU 0x13
 
CursorRow EQU 0x7C2
CursorCol EQU 0x7C3
CursorFlash EQU 0x7C4
IRQFlag EQU 0x7C6
CursorFlash EQU 0xFC4
IRQFlag EQU 0xFC6
 
OSSP EQU 0x700
TXTUNF EQU 0x701
VARBGN EQU 0x702
LOPVAR EQU 0x703
STKGOS EQU 0x704
CURRNT EQU 0x705
BUFFER EQU 0x706
OSSP EQU 0xF00
TXTUNF EQU 0xF01
VARBGN EQU 0xF02
LOPVAR EQU 0xF03
STKGOS EQU 0xF04
CURRNT EQU 0xF05
BUFFER EQU 0xF06
BUFLEN EQU 84
LOPPT EQU 0x760
LOPLN EQU 0x761
LOPINC EQU 0x762
LOPLMT EQU 0x763
NUMWKA EQU 0x764
STKINP EQU 0x774
STKBOT EQU 0x775
usrJmp EQU 0x776
IRQROUT EQU 0x777
LOPPT EQU 0xF60
LOPLN EQU 0xF61
LOPINC EQU 0xF62
LOPLMT EQU 0xF63
NUMWKA EQU 0xF64
STKINP EQU 0xF74
STKBOT EQU 0xF75
usrJmp EQU 0xF76
IRQROUT EQU 0xF77
 
 
 
cpu rtf65002
code
org $FFFFE800
org $FFFFEC00
GOSTART:
jmp CSTART ; Cold Start entry point
GOWARM:
342,10 → 340,10
;
TAB1_1:
dh LISTX ;Direct commands
dh LOAD
dh LOAD3
dh NEW
dh RUN
dh SAVE
dh SAVE3
TAB2_1:
dh NEXT ; Direct / statement
dh LET
542,8 → 540,6
; line, and jumps to 'RUNTSL' to do it.
;
GOTO
lda #'G'
jsr DisplayChar
jsr OREXPR ;evaluate the following expression
jsr DisplayWord
ld r5,r1
1127,7 → 1123,51
and #15 ; make sure a nybble
rts
 
LOAD3:
jsr spi_init
cmp #0
bne WSTART
lda #5000
ldx #$E00
jsr spi_read_sector
lda #5001
ldx TXTBGN>>2
asl r2,r2,#2
LOAD4:
pha
jsr spi_read_sector
add r2,r2,#512
pla
ina
ld r4,TXTBGN>>2
asl r4,r4,#2
add r4,r4,#65536
cmp r2,r4
bmi LOAD4
bra WSTART
 
SAVE3:
jsr spi_init
cmp #0
bne WSTART
lda #5000 ; starting sector
ldx #$E00 ; starting address to write
jsr spi_write_sector
lda #5001
ldx TXTBGN>>2
asl r2,r2,#2
SAVE4:
pha
jsr spi_write_sector
add r2,r2,#512
pla
ina
ld r4,TXTBGN>>2
asl r4,r4,#2
add r4,r4,#65536
cmp r2,r4
bmi SAVE4
bra WSTART
 
SAVE:
ld r8,TXTBGN>>2 ;set pointer to start of prog. area
1889,8 → 1929,6
; r1
;
ENDCHK:
lda #'E'
jsr DisplayChar
jsr IGNBLK
lda (r8)
cmp #CR

powered by: WebSVN 2.1.0

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