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

Subversion Repositories rtf65002

[/] [rtf65002/] [trunk/] [software/] [asm/] [bootrom.asm] - Blame information for rev 28

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 robfinch
; ============================================================================
2
;        __
3
;   \\__/ o\    (C) 2013  Robert Finch, Stratford
4
;    \  __ /    All rights reserved.
5
;     \/_//     robfinch@opencores.org
6
;       ||
7
;
8
;
9
; This source file is free software: you can redistribute it and/or modify
10
; it under the terms of the GNU Lesser General Public License as published
11
; by the Free Software Foundation, either version 3 of the License, or
12
; (at your option) any later version.
13
;
14
; This source file is distributed in the hope that it will be useful,
15
; but WITHOUT ANY WARRANTY; without even the implied warranty of
16
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
; GNU General Public License for more details.
18
;
19
; You should have received a copy of the GNU General Public License
20
; along with this program.  If not, see .
21
;
22
; ============================================================================
23
;
24
CR      EQU     0x0D            ;ASCII equates
25
LF      EQU     0x0A
26
TAB     EQU     0x09
27
CTRLC   EQU     0x03
28
CTRLH   EQU     0x08
29
CTRLI   EQU     0x09
30
CTRLJ   EQU     0x0A
31
CTRLK   EQU     0x0B
32
CTRLM   EQU 0x0D
33
CTRLS   EQU     0x13
34
CTRLX   EQU     0x18
35
XON             EQU     0x11
36
XOFF    EQU     0x13
37
 
38 26 robfinch
; error codes
39
E_Ok            =               0x00
40
E_Arg           =               0x01
41
E_BadMbx        =               0x04
42
E_QueFull       =               0x05
43
E_NoThread      =               0x06
44
E_NotAlloc      =               0x09
45
E_NoMsg         =               0x0b
46
E_Timeout       =               0x10
47
E_BadAlarm      =               0x11
48
E_NotOwner      =               0x12
49
; resource errors
50
E_NoMoreMbx     =               0x40
51
E_NoMoreMsgBlks =       0x41
52
E_NoMoreAlarmBlks       =0x44
53
E_NoMoreTCBs    =       0x45
54
 
55
; task status
56
TS_NONE     =0
57
TS_TIMEOUT      =1
58
TS_WAITMSG      =2
59 28 robfinch
TS_PREEMPT      =4
60 26 robfinch
TS_RUNNING      =8
61
TS_READY        =16
62
TS_WAITFOCUS    = 32
63
 
64
 
65
; message queuing strategy
66
MQS_UNLIMITED   =0      ; unlimited queue size
67
MQS_NEWEST              =1      ; buffer queue size newest messages
68
MQS_OLDEST              =2      ; buffer queue size oldest messages
69
 
70
 
71 11 robfinch
TEXTSCR         EQU             0xFFD00000
72
COLORSCR        EQU             0xFFD10000
73
TEXTREG         EQU             0xFFDA0000
74
TEXT_COLS       EQU             0x0
75
TEXT_ROWS       EQU             0x1
76
TEXT_CURPOS     EQU             11
77
KEYBD           EQU             0xFFDC0000
78
KEYBDCLR        EQU             0xFFDC0001
79 15 robfinch
PIC                     EQU             0xFFDC0FF0
80
PIC_IE          EQU             0xFFDC0FF1
81 26 robfinch
TASK_SELECT     EQU             0xFFDD0008
82
RQ_SEMA         EQU             0xFFDB0000
83
TO_SEMA         EQU             0xFFDB0010
84
SERIAL_SEMA     EQU             0xFFDB0020
85
KEYBD_SEMA      EQU             0xFFDB0030
86
IOF_LIST_SEMA   EQU     0xFFDB0040
87
MBX_SEMA        EQU             0xFFDB0050
88 11 robfinch
 
89
SPIMASTER       EQU             0xFFDC0500
90
SPI_MASTER_VERSION_REG  EQU     0x00
91
SPI_MASTER_CONTROL_REG  EQU     0x01
92
SPI_TRANS_TYPE_REG      EQU             0x02
93
SPI_TRANS_CTRL_REG      EQU             0x03
94
SPI_TRANS_STATUS_REG    EQU     0x04
95
SPI_TRANS_ERROR_REG             EQU     0x05
96
SPI_DIRECT_ACCESS_DATA_REG              EQU     0x06
97
SPI_SD_SECT_7_0_REG             EQU     0x07
98
SPI_SD_SECT_15_8_REG    EQU     0x08
99
SPI_SD_SECT_23_16_REG   EQU     0x09
100
SPI_SD_SECT_31_24_REG   EQU     0x0a
101
SPI_RX_FIFO_DATA_REG    EQU     0x10
102
SPI_RX_FIFO_DATA_COUNT_MSB      EQU     0x12
103
SPI_RX_FIFO_DATA_COUNT_LSB  EQU 0x13
104
SPI_RX_FIFO_CTRL_REG            EQU     0x14
105
SPI_TX_FIFO_DATA_REG    EQU     0x20
106
SPI_TX_FIFO_CTRL_REG    EQU     0x24
107
SPI_RESP_BYTE1                  EQU     0x30
108
SPI_RESP_BYTE2                  EQU     0x31
109
SPI_RESP_BYTE3                  EQU     0x32
110
SPI_RESP_BYTE4                  EQU     0x33
111
SPI_INIT_SD                     EQU             0x01
112
SPI_TRANS_START         EQU             0x01
113
SPI_TRANS_BUSY          EQU             0x01
114
SPI_INIT_NO_ERROR       EQU             0x00
115
SPI_READ_NO_ERROR       EQU             0x00
116 15 robfinch
SPI_WRITE_NO_ERROR      EQU             0x00
117 11 robfinch
RW_READ_SD_BLOCK        EQU             0x02
118
RW_WRITE_SD_BLOCK       EQU             0x03
119
 
120 26 robfinch
UART            EQU             0xFFDC0A00
121
UART_LS         EQU             0xFFDC0A01
122
UART_MS         EQU             0xFFDC0A02
123
UART_IS         EQU             0xFFDC0A03
124
UART_IE         EQU             0xFFDC0A04
125
UART_MC         EQU             0xFFDC0A06
126
UART_CM1        EQU             0xFFDC0A09
127
UART_CM2        EQU             0xFFDC0A0A
128
UART_CM3        EQU             0xFFDC0A0B
129
txempty         EQU             0x40
130
rxfull          EQU             0x01
131
 
132
CONFIGREC       EQU             0xFFDCFFF0
133
CR_CLOCK        EQU             0xFFDCFFF4
134
GACCEL          EQU             0xFFDAE000
135 28 robfinch
AC97            EQU             0xFFDC1000
136
PSG                     EQU             0xFFD50000
137
PSGFREQ0        EQU             0xFFD50000
138
PSGPW0          EQU             0xFFD50001
139
PSGCTRL0        EQU             0xFFD50002
140
PSGADSR0        EQU             0xFFD50003
141 26 robfinch
 
142
ETHMAC          EQU             0xFFDC2000
143
ETH_MODER               EQU             0x00
144
ETH_INT_SOURCE  EQU             0x01
145
ETH_INT_MASK    EQU             0x02
146
ETH_IPGT                EQU             0x03
147
ETH_IPGR1               EQU             0x04
148
ETH_IPGR2               EQU             0x05
149
ETH_PACKETLEN   EQU             0x06
150
ETH_COLLCONF    EQU             0x07
151
ETH_TX_BD_NUM   EQU             0x08
152
ETH_CTRLMODER   EQU             0x09
153
ETH_MIIMODER    EQU             0x0A
154
ETH_MIICOMMAND  EQU             0x0B
155
ETH_MIIADDRESS  EQU             0x0C
156
ETH_MIITX_DATA  EQU             0x0D
157
ETH_MIIRX_DATA  EQU             0x0E
158
ETH_MIISTATUS   EQU             0x0F
159
ETH_MAC_ADDR0   EQU             0x10
160
ETH_MAC_ADDR1   EQU             0x11
161
ETH_HASH0_ADDR  EQU             0x12
162
ETH_HASH1_ADDR  EQU             0x13
163
ETH_TXCTRL              EQU             0x14
164
 
165
SPRITEREGS      EQU             0xFFDAD000
166
SPRRAM          EQU             0xFFD80000
167
 
168
THRD_AREA       EQU             0x04000000      ; threading area 0x04000000-0x40FFFFF
169
BITMAPSCR       EQU             0x04100000
170
SECTOR_BUF      EQU             0x05FBEC00
171
BIOS_STACKS     EQU             0x05FC0000      ; room for 256 1kW stacks
172
BIOS_SCREENS    EQU     0x05C00000      ; 0x05C00000 to 0x05DFFFFF
173
 
174 15 robfinch
BYTE_SECTOR_BUF EQU     SECTOR_BUF<<2
175 26 robfinch
PROG_LOAD_AREA  EQU             0x4180000<<2
176 11 robfinch
 
177 28 robfinch
 
178 26 robfinch
eth_rx_buffer   EQU             0x5F80000
179
eth_tx_buffer   EQU             0x5F84000
180 11 robfinch
 
181 26 robfinch
; Mailboxes, room for 2048
182
MBX_LINK        EQU             0x05F90000
183
MBX_TQ_HEAD     EQU             0x05F90800
184
MBX_TQ_TAIL     EQU             0x05F91000
185
MBX_MQ_HEAD     EQU             0x05F91800
186
MBX_MQ_TAIL     EQU             0x05F92000
187
MBX_TQ_COUNT    EQU     0x05F92800
188
MBX_MQ_SIZE     EQU             0x05F93000
189
MBX_MQ_COUNT    EQU     0x05F93800
190
MBX_MQ_MISSED   EQU     0x05F94000
191
MBX_OWNER               EQU     0x05F94800
192
MBX_MQ_STRATEGY EQU     0x05F95000
193
MBX_RESV                EQU     0x05F95800
194 11 robfinch
 
195 26 robfinch
; Messages, room for 8kW (8,192) messages
196
MSG_LINK        EQU             0x05FA0000
197
MSG_D1          EQU             0x05FA2000
198
MSG_D2          EQU             0x05FA4000
199
MSG_TYPE        EQU             0x05FA6000
200
 
201
; Task control blocks, room for 256 tasks
202
TCB_NxtRdy              EQU             0x05FBE100      ; next task on ready / timeout list
203
TCB_PrvRdy              EQU             0x05FBE200      ; previous task on ready / timeout list
204
TCB_NxtTCB              EQU             0x05FBE300
205
TCB_Timeout             EQU             0x05FBE400
206
TCB_Priority    EQU             0x05FBE500
207
TCB_MSGPTR_D1   EQU             0x05FBE600
208
TCB_MSGPTR_D2   EQU             0x05FBE700
209
TCB_hJCB                EQU             0x05FBE800
210
TCB_Status              EQU             0x05FBE900
211
TCB_CursorRow   EQU             0x05FBD100
212
TCB_CursorCol   EQU             0x05FBD200
213
TCB_hWaitMbx    EQU             0x05FBD300      ; handle of mailbox task is waiting at
214
TCB_mbq_next    EQU             0x05FBD400      ; mailbox queue next
215
TCB_mbq_prev    EQU             0x05FBD500      ; mailbox queue previous
216 28 robfinch
TCB_iof_next    EQU             0x05FBD600
217
TCB_iof_prev    EQU             0x05FBD700
218
TCB_SP8Save             EQU             0x05FBD800      ; TCB_SP8Save area
219
TCB_SPSave              EQU             0x05FBD900      ; TCB_SPSave area
220 26 robfinch
 
221
KeybdHead       EQU             0x05FBEA00
222
KeybdTail       EQU             0x05FBEB00
223
KeybdEcho       EQU             0x05FBEC00
224
KeybdBad        EQU             0x05FBED00
225
KeybdAck        EQU             0x05FBEE00
226
KeybdLocks      EQU             0x05FBEF00
227
KeybdBuffer     EQU             0x05FBF000      ; buffer is 16 chars
228
 
229 28 robfinch
; Bitmap of tasks requesting the I/O focus
230
;
231
IOFocusTbl      EQU             0x05FBD000
232 26 robfinch
 
233 28 robfinch
; EhBASIC vars:
234 15 robfinch
;
235 26 robfinch
NmiBase         EQU             0xDC
236
IrqBase         EQU             0xDF
237
 
238 28 robfinch
; BIOS vars at the top of the 8kB scratch memory
239
;
240
; TinyBasic AREA = 0xF00 to 0xF7F
241 26 robfinch
 
242 28 robfinch
HeadRdy0        EQU             0xF80
243 26 robfinch
HeadRdy1        EQU             HeadRdy0+1
244
HeadRdy2        EQU             HeadRdy1+1
245
HeadRdy3        EQU             HeadRdy2+1
246
HeadRdy4        EQU             HeadRdy3+1
247
TailRdy0        EQU             HeadRdy4+1
248
TailRdy1        EQU             TailRdy0+1
249
TailRdy2        EQU             TailRdy1+1
250
TailRdy3        EQU             TailRdy2+1
251
TailRdy4        EQU             TailRdy3+1
252
FreeTCB         EQU             TailRdy4+1
253
TimeoutList     EQU             FreeTCB+1
254
RunningTCB              EQU             TimeoutList+1
255
FreeMbx         EQU             RunningTCB + 1
256
nMailbox        EQU             FreeMbx + 1
257
FreeMsg         EQU             nMailbox + 1
258
nMsgBlk         EQU             FreeMsg + 1
259
 
260 28 robfinch
; The IO focus list is a doubly linked list formed into a ring.
261
;
262
IOFocusNdx      EQU             nMsgBlk + 1
263 26 robfinch
 
264 28 robfinch
IrqSource       EQU             0xF98
265 15 robfinch
 
266 28 robfinch
JMPTMP          EQU             0xFA0
267
SP8Save         EQU             0xFAE
268
SRSave          EQU             0xFAF
269
R1Save          EQU             0xFB0
270
R2Save          EQU             0xFB1
271
R3Save          EQU             0xFB2
272
R4Save          EQU             0xFB3
273
R5Save          EQU             0xFB4
274
R6Save          EQU             0xFB5
275
R7Save          EQU             0xFB6
276
R8Save          EQU             0xFB7
277
R9Save          EQU             0xFB8
278
R10Save         EQU             0xFB9
279
R11Save         EQU             0xFBA
280
R12Save         EQU             0xFBB
281
R13Save         EQU             0xFBC
282
R14Save         EQU             0xFBD
283
R15Save         EQU             0xFBE
284
SPSave          EQU             0xFBF
285 15 robfinch
 
286 28 robfinch
CharColor       EQU             0xFC0
287
ScreenColor     EQU             0xFC1
288
CursorRow       EQU             0xFC2
289
CursorCol       EQU             0xFC3
290
CursorFlash     EQU             0xFC4
291
Milliseconds    EQU             0xFC5
292
IRQFlag         EQU             0xFC6
293
RdyQueTick      EQU             0xFC7
294
eth_unique_id   EQU             0xFC8
295
LineColor       EQU             0xFC9
296
 
297 26 robfinch
Uart_rxfifo             EQU             0x05FBC000
298 28 robfinch
Uart_rxhead             EQU             0xFD0
299
Uart_rxtail             EQU             0xFD1
300
Uart_ms                 EQU             0xFD2
301
Uart_rxrts              EQU             0xFD3
302
Uart_rxdtr              EQU             0xFD4
303
Uart_rxxon              EQU             0xFD5
304
Uart_rxflow             EQU             0xFD6
305
Uart_fon                EQU             0xFD7
306
Uart_foff               EQU             0xFD8
307
Uart_txrts              EQU             0xFD9
308
Uart_txdtr              EQU             0xFDA
309
Uart_txxon              EQU             0xFDB
310
Uart_txxonoff   EQU             0xFDC
311 15 robfinch
 
312 28 robfinch
startSector     EQU             0xFF0
313 15 robfinch
 
314
 
315 11 robfinch
        cpu             rtf65002
316
        code
317 15 robfinch
 
318 26 robfinch
message "jump table"
319 15 robfinch
        ; jump table of popular BIOS routines
320 11 robfinch
        org             $FFFFC000
321 15 robfinch
        dw      DisplayChar
322
        dw      KeybdCheckForKeyDirect
323
        dw      KeybdGetCharDirect
324 26 robfinch
        dw      KeybdGetChar
325
        dw      KeybdCheckForKey
326
        dw      RequestIOFocus
327
        dw      ReleaseIOFocus
328
        dw      ClearScreen
329
        dw      HomeCursor
330
        dw      ExitTask
331
        dw      SetKeyboardEcho
332 28 robfinch
        dw      Sleep
333 15 robfinch
 
334
        org             $FFFFC200               ; leave room for 128 vectors
335 26 robfinch
message "cold start point"
336 15 robfinch
KeybdRST
337 11 robfinch
start
338
        sei                                             ; disable interrupts
339
        cld                                             ; disable decimal mode
340 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer top of memory
341 11 robfinch
        txs
342 15 robfinch
        trs             r0,dp                   ; set direct page register
343
        trs             r0,dp8                  ; and 8 bit mode direct page
344
        trs             r0,abs8                 ; and 8 bit mode absolute address offset
345
 
346
        ; setup interrupt vectors
347 26 robfinch
        ldx             #$05FB0001              ; interrupt vector table from $5FB0000 to $5FB01FF
348 18 robfinch
                                                        ; also sets nmoi policy (native mode on interrupt)
349 15 robfinch
        trs             r2,vbr
350 18 robfinch
        dex
351 15 robfinch
        lda             #brk_rout
352
        sta             (x)
353
        lda             #slp_rout
354
        sta             1,x
355
        lda             #KeybdRST
356
        sta             448+1,x
357
        lda             #p1000Hz
358
        sta             448+2,x
359
        lda             #p100Hz
360
        sta             448+3,x
361
        lda             #KeybdIRQ
362
        sta             448+15,x
363 26 robfinch
        lda             #SerialIRQ
364
        sta             448+8,x
365
        lda             #bus_err_rout
366
        sta             508,x
367
        sta             509,x
368 15 robfinch
 
369
        emm
370
        cpu             W65C02
371
        ldx             #$FF                    ; set 8 bit stack pointer
372
        txs
373
        nat
374
        cpu             rtf65002
375 26 robfinch
 
376
        ldx             #0
377
        stz             IrqBase                 ; support for EhBASIC's interrupt mechanism
378
        stz             NmiBase
379
        ; Initialize the BIOS task
380
        lda             #TS_RUNNING|TS_READY
381
        sta             TCB_Status
382
        stz             TCB_Priority    ; set task#0 priority
383
        lda             #-1
384
        sta             TCB_NxtRdy              ; set task#0 next and previous fields
385
        sta             TCB_PrvRdy
386
        stz             TCB_Timeout
387
        stz             RunningTCB              ; the BIOS task is the running task
388
 
389
        sta             TimeoutList             ; no entries in timeout list
390 28 robfinch
        sta             IOFocusNdx
391 26 robfinch
        stz             HeadRdy0                ; task zero (the BIOS task) is always present
392
        sta             HeadRdy1
393
        sta             HeadRdy2
394
        sta             HeadRdy3
395
        sta             HeadRdy4
396
        stz             TailRdy0
397
        sta             TailRdy1
398
        sta             TailRdy2
399
        sta             TailRdy3
400
        sta             TailRdy4
401
 
402
        ; Initialize IO Focus List
403
        ;
404
        ldx             #0
405
st5:
406 28 robfinch
        stz             IOFocusTbl,x
407 26 robfinch
        inx
408
        cpx             #8
409
        bne             st5
410
 
411 28 robfinch
        ldx             #0
412
        lda             #-1
413
st9:
414
        sta             TCB_iof_next,x
415
        sta             TCB_iof_prev,x
416
        inx
417
        cpx             #256
418
        bne             st9
419
 
420 26 robfinch
        ; Initialize free message list
421
        lda             #8192
422
        sta             nMsgBlk
423
        stz             FreeMsg
424
        ldx             #0
425
        lda             #1
426
st4:
427
        sta             MSG_LINK,x
428
        ina
429
        inx
430
        cpx             #8192
431
        bne             st4
432
        lda             #-1
433
        sta             MBX_LINK+8191
434
 
435
        ; Initialize free mailbox list
436
        lda             #2048
437
        sta             nMailbox
438
 
439
        stz             FreeMbx
440
        ldx             #0
441
        lda             #1
442
st3:
443
        sta             MBX_LINK,x
444
        ina
445
        inx
446
        cpx             #2048
447
        bne             st3
448
        lda             #-1
449
        sta             MBX_LINK+2047
450
 
451
        ; Initialize the FreeTCB list
452
        lda             #1                              ; the next available TCB
453
        sta             FreeTCB
454
        ldx             #1
455
        lda             #2
456
st2:
457
        sta             TCB_NxtTCB,x
458
        ina
459
        inx
460
        cpx             #256
461
        bne             st2
462
        lda             #-1
463
        sta             TCB_NxtTCB+255
464
 
465
        lda             #1
466
        sta             MBX_SEMA
467
        sta             IOF_LIST_SEMA
468
        sta             RQ_SEMA                 ; set ready queue semaphore
469
        sta             TO_SEMA                 ; set timeout list semaphore
470
        jsr             RequestIOFocus          ; Get the IO focus for the BIOS (must be after semaphore is initialized)
471 11 robfinch
        lda             #$CE                    ; CE =blue on blue FB = grey on grey
472
        sta             ScreenColor
473
        sta             CharColor
474 26 robfinch
        sta             CursorFlash
475 11 robfinch
        jsr             ClearScreen
476 15 robfinch
        jsr             ClearBmpScreen
477 28 robfinch
        lda             CONFIGREC               ; do we have sprites ?
478
        bit             #1
479
        beq             st8
480 26 robfinch
        lda             #$3FFF                  ; turn on sprites
481
        sta             SPRITEREGS+120
482
        jsr             RandomizeSprram
483 28 robfinch
st8:
484 26 robfinch
        jsr             HomeCursor
485 15 robfinch
        lda             #msgStart
486 11 robfinch
        jsr             DisplayStringB
487 15 robfinch
        jsr             KeybdInit
488
        lda             #1
489
        sta             KeybdEcho
490 28 robfinch
        lda             CONFIGREC               ; do we have a serial port ?
491
        bit             #32
492
        beq             st7
493 26 robfinch
        ; 19200 * 16
494
        ;-------------
495
        ; 25MHz / 2^32
496
        lda             #$03254E6E              ; constant for 19,200 baud at 25MHz
497 28 robfinch
        jsr             SerialInit
498
st7:
499 26 robfinch
        lda             #4
500
        ldx             #0
501
        ldy             #IdleTask
502
        jsr             StartTask
503 15 robfinch
        jsr             PICInit
504
        cli                                             ; enable interrupts
505 28 robfinch
        ; The following must be after interrupts are enabled.
506
        ; The AC97 setup uses the millisecond counter and the
507
        ; keyboard.
508
        lda             CONFIGREC               ; do we have a sound generator ?
509
        bit             #4
510
        beq             st6
511
        jsr             SetupAC97
512
        jsr             Beep
513
st6:
514 15 robfinch
        jmp             Monitor
515
st1
516
        jsr             KeybdGetCharDirect
517
        bra             st1
518 11 robfinch
        stp
519
        bra             start
520
 
521
msgStart
522
        db              "RTF65002 system starting.",$0d,$0a,00
523
 
524 15 robfinch
;----------------------------------------------------------
525
; Initialize programmable interrupt controller (PIC)
526
;  0 = nmi (parity error)
527
;  1 = keyboard reset
528
;  2 = 1000Hz pulse (context switcher)
529
;  3 = 100Hz pulse (cursor flash)
530
;  4 = ethmac
531
;  8 = uart
532
; 13 = raster interrupt
533
; 15 = keyboard char
534
;----------------------------------------------------------
535 26 robfinch
message "PICInit"
536 15 robfinch
PICInit:
537
        ; enable: raster irq,
538 26 robfinch
        lda             #$810F                  ; enable nmi,kbd_rst,and kbd_irq
539 15 robfinch
        ; A10F enable serial IRQ
540
        sta             PIC_IE
541
PICret:
542
        rts
543
 
544 11 robfinch
;------------------------------------------------------------------------------
545 26 robfinch
;------------------------------------------------------------------------------
546
message "DumpTaskList"
547
DumpTaskList:
548
        pha
549
        phx
550
        phy
551
        push    r4
552
        lda             #msgTaskList
553
        jsr             DisplayStringB
554
        ldy             #0
555
        php
556
        sei
557
dtl2:
558
        lda             HeadRdy0,y
559
        ld              r4,r1
560
        bmi             dtl1
561
dtl3:
562
        ldx             #3
563
        tya
564
        jsr             PRTNUM
565
        lda             #' '
566
        jsr             DisplayChar
567
        ld              r1,r4
568
        ldx             #3
569
        jsr             PRTNUM
570
        lda             #' '
571
        jsr             DisplayChar
572
        jsr             DisplayChar
573
        jsr             DisplayChar
574
        ld              r1,r4
575
        lda             TCB_Status,r1
576
        jsr             DisplayByte
577
        lda             #' '
578
        jsr             DisplayChar
579
        ldx             #3
580
        lda             TCB_PrvRdy,r4
581
        jsr             PRTNUM
582
        lda             #' '
583
        jsr             DisplayChar
584
        ldx             #3
585
        lda             TCB_NxtRdy,r4
586
        jsr             PRTNUM
587
        lda             #' '
588
        jsr             DisplayChar
589
        lda             TCB_Timeout,r4
590
        jsr             DisplayWord
591
        jsr             CRLF
592
        ld              r4,TCB_NxtRdy,r4
593
        bpl             dtl3
594
dtl1:
595
        iny
596
        cpy             #5
597
        bne             dtl2
598
        plp
599
        pop             r4
600
        ply
601
        plx
602
        pla
603
        rts
604
 
605
msgTaskList:
606
        db      CR,LF,"Pri Task Stat Prv Nxt Timeout",CR,LF,0
607
 
608
;------------------------------------------------------------------------------
609 28 robfinch
;------------------------------------------------------------------------------
610
message "DumpIOFocusList"
611
DumpIOFocusList:
612
        pha
613
        phx
614
        phy
615
        php
616
        sei
617
        lda             #msgIOFocusList
618
        jsr             DisplayStringB
619
        lda             IOFocusNdx
620
diofl2:
621
        bmi             diofl1
622
        tay
623
        ldx             #3
624
        jsr             PRTNUM
625
        lda             #' '
626
        jsr             DisplayChar
627
        lda             TCB_iof_prev,y
628
        ldx             #3
629
        jsr             PRTNUM
630
        lda             #' '
631
        jsr             DisplayChar
632
        lda             TCB_iof_next,y
633
        ldx             #3
634
        jsr             PRTNUM
635
        jsr             CRLF
636
        lda             TCB_iof_next,y
637
        cmp             IOFocusNdx
638
        bne             diofl2
639
 
640
diofl1:
641
        plp
642
        ply
643
        plx
644
        pla
645
        rts
646
 
647
msgIOFocusList:
648
        db      CR,LF,"Task Prv Nxt",CR,LF,0
649
 
650
;------------------------------------------------------------------------------
651 26 robfinch
; IdleTask is a low priority task that is always running. It runs when there
652
; is nothing else to run.
653
;------------------------------------------------------------------------------
654
IdleTask:
655
        inc             TEXTSCR+167             ; increment IDLE active flag
656
        cli                                             ; enable interrupts
657
        wai                                             ; wait for one to happen
658
        bra             IdleTask
659
 
660
;------------------------------------------------------------------------------
661
; r1 = task priority
662
; r2 = start flags
663
; r3 = start address
664
;------------------------------------------------------------------------------
665
message "StartTask"
666
StartTask:
667
        pha
668
        phx
669
        phy
670
        push    r4
671
        push    r5
672
        push    r6
673
        push    r7
674
        push    r8
675
        tsr             sp,r4                           ; save off current stack pointer
676
        ld              r6,r1                           ; r6 = task priority
677
        ld              r8,r2
678
 
679
        ; get a free TCB
680
        ;
681
        sei
682
        lda             FreeTCB                         ; get free tcb list pointer
683
        bmi             stask1
684
        tax
685
        lda             TCB_NxtTCB,x
686
        sta             FreeTCB                         ; update the FreeTCB list pointer
687
        cli
688
        txa
689
 
690
        ; setup the stack for the task
691
        ld              r7,r2
692
        asl             r2,r2,#10                       ; 1kW stack per task
693
        add             r2,r2,#BIOS_STACKS+0x3ff        ; add in stack base
694
        txs
695
        ldx             #$FF
696
        stx             TCB_SP8Save,r7
697
        st              r6,TCB_Priority,r7
698
        stz             TCB_Status,r7
699
        stz             TCB_Timeout,r7
700
 
701
        ; setup the initial stack image for the task
702
        ; Cause a return to the ExitTask routine when the task does a
703
        ; final rts.
704
        ; fake an IRQ call by stacking the return address and processor
705
        ; flags on the stack
706
        ldx             #ExitTask                       ; save the address of the task exit routine
707
        phx
708
        phy                                                     ; save start address on stack
709
        push    r8                                      ; save processor status reg on stack
710
 
711
        ; now fake pushing the register set onto the stack. Registers start up
712
        ; in an undefined state.
713
        sub             sp,#15                          ; 15 registers
714
        tsx
715
        stx             TCB_SPSave,r7
716
 
717
        ; now restore the current stack pointer
718
        trs             r4,sp
719
 
720
        ; Insert the task into the ready list
721
        jsr             AddTaskToReadyList
722
stask2:
723
        pop             r8
724
        pop             r7
725
        pop             r6
726
        pop             r5
727
        pop             r4
728
        ply
729
        plx
730
        pla
731
        rts
732
stask1:
733
        cli
734
        lda             #msgNoTCBs
735
        jsr             DisplayStringB
736
        bra             stask2
737
 
738
msgNoTCBs:
739
        db              "No more task control blocks available.",CR,LF,0
740
 
741
;------------------------------------------------------------------------------
742
; This routine is called when the task exits with an rts instruction. OR
743 28 robfinch
; it may be invoked with a JMP ExitTask. In either case the task must be
744
; running so it can't be on the timeout list.
745 26 robfinch
;------------------------------------------------------------------------------
746
message "ExitTask"
747
ExitTask:
748
        sei
749
        ; release any aquired resources
750
        ; - mailboxes
751
        ; - messages
752
        lda             RunningTCB
753
        jsr             RemoveTaskFromReadyList
754
        stz             TCB_Status,r1                           ; set task status to TS_NONE
755 28 robfinch
        jsr             ReleaseIOFocus
756
        ldx             FreeTCB                                         ; add the task control block to the free list
757 26 robfinch
        stx             TCB_NxtTCB,r1
758
        sta             FreeTCB
759
        jmp             SelectTaskToRun
760
 
761
;------------------------------------------------------------------------------
762
; AddTaskToReadyList
763
; This subroutine is called from the timer ISR so it must be relatively
764
; fast.
765
; Parameters:
766
; r1 = task number
767
;
768
;------------------------------------------------------------------------------
769
message "AddTaskToReadyList"
770
AddTaskToReadyList:
771 28 robfinch
        pha
772 26 robfinch
        phx
773
        phy
774
        php
775
        sei
776
        ldy             TCB_Priority,r1 ; make sure the priority value isn't screwy.
777
        cpy             #5
778
        bpl             arl3
779
arl2:
780
        ldx             TCB_Status,r1   ; set the task status to ready
781 28 robfinch
        bit             r2,#TS_READY    ; is the task already on the ready list ?
782
        bne             arl3
783 26 robfinch
        or              r2,r2,#TS_READY
784
        stx             TCB_Status,r1
785
        ldx     TailRdy0,y              ; insert the task at the list tail
786 28 robfinch
        bmi             arl1                    ; if no tail, then either the list is screwed up, or no tasks are on it.
787
        sta             TCB_NxtRdy,x    ; add as next ready on tail
788
arl4:
789
        stx             TCB_PrvRdy,r1   ; the old tail is the previous task on the list now.
790
        sta             TailRdy0,y              ; update with new tail
791 26 robfinch
        ldx             #-1
792 28 robfinch
        stx             TCB_NxtRdy,r1   ; There is no next ready task to the tail.
793 26 robfinch
        ldx             HeadRdy0,y              ; check if the head of the ready list needs to be updated
794
        bpl             arl3
795 28 robfinch
        sta             HeadRdy0,y              ; Update the head of the ready list.
796
        ldx             #-1                             ; There is no previous task at the head.
797 26 robfinch
        stx             TCB_PrvRdy,r1
798
arl3:
799
        plp
800
        ply
801
        plx
802 28 robfinch
        pla
803 26 robfinch
        rts
804 28 robfinch
        ; Here the tail of the ready list needed to be updated. Flag no prior task.
805
arl1:
806
        ldx             #-1
807
        bra             arl4
808 26 robfinch
 
809
;------------------------------------------------------------------------------
810
; RemoveTaskFromReadyList
811
; This subroutine removes a task from the ready list.
812
; This can be called from within an ISR.
813
;
814
; r1 = task number
815
;------------------------------------------------------------------------------
816
message "RemoveTaskFromReadyList"
817
RemoveTaskFromReadyList:
818
        cmp             #0
819
        bmi             rfr9                    ; bad task number, must be >= 0
820
        cmp             #255                    ; and must be <= 255
821
        bpl             rfr9
822
        pha
823 28 robfinch
        phx
824 26 robfinch
        phy
825
        push    r4
826
        push    r5
827
 
828
        php                                             ; save off interrupt mask state
829
        sei
830 28 robfinch
        ld              r4,TCB_Status,r1        ; check if the task is even on the ready list
831
        bit             r4,#TS_READY
832
        beq             rfr2                            ; not on ready list, then we're done
833 26 robfinch
        ld              r4,TCB_NxtRdy,r1        ; Get previous and next fields.
834
        ld              r5,TCB_PrvRdy,r1        ; if there is no previous task, then this is
835
        bmi             rfr1                    ; the head of the list. Update.
836
        st              r4,TCB_NxtRdy,r5
837
        cmp             r4,#0                   ; is there a next task to update ?
838
        bmi             rfr8
839
        st              r5,TCB_PrvRdy,r4
840 28 robfinch
rfr4:
841 26 robfinch
        ld              r5,#-1
842
        st              r5,TCB_NxtRdy,r1
843
        st              r5,TCB_PrvRdy,r1
844
        bra             rfr8
845
 
846
        ; Update the head of the list
847
rfr1:
848
        ldy             TCB_Priority,r1
849
        st              r4,HeadRdy0,y
850
        cmp             r4,#0                   ; did we empty the list ?
851 28 robfinch
        bmi             rfr3
852 26 robfinch
        ld              r5,#-1                  ; flag no previous task for head of list
853
        st              r5,TCB_PrvRdy,r4
854
        st              r5,TCB_NxtRdy,r1
855
        st              r5,TCB_PrvRdy,r1
856
rfr8:
857 28 robfinch
        ldx             TCB_Status,r1   ; set the task status to no longer ready.
858
        and             r2,r2,#~TS_READY
859
        stx             TCB_Status,r1
860
rfr2:
861 26 robfinch
        plp
862
        pop             r5
863
        pop             r4
864
        ply
865 28 robfinch
        plx
866 26 robfinch
        pla
867
rfr9:
868
        rts
869 28 robfinch
rfr3:
870
        st              r4,TailRdy0,y   ;
871
        bra             rfr4
872
 
873 26 robfinch
;------------------------------------------------------------------------------
874 28 robfinch
; AddToTimeoutList
875
; AddToTimeoutList adds a task to the timeout list. The task is placed in the
876
; list depending on it's timeout value.
877
;
878
; Parameters:
879
;       r1 = task
880
;       r2 = timeout value
881 26 robfinch
;------------------------------------------------------------------------------
882
message "AddToTimeoutList"
883
AddToTimeoutList:
884 28 robfinch
        cmp             #0                                              ; quickly validate the task number
885
        bmi             attl4                                   ; must be between 0 and 255
886
        cmp             #255
887
        bpl             attl4
888
 
889 26 robfinch
        phx
890
        push    r4
891
        push    r5
892
        php
893
        sei
894
 
895
        ld              r5,#-1
896
        ld              r4,TimeoutList  ; are there any tasks on the timeout list ?
897
        bmi             attl1
898
attl_check_next:
899
        sub             r2,r2,TCB_Timeout,r4    ; is this timeout > next
900
        bmi             attl_insert_before
901
        ld              r5,r4
902
        ld              r4,TCB_NxtRdy,r4
903
        bpl             attl_check_next
904
 
905
        ; Here we scanned until the end of the timeout list and didn't find a
906
        ; timeout of a greater value. So we add the task to the end of the list.
907
attl_add_at_end:
908
        st              r4,TCB_NxtRdy,r1        ; r4 was = -1
909
        st              r1,TCB_NxtRdy,r5
910
        st              r5,TCB_PrvRdy,r1
911
        st              r2,TCB_Timeout,r1
912
        bra             attl_exit
913
 
914
attl_insert_before:
915
        cmp             r5,#-1
916
        beq             attl2
917
        st              r4,TCB_NxtRdy,r1        ; next on list goes after this task
918
        st              r5,TCB_PrvRdy,r1        ; set previous link
919
        st              r1,TCB_NxtRdy,r5
920
        st              r1,TCB_PrvRdy,r4
921
        bra             attl3
922
 
923
        ; Here there is no previous entry in the timeout list
924
        ; Add at start
925
attl2:
926
        sta             TCB_PrvRdy,r4
927
        st              r5,TCB_PrvRdy,r1        ; r5 = -1
928
        st              r4,TCB_NxtRdy,r1
929
        sta             TimeoutList             ; update the head pointer
930
attl3:
931
        add             r2,r2,TCB_Timeout,r4    ; get back timeout
932
        stx             TCB_Timeout,r1
933
        ld              r5,TCB_Timeout,r4       ; adjust the timeout of the next task
934
        sub             r5,r5,r2
935
        st              r5,TCB_Timeout,r4
936
        bra             attl_exit
937
 
938
        ; Here there were no tasks on the timeout list, so we add at the
939
        ; head of the list.
940
attl1:
941
        sta             TimeoutList             ; set the head of the timeout list
942
        stx             TCB_Timeout,r1
943
        ldx             #-1                             ; flag no more entries in timeout list
944
        stx             TCB_NxtRdy,r1           ; no next entries
945
        stx             TCB_PrvRdy,r1           ; and no prev entries
946
attl_exit:
947 28 robfinch
        ldx             TCB_Status,r1           ; set the task's status as timing out
948
        or              r2,r2,#TS_TIMEOUT
949
        stx             TCB_Status,r1
950 26 robfinch
        plp
951
        pop             r5
952
        pop             r4
953
        plx
954 28 robfinch
attl4:
955 26 robfinch
        rts
956
 
957
;------------------------------------------------------------------------------
958 28 robfinch
; This subroutine is called from within the timer ISR when the task's
959
; timeout expires.
960 26 robfinch
;
961
; r1 = task number
962
;------------------------------------------------------------------------------
963
message "RemoveFromTimeoutList"
964
RemoveFromTimeoutList:
965 28 robfinch
        cmp             #0                                              ; quickly validate the task number
966
        bmi             rft4                                    ; must be between 0 and 255
967
        cmp             #255
968
        bpl             rft4
969
 
970 26 robfinch
        pha
971
        phx
972
        push    r4
973
        push    r5
974
        php
975
        sei
976
 
977
        ld              r4,TCB_PrvRdy,r1                ; adjust the links of the next and previous
978
        bmi             rftl2
979
        ld              r5,TCB_NxtRdy,r1                ; tasks on the list to point around the task
980
        st              r5,TCB_NxtRdy,r4
981
        bmi             rftl1
982
        st              r4,TCB_PrvRdy,r5
983
        ldx             TCB_Timeout,r1                  ; update the timeout of the next on list
984
        add             r2,r2,TCB_Timeout,r5    ; with any remaining timeout in the task
985
        stx             TCB_Timeout,r5                  ; removed from the list
986
 
987
        ; Here there is no next item on the list
988
rftl1:
989
        bra             rftl3
990
 
991
        ; Here there is no previous item on the list, so update the head of
992
        ; the list.
993
rftl2:
994
        ld              r5,TCB_NxtRdy,r1
995
        st              r5,TimeoutList          ; store next field into list head
996
        bmi             rftl3
997 28 robfinch
        ld              r4,TCB_Timeout,r1               ; add any remaining timeout to the timeout
998
        add             r4,r4,TCB_Timeout,r5    ; of the next task on the list.
999
        st              r4,TCB_Timeout,r5
1000
        ld              r4,#-1                                  ; there is no previous item to the head
1001 26 robfinch
        sta             TCB_PrvRdy,r5
1002
 
1003
        ; Here there is no previous or next items in the list, so the list
1004
        ; will be empty once this task is removed from it.
1005
rftl3:
1006 28 robfinch
        ldx             TCB_Status,r1           ; set the task status to not timing out
1007
        and             r2,r2,#~TS_TIMEOUT
1008
        stx             TCB_Status,r1
1009 26 robfinch
        plp
1010
        pop             r5
1011
        pop             r4
1012
        plx
1013
        pla
1014 28 robfinch
rft4:
1015 26 robfinch
        rts
1016 28 robfinch
 
1017 26 robfinch
;------------------------------------------------------------------------------
1018 28 robfinch
; Parameters:
1019
; r1 = time duration in centi-seconds
1020
;------------------------------------------------------------------------------
1021
Sleep:
1022
        tax
1023
        sei
1024
        lda             RunningTCB
1025
        jsr             RemoveTaskFromReadyList
1026
        jsr             AddToTimeoutList
1027
        ldx             #SleepRet                       ; The scheduler will be returning to this
1028
        jmp             PushRegsAndRunTask      ; task eventually, once the timeout expires,
1029
                                                                ; so fake an interrupt call
1030
SleepRet:
1031
        cli
1032
        rts
1033
 
1034
;------------------------------------------------------------------------------
1035 26 robfinch
; Allocate a mailbox
1036
; r1 = pointer to place to store handle
1037
;------------------------------------------------------------------------------
1038
message "AllocMbx"
1039
AllocMbx:
1040
        cmp             #0
1041
        beq             ambx1
1042
        phx
1043
        phy
1044
        push    r4
1045
        ld              r4,r1
1046
        php
1047
        sei
1048
        lda             FreeMbx                 ; Get mailbox off of free mailbox list
1049
        sta             (r4)                    ; store off the mailbox number
1050
        bmi             ambx2
1051
        ldx             MBX_LINK,r1             ; and update the head of the list
1052
        stx             FreeMbx
1053
        dec             nMailbox                ; decrement number of available mailboxes
1054
        tax
1055
        ldy             RunningTCB                      ; set the mailbox owner
1056
        lda             TCB_hJCB,y
1057
        sta             MBX_OWNER,x
1058
        lda             #-1                             ; initialize the head and tail of the queues
1059
        sta             MBX_TQ_HEAD,x
1060
        sta             MBX_TQ_TAIL,x
1061
        sta             MBX_MQ_HEAD,x
1062
        sta             MBX_MQ_TAIL,x
1063
        stz             MBX_TQ_COUNT,x  ; initialize counts to zero
1064
        stz             MBX_MQ_COUNT,x
1065
        stz             MBX_MQ_MISSED,x
1066
        lda             #8                              ; set the max queue size
1067
        sta             MBX_MQ_SIZE,x   ; and
1068
        lda             #MQS_NEWEST             ; queueing strategy
1069
        sta             MBX_MQ_STRATEGY,x
1070
        plp
1071
        pop             r4
1072
        ply
1073
        plx
1074
        lda             #E_Ok
1075
        rts
1076
ambx1:
1077
        lda             #E_Arg
1078
        rts
1079
ambx2:
1080
        plp
1081
        pop             r4
1082
        ply
1083
        plx
1084
        lda             #E_NoMoreMbx
1085
        rts
1086
 
1087
;------------------------------------------------------------------------------
1088
; r1 = message
1089
; r2 = mailbox
1090
;------------------------------------------------------------------------------
1091
message "QueueMsgAtMbx"
1092
QueueMsgAtMbx:
1093
        pha
1094
        phx
1095
        phy
1096
        php
1097
        sei
1098
        ldy             MBX_MQ_TAIL,x
1099
        bmi             qmam1
1100
        sta             MBX_LINK,y
1101
        bra             qmam2
1102
qmam1:
1103
        sta             MBX_MQ_HEAD,x
1104
qmam2:
1105
        sta             MBX_MQ_TAIL,x
1106
        inc             MBX_MQ_COUNT,x          ; increase the queued message count
1107
        ldx             #-1
1108
        stx             MSG_LINK,r1
1109
        plp
1110
        ply
1111
        plx
1112
        pla
1113
        rts
1114
 
1115
;------------------------------------------------------------------------------
1116
; Returns
1117
; r1 = message number
1118
;------------------------------------------------------------------------------
1119
message "DequeueMsgFromMbx"
1120
DequeueMsgFromMbx:
1121
        phx
1122
        phy
1123
        php
1124
        sei
1125
        tax                                             ; x = mailbox index
1126
        lda             MBX_MQ_COUNT,x          ; are there any messages available ?
1127
        beq             dmfm1
1128
        dea
1129
        sta             MBX_MQ_COUNT,x          ; update the message count
1130
        lda             MBX_MQ_HEAD,x           ; Get the head of the list, this should not be -1
1131
        bmi             dmfm1                   ; since the message count > 0
1132
        ldy             MSG_LINK,r1             ; get the link to the next message
1133
        sty             MBX_MQ_HEAD,x           ; update the head of the list
1134
        bpl             dmfm2                   ; if there was no more messages then update the
1135
        sty             MBX_MQ_TAIL,x           ; tail of the list as well.
1136
dmfm2:
1137
        sta             MSG_LINK,r1             ; point the link to the messahe itself to indicate it's dequeued
1138
dmfm1:
1139
        plp
1140
        ply
1141
        plx
1142
        rts
1143
 
1144
;------------------------------------------------------------------------------
1145
;------------------------------------------------------------------------------
1146
DequeueThreadFromMbx:
1147
        cpx             #0
1148
        beq             dtfm1
1149
        php
1150
        sei
1151
        push    r4
1152
        ld              r4,MBX_TQ_HEAD,r1
1153
        bpl             dtfm2
1154
                pop             r4
1155
                stz             (x)
1156
                plp
1157
                lda             #E_NoThread
1158
                rts
1159
dtfm2:
1160
        push    r5
1161
        dec             MBX_TQ_COUNT,r1
1162
        st              r4,(x)
1163
        ld              r4,TCB_mbq_next,r4
1164
        st              r4,MBX_TQ_HEAD,r1
1165
        bmi             dtfm3
1166
                ld              r5,#-1
1167
                st              r5,TCB_mbq_prev,r4
1168
                bra             dtfm4
1169
dtfm3:
1170
                ld              r5,#-1
1171
                st              r5,MBX_TQ_TAIL,r1
1172
dtfm4:
1173
        stz             MBX_SEMA+1
1174
        ld              r5,(x)
1175
        lda             TCB_Status,r5
1176
        bit             #TS_TIMEOUT
1177
        beq             dtfm5
1178
                ld              r1,r5
1179
                jsr             RemoveFromTimeoutList
1180
dtfm5:
1181
        ld              r4,#-1
1182
        st              r4,TCB_mbq_next,r5
1183
        st              r4,TCB_mbq_prev,r5
1184
        stz             TCB_hWaitMbx,r5
1185
        lda             TCB_Status,r5
1186
        and             #~TS_WAITMSG
1187
        sta             TCB_Status,r5
1188
        pop             r5
1189
        pop             r4
1190
        plp
1191
        lda             #E_Ok
1192
        rts
1193
dtfm1:
1194
        lda             #E_Arg
1195
        rts
1196
 
1197
;------------------------------------------------------------------------------
1198
; r1 = handle to mailbox
1199
; r2 = message D1
1200
; r3 = message D2
1201
;------------------------------------------------------------------------------
1202
message "SendMsg"
1203
SendMsg:
1204
        cmp             #0                                              ; check the mailbox number to make sure
1205
        bmi             smsg1                                   ; that it's sensible
1206
        cmp             #2047
1207
        bpl             smsg1
1208
        push    r4
1209
        push    r5
1210
        push    r6
1211
        php
1212
        sei
1213
        ld              r4,MBX_OWNER,r1
1214
        bmi             smsg2                                   ; error: no owner
1215
        pha
1216
        phx
1217
        jsr             DequeueThreadFromMbx    ; r1=mbx, r2=thread (returned)
1218
        ld              r6,r2                                   ; r6 = thread
1219
        plx
1220
        pla
1221
        cmp             r6,#0
1222
        bpl             smsg3
1223
                ; Here there was no thread waiting at the mailbox, so a message needs to
1224
                ; be allocated
1225
                ld              r4,FreeMsg
1226
                bmi             smsg4           ; no more messages available
1227
                ld              r5,MSG_LINK,r4
1228
                st              r5,FreeMsg
1229
                dec             nMsgBlk         ; decrement the number of available messages
1230
                stx             MSG_D1,r4
1231
                sty             MSG_D2,r4
1232
                pha
1233
                phx
1234
                tax                                             ; x = mailbox
1235
                ld              r1,r4                   ; acc = message
1236
                jsr             QueueMsgAtMbx
1237
                plx
1238
                pla
1239
                cmp             r6,#0                   ; check if there is a thread waiting for a message
1240
                bmi             smsg5
1241
smsg3:
1242
        ld              r5,TCB_MSGPTR_D1,r6
1243
        beq             smsg6
1244
        stx             (r5)
1245
smsg6:
1246
        ld              r5,TCB_MSGPTR_D2,r6
1247
        beq             smsg7
1248
        sty             (r5)
1249
smsg7:
1250
        ld              r5,TCB_Status,r6
1251
        and             r5,r5,#TS_TIMEOUT
1252
        beq             smsg8
1253
        ld              r1,r6
1254
        jsr             RemoveFromTimeoutList
1255
smsg8:
1256
        ld              r1,r6
1257
        jsr             AddTaskToReadyList
1258
smsg5:
1259
        plp
1260
        pop             r6
1261
        pop             r5
1262
        pop             r4
1263
        lda             #E_Ok
1264
        rts
1265
smsg1:
1266
        lda             #E_BadMbx
1267
        rts
1268
smsg2:
1269
        plp
1270
        pop             r6
1271
        pop             r5
1272
        pop             r4
1273
        lda             #E_NotAlloc
1274
        rts
1275
smsg4:
1276
        plp
1277
        pop             r6
1278
        pop             r5
1279
        pop             r4
1280
        lda             #E_NoMsg
1281
        rts
1282
 
1283
;------------------------------------------------------------------------------
1284
; WaitMsg
1285
; Wait at a mailbox for a message to arrive. This subroutine will block the
1286
; task until a message is available or the task times out on the timeout
1287
; list.
1288
;
1289
; Parameters
1290
;       r1=mailbox
1291
;       r2=pointer to D1
1292
;       r3=pointer to D2
1293
;       r4=timeout
1294
; Returns:
1295
;       r1=E_Ok                 if everything is ok
1296
;       r1=E_BadMbx             for a bad mailbox number
1297
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1298
;------------------------------------------------------------------------------
1299
WaitMsg:
1300
        cmp             #0                                              ; check the mailbox number to make sure
1301
        bmi             wmsg1                                   ; that it's sensible
1302
        cmp             #2047
1303
        bpl             wmsg1
1304
        phx
1305
        phy
1306
        push    r4
1307
        push    r5
1308
        push    r6
1309
        push    r7
1310
        ld              r6,r1
1311
        php
1312
        sei
1313
        ld              r5,MBX_OWNER,r1
1314
        bmi             wmsg2                                   ; error: no owner
1315
        jsr             DequeueMsgFromMbx
1316
        cmp             #0
1317
        bpl             wmsg3
1318
 
1319
        ; Here there was no message available, remove the task from
1320
        ; the ready list, and optionally add it to the timeout list.
1321
        ; Queue the task at the mailbox.
1322
        lda             RunningTCB                              ; remove the task from the ready list
1323
        jsr             RemoveTaskFromReadyList
1324
        ld              r7,TCB_Status,r1                        ; set task status to waiting
1325
        or              r7,r7,#TS_WAITMSG
1326
        st              r7,TCB_Status,r1
1327
        st              r6,TCB_hWaitMbx,r1                      ; set which mailbox is waited for
1328
        ld              r7,#-1
1329
        st              r7,TCB_mbq_next,r1                      ; adding at tail, so there is no next
1330
        stx             TCB_MSGPTR_D1,r1                        ; save off the message pointers
1331
        sty             TCB_MSGPTR_D2,r1
1332
        ld              r7,MBX_TQ_HEAD,r1                       ; is there a task que setup at the mailbox ?
1333
        bmi             wmsg6
1334
        ld              r7,MBX_TQ_TAIL,r6
1335
        st              r7,TCB_mbq_prev,r1
1336
        sta             TCB_mbq_next,r7
1337
        sta             MBX_TQ_TAIL,r6
1338
        inc             MBX_TQ_COUNT,r6                         ; increment number of tasks queued
1339
wmsg7:
1340
        cmp             r4,#0                                           ; check for a timeout
1341
        beq             wmsg10
1342
        ld              r2,r4
1343
        jsr             AddToTimeoutList
1344
wmsg10:
1345
        ld              r2,#wmsg8                                       ; save the return address
1346 28 robfinch
PushRegsAndRunTask:
1347 26 robfinch
        phx
1348
        php                                                                     ; save status register
1349
        pha                                                                     ; and save the register set
1350
        phx
1351
        phy
1352
        push    r4
1353
        push    r5
1354
        push    r6
1355
        push    r7
1356
        push    r8
1357
        push    r9
1358
        push    r10
1359
        push    r11
1360
        push    r12
1361
        push    r13
1362
        push    r14
1363
        push    r15
1364
        jmp             SelectTaskToRun
1365
 
1366
        ; Here there were no prior tasks queued at the mailbox
1367
wmsg6:
1368
        ld              r7,#-1
1369
        st              r7,TCB_mbq_prev,r1              ; no previous tasks
1370
        st              r7,TCB_mbq_next,r1
1371
        sta             MBX_TQ_HEAD,r6                  ; set both head and tail indexes
1372
        sta             MBX_TQ_TAIL,r6
1373
        ld              r7,#1
1374
        st              r7,MBX_TQ_COUNT,r6              ; one task queued
1375
        bra             wmsg7                                   ; check for a timeout value
1376
 
1377
        ; Store message D1 to pointer
1378
wmsg3:
1379
        cpx             #0
1380
        beq             wmsg4
1381
        ld              r7,MSG_D1,r1
1382
        st              r7,(x)
1383
        ; Store message D2 to pointer
1384
wmsg4:
1385
        cpy             #0
1386
        beq             wmsg5
1387
        ld              r7,MSG_D2,r1
1388
        st              r7,(y)
1389
        ; Add the newly dequeued message to the free messsage list
1390
wmsg5:
1391
        ld              r7,FreeMsg
1392
        st              r7,MSG_LINK,r1
1393
        sta             FreeMsg
1394
        inc             nMsgBlk
1395
wmsg8:
1396
        plp
1397
        pop             r7
1398
        pop             r6
1399
        pop             r5
1400
        pop             r4
1401
        ply
1402
        plx
1403
        lda             #E_Ok
1404
        rts
1405
wmsg1:
1406
        lda             #E_BadMbx
1407
        rts
1408
wmsg2:
1409
        plp
1410
        pop             r7
1411
        pop             r6
1412
        pop             r5
1413
        pop             r4
1414
        ply
1415
        plx
1416
        lda             #E_NotAlloc
1417
        rts
1418
 
1419
;------------------------------------------------------------------------------
1420
; CheckMsg
1421
; Check for a message at a mailbox. Does not block.
1422
;
1423
; Parameters
1424
;       r1=mailbox
1425
;       r2=pointer to D1
1426
;       r3=pointer to D2
1427
;       r4=remove from queue if present
1428
; Returns:
1429
;       r1=E_Ok                 if everything is ok
1430
;       r1=E_NoMsg              if no message is available
1431
;       r1=E_BadMbx             for a bad mailbox number
1432
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1433
;------------------------------------------------------------------------------
1434
CheckMsg:
1435
        cmp             #0                                              ; check the mailbox number to make sure
1436
        bmi             cmsg1                                   ; that it's sensible
1437
        cmp             #2047
1438
        bpl             cmsg1
1439
        phx
1440
        phy
1441
        push    r4
1442
        push    r5
1443
        php
1444
        sei
1445
        ld              r5,MBX_OWNER,r1
1446
        bmi             cmsg2                                   ; error: no owner
1447
        cmp             r4,#0                                   ; are we to dequeue the message ?
1448
        beq             cmsg3
1449
        jsr             DequeueMsgFromMbx
1450
        bra             cmsg4
1451
cmsg3:
1452 28 robfinch
        lda             MBX_MQ_HEAD,r1                  ; peek the message at the head of the messages queue
1453 26 robfinch
cmsg4:
1454
        cmp             #0
1455
        bmi             cmsg5
1456
        cpx             #0
1457
        beq             cmsg6
1458
        ld              r5,MSG_D1,r1
1459
        st              r5,(x)
1460
cmsg6:
1461
        cpy             #0
1462
        beq             cmsg7
1463
        ld              r5,MSG_D2,r1
1464
        st              r5,(y)
1465
cmsg7:
1466
        cmp             r4,#0
1467
        beq             cmsg8
1468
        ld              r5,FreeMsg
1469
        st              r5,MSG_LINK,r1
1470
        sta             FreeMsg
1471
        inc             nMsgBlk
1472
cmsg8:
1473
        plp
1474
        pop             r5
1475
        pop             r4
1476
        ply
1477
        plx
1478
        lda             #E_Ok
1479
        rts
1480
cmsg1:
1481
        lda             #E_BadMbx
1482
        rts
1483
cmsg2:
1484
        plp
1485
        pop             r5
1486
        pop             r4
1487
        ply
1488
        plx
1489
        lda             #E_NotAlloc
1490
        rts
1491
cmsg5:
1492
        plp
1493
        pop             r5
1494
        pop             r4
1495
        ply
1496
        plx
1497
        lda             #E_NoMsg
1498
        rts
1499
 
1500
;------------------------------------------------------------------------------
1501
;------------------------------------------------------------------------------
1502 28 robfinch
SetIOFocusBit:
1503
        and             r1,r2,#$1F              ; get bit index 0 to 31
1504
        ldy             #1
1505
        asl             r3,r3,r1                ; shift bit to proper place
1506
        lsr             r2,r2,#5                ; get word index /32 bits per word
1507
        lda             IOFocusTbl,x
1508
        or              r1,r1,r3
1509
        sta             IOFocusTbl,x
1510 26 robfinch
        rts
1511
 
1512
;------------------------------------------------------------------------------
1513
; The I/O focus list is an array indicating which tasks are requesting the
1514
; I/O focus. The I/O focus is user controlled by pressing ALT-TAB on the
1515
; keyboard.
1516
;------------------------------------------------------------------------------
1517
message "RequestIOFocus"
1518
RequestIOFocus:
1519
        pha
1520
        phx
1521
        phy
1522
        php
1523
        sei
1524 28 robfinch
        ldx             RunningTCB
1525
        ldy             IOFocusNdx              ; Is the focus list empty ?
1526
        bmi             riof2
1527
        cpx             IOFocusNdx              ; does the task already have the focus ?
1528
        beq             riof4
1529
        lda             TCB_Status,x    ; update the task status to waiting for focus
1530
        or              #TS_WAITFOCUS
1531
        sta             TCB_Status,x
1532
riof4:
1533
        lda             TCB_iof_next,x  ; is the task already in the IO focus list ?
1534
        bpl             riof3
1535
        lda             IOFocusNdx              ; Expand the list
1536
        ldy             TCB_iof_prev,r1
1537
        stx             TCB_iof_prev,r1
1538
        sta             TCB_iof_next,x
1539
        sty             TCB_iof_prev,x
1540
        stx             TCB_iof_next,y
1541
riof3:
1542
        jsr             SetIOFocusBit
1543
 
1544
        ; If the task doesn't have the I/O focus, then remove it
1545
        ; from the ready list.
1546 26 robfinch
        ldx             RunningTCB
1547 28 robfinch
        cpx             IOFocusNdx
1548
        beq             riof5
1549
        txa
1550
        jsr             RemoveTaskFromReadyList
1551
riof5:
1552 26 robfinch
        plp
1553
        ply
1554
        plx
1555
        pla
1556
        rts
1557 28 robfinch
 
1558
        ; Here, the IO focus list was empty. So expand it.
1559
        ; Update pointers to loop back to self.
1560
riof2:
1561
        stx             IOFocusNdx
1562
        stx             TCB_iof_next,x
1563
        stx             TCB_iof_prev,x
1564
        lda             TCB_Status,x
1565
        and             #~TS_WAITFOCUS
1566
        sta             TCB_Status,x
1567
        bra             riof3
1568
 
1569
;------------------------------------------------------------------------------
1570
; Releasing the I/O focus causes the focus to switch if the running task
1571
; had the I/O focus.
1572
;------------------------------------------------------------------------------
1573 26 robfinch
message "ReleaseIOFocus"
1574
ReleaseIOFocus:
1575
        pha
1576
        phx
1577
        phy
1578
        php
1579
        sei
1580 28 robfinch
        ldx             RunningTCB
1581
        phx
1582
        lda             TCB_Status,x    ; set the task status as no longer waiting for
1583
        and             r1,r1,#~TS_WAITFOCUS    ; focus
1584
        sta             TCB_Status,x
1585
        ldy             #1
1586 26 robfinch
        and             r1,r2,#$1F              ; get bit index 0 to 31
1587
        asl             r3,r3,r1                ; shift bit to proper place
1588
        eor             r3,r3,#-1               ; invert bit mask
1589
        lsr             r2,r2,#5                ; get word index /32 bits per word
1590 28 robfinch
        lda             IOFocusTbl,x
1591 26 robfinch
        and             r1,r1,r3
1592 28 robfinch
        sta             IOFocusTbl,x
1593
        plx
1594
        cpx             IOFocusNdx              ; Does the running task have the I/O focus ?
1595
        bne             rliof1
1596
        jsr             SwitchIOFocus   ; If so, then switch the focus.
1597
rliof1:
1598
        lda             TCB_iof_next,x  ; get next and previous fields.
1599
        bmi             rliof2                  ; Is the task on the list ?
1600
        ldy             TCB_iof_prev,x
1601
        sta             TCB_iof_next,y  ; prev->next = current->next
1602
        sty             TCB_iof_prev,r1 ; next->prev = current->prev
1603
        cmp             r1,r3                   ; Check if the IO focus list is collapsing.
1604
        bne             rliof2                  ; If the list just points back to the task
1605
        cmp             r1,r2                   ; being removed, then it's the last task
1606
        bne             rliof2                  ; removed from the list, so the list is being
1607
        lda             #-1                             ; emptied.
1608
        sta             IOFocusNdx
1609
rliof2:
1610
        lda             #-1                             ; Update the next and prev fields to indicate
1611
        sta             TCB_iof_next,x  ; the task is no longer on the list.
1612
        sta             TCB_iof_prev,x
1613 26 robfinch
        plp
1614
        ply
1615
        plx
1616
        pla
1617
        rts
1618
 
1619
;------------------------------------------------------------------------------
1620
;------------------------------------------------------------------------------
1621
GetScreenLocation:
1622
        lda             RunningTCB
1623 28 robfinch
        cmp             IOFocusNdx
1624 26 robfinch
        beq             gsl1
1625
        asl             r1,r1,#13                       ; 8192 words per screen
1626
        add             r1,r1,#BIOS_SCREENS
1627
        rts
1628
gsl1:
1629
        lda             #TEXTSCR
1630
        rts
1631
 
1632
GetColorCodeLocation:
1633
        lda             RunningTCB
1634 28 robfinch
        cmp             IOFocusNdx
1635 26 robfinch
        beq             gccl1
1636
        asl             r1,r1,#13                       ; 8192 words per screen
1637
        add             r1,r1,#BIOS_SCREENS+4096
1638
        rts
1639
gccl1:
1640
        lda             #TEXTSCR+$10000
1641
        rts
1642
 
1643
;------------------------------------------------------------------------------
1644
;------------------------------------------------------------------------------
1645
message "CopyVirtualScreenToScreen"
1646
CopyVirtualScreenToScreen
1647
        pha
1648
        phx
1649
        phy
1650 28 robfinch
        push    r4
1651 26 robfinch
        lda             #4095                           ; number of words to copy-1
1652 28 robfinch
        ldx             IOFocusNdx                      ; compute virtual screen location
1653
        bmi             cvss3
1654 26 robfinch
        asl             r2,r2,#13                       ; 8192 words per screen
1655
        add             r2,r2,#BIOS_SCREENS     ; add in screens array base address
1656
        ldy             #TEXTSCR
1657
;       mvn
1658
cvss1:
1659
        ld              r4,(x)
1660
        st              r4,(y)
1661
        inx
1662
        iny
1663
        dea
1664
        bne             cvss1
1665
        ; now copy the color codes
1666
        lda             #4095
1667 28 robfinch
        ldx             IOFocusNdx
1668 26 robfinch
        asl             r2,r2,#13
1669
        add             r2,r2,#BIOS_SCREENS+4096        ; virtual char color array
1670
        ldy             #TEXTSCR+$10000
1671
cvss2:
1672
        ld              r4,(x)
1673
        st              r4,(y)
1674
        inx
1675
        iny
1676
        dea
1677
        bne             cvss2
1678 28 robfinch
cvss3:
1679
        ; reset the cursor position in the text controller
1680
        ldy             IOFocusNdx
1681
        ldx             TCB_CursorRow,y
1682
        lda             TEXTREG+TEXT_COLS
1683
        mul             r2,r2,r1
1684
        add             r2,r2,TCB_CursorCol,y
1685
        stx             TEXTREG+TEXT_CURPOS
1686
        pop             r4
1687 26 robfinch
        ply
1688
        plx
1689
        pla
1690
        rts
1691
message "CopyScreenToVirtualScreen"
1692
CopyScreenToVirtualScreen
1693
        pha
1694
        phx
1695
        phy
1696 28 robfinch
        push    r4
1697 26 robfinch
        lda             #4095
1698
        ldx             #TEXTSCR
1699 28 robfinch
        ldy             IOFocusNdx
1700
        bmi             csvs3
1701 26 robfinch
        asl             r3,r3,#13
1702
        add             r3,r3,#BIOS_SCREENS
1703
csvs1:
1704
        ld              r4,(x)
1705
        st              r4,(y)
1706
        inx
1707
        iny
1708
        dea
1709
        bne             csvs1
1710
        lda             #4095
1711
        ldx             #TEXTSCR+$10000
1712 28 robfinch
        ldy             IOFocusNdx
1713 26 robfinch
        asl             r3,r3,#13
1714
        add             r3,r3,#BIOS_SCREENS+4096
1715
csvs2:
1716
        ld              r4,(x)
1717
        st              r4,(y)
1718
        inx
1719
        iny
1720
        dea
1721
        bne             csvs2
1722 28 robfinch
csvs3:
1723
        pop             r4
1724 26 robfinch
        ply
1725
        plx
1726
        pla
1727
        rts
1728
 
1729
;------------------------------------------------------------------------------
1730 11 robfinch
; Clear the screen and the screen color memory
1731
; We clear the screen to give a visual indication that the system
1732
; is working at all.
1733
;------------------------------------------------------------------------------
1734
;
1735 26 robfinch
message "ClearScreen"
1736 11 robfinch
ClearScreen:
1737
        pha                                                     ; holds a space character
1738
        phx                                                     ; loop counter
1739
        phy                                                     ; memory addressing
1740
        push    r4                                      ; holds the screen color
1741 26 robfinch
        push    r5
1742 11 robfinch
        lda             TEXTREG+TEXT_COLS       ; calc number to clear
1743
        ldx             TEXTREG+TEXT_ROWS
1744
        mul             r2,r1,r2                        ; r2 = # chars to clear
1745 26 robfinch
        jsr             GetScreenLocation
1746
        tay
1747
        jsr             GetColorCodeLocation
1748
        ld              r5,r1
1749 11 robfinch
        lda             #' '                            ; space char
1750
        ld              r4,ScreenColor
1751
        jsr             AsciiToScreen
1752
csj4:
1753
        sta             (y)
1754
        iny
1755 26 robfinch
        st              r4,(r5)
1756
        inc             r5
1757 11 robfinch
        dex
1758
        bne             csj4
1759 26 robfinch
        pop             r5
1760 11 robfinch
        pop             r4
1761
        ply
1762
        plx
1763
        pla
1764
        rts
1765
 
1766
;------------------------------------------------------------------------------
1767
; Scroll text on the screen upwards
1768
;------------------------------------------------------------------------------
1769
;
1770 26 robfinch
message "ScrollUp"
1771 11 robfinch
ScrollUp:
1772
        pha
1773
        phx
1774
        phy
1775
        push    r4
1776
        push    r5
1777 26 robfinch
        push    r6
1778 11 robfinch
        lda             TEXTREG+TEXT_COLS       ; acc = # text columns
1779
        ldx             TEXTREG+TEXT_ROWS
1780
        mul             r2,r1,r2                        ; calc number of chars to scroll
1781
        sub             r2,r2,r1                        ; one less row
1782 26 robfinch
        pha
1783
        jsr             GetScreenLocation
1784
        tay
1785
        jsr             GetColorCodeLocation
1786
        ld              r6,r1
1787
        pla
1788 11 robfinch
scrup1:
1789
        add             r5,r3,r1
1790
        ld              r4,(r5)                         ; move character
1791
        st              r4,(y)
1792 26 robfinch
        add             r5,r6,r1
1793
        ld              r4,(r5)                         ; and move color code
1794
        st              r4,(r6)
1795 11 robfinch
        iny
1796 26 robfinch
        inc             r6
1797 11 robfinch
        dex
1798
        bne             scrup1
1799
        lda             TEXTREG+TEXT_ROWS
1800
        dea
1801
        jsr             BlankLine
1802 26 robfinch
        pop             r6
1803 11 robfinch
        pop             r5
1804
        pop             r4
1805
        ply
1806
        plx
1807
        pla
1808
        rts
1809
 
1810
;------------------------------------------------------------------------------
1811
; Blank out a line on the display
1812
; line number to blank is in acc
1813
;------------------------------------------------------------------------------
1814
;
1815
BlankLine:
1816
        pha
1817
        phx
1818
        phy
1819 26 robfinch
        push    r4
1820 11 robfinch
        ldx             TEXTREG+TEXT_COLS       ; x = # chars to blank out from video controller
1821
        mul             r3,r2,r1                        ; y = screen index (row# * #cols)
1822 26 robfinch
        pha
1823
        jsr             GetScreenLocation
1824
        ld              r4,r1
1825
        pla
1826
        add             r3,r3,r4                ; y = screen address
1827 11 robfinch
        lda             #' '
1828 26 robfinch
        jsr             AsciiToScreen
1829 11 robfinch
blnkln1:
1830
        sta             (y)
1831
        iny
1832
        dex
1833
        bne             blnkln1
1834 26 robfinch
        pop             r4
1835 11 robfinch
        ply
1836
        plx
1837
        pla
1838
        rts
1839
 
1840
;------------------------------------------------------------------------------
1841
; Convert ASCII character to screen display character.
1842
;------------------------------------------------------------------------------
1843
;
1844
AsciiToScreen:
1845
        and             #$FF
1846
        cmp             #'A'
1847
        bcc             atoscr1         ; blt
1848
        cmp             #'Z'
1849
        bcc             atoscr1
1850
        beq             atoscr1
1851 15 robfinch
        cmp             #'z'+1
1852 11 robfinch
        bcs             atoscr1
1853
        cmp             #'a'
1854
        bcc             atoscr1
1855
        sub             #$60
1856
atoscr1:
1857
        or              #$100
1858
        rts
1859
 
1860
;------------------------------------------------------------------------------
1861
; Convert screen character to ascii character
1862
;------------------------------------------------------------------------------
1863
;
1864
ScreenToAscii:
1865
        and             #$FF
1866 15 robfinch
        cmp             #26+1
1867 11 robfinch
        bcs             stasc1
1868
        add             #$60
1869
stasc1:
1870
        rts
1871
 
1872
;------------------------------------------------------------------------------
1873 26 robfinch
; HomeCursor
1874
; Set the cursor location to the top left of the screen.
1875
;------------------------------------------------------------------------------
1876
HomeCursor:
1877
        phx
1878
        ldx             RunningTCB
1879
        stz             TCB_CursorRow,x
1880
        stz             TCB_CursorCol,x
1881
        plx
1882
        rts
1883
 
1884
;------------------------------------------------------------------------------
1885 11 robfinch
; Calculate screen memory location from CursorRow,CursorCol.
1886
; Also refreshes the cursor location.
1887
; Returns:
1888
; r1 = screen location
1889
;------------------------------------------------------------------------------
1890
;
1891
CalcScreenLoc:
1892
        phx
1893 26 robfinch
        push    r4
1894
        ld              r4,RunningTCB
1895
        lda             TCB_CursorRow,r4
1896 11 robfinch
        ldx             TEXTREG+TEXT_COLS
1897
        mul             r2,r2,r1
1898 26 robfinch
        add             r2,r2,TCB_CursorCol,r4
1899 28 robfinch
        cmp             r4,IOFocusNdx                   ; update cursor position in text controller
1900 26 robfinch
        bne             csl1                                    ; only for the task with the output focus
1901 11 robfinch
        stx             TEXTREG+TEXT_CURPOS
1902 26 robfinch
csl1:
1903
        jsr             GetScreenLocation
1904
        add             r1,r2,r1
1905
csl2:
1906
        pop             r4
1907 11 robfinch
        plx
1908
        rts
1909
 
1910
;------------------------------------------------------------------------------
1911 26 robfinch
; Display a character on the screen.
1912
; If the task doesn't have the I/O focus then the character is written to
1913
; the virtual screen.
1914 11 robfinch
; r1 = char to display
1915
;------------------------------------------------------------------------------
1916
;
1917 26 robfinch
message "DisplayChar"
1918 11 robfinch
DisplayChar:
1919 26 robfinch
        push    r4
1920
        ld              r4,RunningTCB
1921
        and             #$FF                            ; mask off any higher order bits (called from eight bit mode).
1922 11 robfinch
        cmp             #'\r'                           ; carriage return ?
1923
        bne             dccr
1924 26 robfinch
        stz             TCB_CursorCol,r4        ; just set cursor column to zero on a CR
1925 11 robfinch
        jsr             CalcScreenLoc
1926 26 robfinch
        pop             r4
1927 11 robfinch
        rts
1928
dccr:
1929
        cmp             #$91                            ; cursor right ?
1930
        bne             dcx6
1931
        pha
1932 26 robfinch
        lda             TCB_CursorCol,r4
1933 11 robfinch
        cmp             #83
1934
        bcs             dcx7
1935
        ina
1936 26 robfinch
        sta             TCB_CursorCol,r4
1937 11 robfinch
dcx7:
1938
        jsr             CalcScreenLoc
1939
        pla
1940 26 robfinch
        pop             r4
1941 11 robfinch
        rts
1942
dcx6:
1943
        cmp             #$90                            ; cursor up ?
1944
        bne             dcx8
1945
        pha
1946 26 robfinch
        lda             TCB_CursorRow,r4
1947 11 robfinch
        beq             dcx7
1948
        dea
1949 26 robfinch
        sta             TCB_CursorRow,r4
1950 11 robfinch
        bra             dcx7
1951
dcx8:
1952
        cmp             #$93                            ; cursor left ?
1953
        bne             dcx9
1954
        pha
1955 26 robfinch
        lda             TCB_CursorCol,r4
1956 11 robfinch
        beq             dcx7
1957
        dea
1958 26 robfinch
        sta             TCB_CursorCol,r4
1959 11 robfinch
        bra             dcx7
1960
dcx9:
1961
        cmp             #$92                            ; cursor down ?
1962
        bne             dcx10
1963
        pha
1964 26 robfinch
        lda             TCB_CursorRow,r4
1965 11 robfinch
        cmp             #46
1966
        beq             dcx7
1967
        ina
1968 26 robfinch
        sta             TCB_CursorRow,r4
1969 11 robfinch
        bra             dcx7
1970
dcx10:
1971
        cmp             #$94                            ; cursor home ?
1972
        bne             dcx11
1973
        pha
1974 26 robfinch
        lda             TCB_CursorCol,r4
1975 11 robfinch
        beq             dcx12
1976 26 robfinch
        stz             TCB_CursorCol,r4
1977 11 robfinch
        bra             dcx7
1978
dcx12:
1979 26 robfinch
        stz             TCB_CursorRow,r4
1980 11 robfinch
        bra             dcx7
1981
dcx11:
1982
        pha
1983
        phx
1984
        phy
1985
        cmp             #$99                            ; delete ?
1986
        bne             dcx13
1987
        jsr             CalcScreenLoc
1988
        tay                                                     ; y = screen location
1989 26 robfinch
        lda             TCB_CursorCol,r4        ; acc = cursor column
1990 11 robfinch
        bra             dcx5
1991
dcx13
1992
        cmp             #CTRLH                          ; backspace ?
1993
        bne             dcx3
1994 26 robfinch
        lda             TCB_CursorCol,r4
1995 11 robfinch
        beq             dcx4
1996
        dea
1997 26 robfinch
        sta             TCB_CursorCol,r4
1998 11 robfinch
        jsr             CalcScreenLoc           ; acc = screen location
1999
        tay                                                     ; y = screen location
2000 26 robfinch
        lda             TCB_CursorCol,r4
2001 11 robfinch
dcx5:
2002
        ldx             $4,y
2003
        stx             (y)
2004
        iny
2005
        ina
2006
        cmp             TEXTREG+TEXT_COLS
2007
        bcc             dcx5
2008
        lda             #' '
2009
        jsr             AsciiToScreen
2010
        dey
2011
        sta             (y)
2012
        bra             dcx4
2013
dcx3:
2014
        cmp             #'\n'                   ; linefeed ?
2015
        beq             dclf
2016
        tax                                             ; save acc in x
2017
        jsr     CalcScreenLoc   ; acc = screen location
2018
        tay                                             ; y = screen location
2019
        txa                                             ; restore r1
2020
        jsr             AsciiToScreen   ; convert ascii char to screen char
2021
        sta             (y)
2022 26 robfinch
        jsr             GetScreenLocation
2023
        sub             r3,r3,r1                ; make y an index into the screen
2024
        jsr             GetColorCodeLocation
2025
        add             r3,r3,r1
2026 11 robfinch
        lda             CharColor
2027 26 robfinch
        sta             (y)
2028 11 robfinch
        jsr             IncCursorPos
2029
        bra             dcx4
2030
dclf:
2031
        jsr             IncCursorRow
2032
dcx4:
2033
        ply
2034
        plx
2035
        pla
2036 26 robfinch
        pop             r4
2037 11 robfinch
        rts
2038
 
2039
;------------------------------------------------------------------------------
2040
; Increment the cursor position, scroll the screen if needed.
2041
;------------------------------------------------------------------------------
2042
;
2043
IncCursorPos:
2044
        pha
2045
        phx
2046 26 robfinch
        push    r4
2047
        ld              r4,RunningTCB
2048
        lda             TCB_CursorCol,r4
2049 11 robfinch
        ina
2050 26 robfinch
        sta             TCB_CursorCol,r4
2051 11 robfinch
        ldx             TEXTREG+TEXT_COLS
2052
        cmp             r1,r2
2053
        bcc             icc1
2054 26 robfinch
        stz             TCB_CursorCol,r4                ; column = 0
2055 11 robfinch
        bra             icr1
2056
IncCursorRow:
2057
        pha
2058
        phx
2059 26 robfinch
        push    r4
2060
        ld              r4,RunningTCB
2061 11 robfinch
icr1:
2062 26 robfinch
        lda             TCB_CursorRow,r4
2063 11 robfinch
        ina
2064 26 robfinch
        sta             TCB_CursorRow,r4
2065 11 robfinch
        ldx             TEXTREG+TEXT_ROWS
2066
        cmp             r1,r2
2067
        bcc             icc1
2068
        beq             icc1
2069
        dex                                                     ; backup the cursor row, we are scrolling up
2070 26 robfinch
        stx             TCB_CursorRow,r4
2071 11 robfinch
        jsr             ScrollUp
2072
icc1:
2073
        jsr             CalcScreenLoc
2074 26 robfinch
        pop             r4
2075 11 robfinch
        plx
2076
        pla
2077
        rts
2078
 
2079
;------------------------------------------------------------------------------
2080
; Display a string on the screen.
2081
; The characters are packed 4 per word
2082
;------------------------------------------------------------------------------
2083
;
2084
DisplayStringB:
2085
        pha
2086
        phx
2087
        tax                                             ; r2 = pointer to string
2088
dspj1B:
2089 15 robfinch
        lb              r1,0,x                  ; move string char into acc
2090 11 robfinch
        inx                                             ; increment pointer
2091
        cmp             #0                              ; is it end of string ?
2092
        beq             dsretB
2093
        jsr             DisplayChar             ; display character
2094 15 robfinch
        bra             dspj1B
2095 11 robfinch
dsretB:
2096
        plx
2097
        pla
2098
        rts
2099
 
2100
;------------------------------------------------------------------------------
2101
; Display a string on the screen.
2102
; The characters are packed 1 per word
2103
;------------------------------------------------------------------------------
2104
;
2105
DisplayStringW:
2106
        pha
2107
        phx
2108
        tax                                             ; r2 = pointer to string
2109
dspj1W:
2110
        lda             (x)                             ; move string char into acc
2111
        inx                                             ; increment pointer
2112
        cmp             #0                              ; is it end of string ?
2113
        beq             dsretW
2114
        jsr             DisplayChar             ; display character
2115
        bra             dspj1W                  ; go back for next character
2116
dsretW:
2117
        plx
2118
        pla
2119
        rts
2120
 
2121
DisplayStringCRLFB:
2122
        jsr             DisplayStringB
2123
CRLF:
2124
        pha
2125
        lda             #'\r'
2126
        jsr             DisplayChar
2127
        lda             #'\n'
2128
        jsr             DisplayChar
2129
        pla
2130
        rts
2131
 
2132
;------------------------------------------------------------------------------
2133 15 robfinch
; Initialize keyboard
2134
;
2135
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
2136
; set #2 (the most common one). Also sets up the keyboard buffer and
2137
; initializes the keyboard semaphore.
2138
;------------------------------------------------------------------------------
2139
;
2140 26 robfinch
message "KeybdInit"
2141 15 robfinch
KeybdInit:
2142
        lda             #1                      ; setup semaphore
2143 26 robfinch
        sta             KEYBD_SEMA
2144
        ldx             #0
2145
kbdi1:
2146
        stz             KeybdHead,x             ; setup keyboard buffer
2147
        stz             KeybdTail,x
2148 15 robfinch
        lda             #1                      ; turn on keyboard echo
2149 26 robfinch
        sta             KeybdEcho,x
2150
        stz             KeybdBad,x
2151
        inx
2152
        cpx             #256
2153
        bne             kbdi1
2154 15 robfinch
 
2155
        lda             #$ff            ; issue keyboard reset
2156
        jsr             SendByteToKeybd
2157
        lda             #1000000                ; delay a bit
2158
kbdi5:
2159
        dea
2160
        bne             kbdi5
2161
        lda             #0xf0           ; send scan code select
2162
        jsr             SendByteToKeybd
2163
        ldx             #0xFA
2164
        jsr             WaitForKeybdAck
2165
        cmp             #$FA
2166
        bne             kbdi2
2167
        lda             #2                      ; select scan code set#2
2168
        jsr             SendByteToKeybd
2169
kbdi2:
2170
        rts
2171
 
2172
msgBadKeybd:
2173
        db              "Keyboard not responding.",0
2174
 
2175
SendByteToKeybd:
2176 26 robfinch
        phx
2177
        ldx             RunningTCB
2178 15 robfinch
        sta             KEYBD
2179
        tsr             TICK,r3
2180
kbdi4:                                          ; wait for transmit complete
2181
        tsr             TICK,r4
2182
        sub             r4,r4,r3
2183
        cmp             r4,#1000000
2184
        bcs             kbdbad
2185
        lda             KEYBD+3
2186
        bit             #64
2187
        beq             kbdi4
2188
        bra             sbtk1
2189
kbdbad:
2190 26 robfinch
        lda             KeybdBad,x
2191 15 robfinch
        bne             sbtk1
2192
        lda             #1
2193 26 robfinch
        sta             KeybdBad,x
2194 15 robfinch
        lda             #msgBadKeybd
2195
        jsr             DisplayStringCRLFB
2196
sbtk1:
2197 26 robfinch
        plx
2198 15 robfinch
        rts
2199
 
2200
; Wait for keyboard to respond with an ACK (FA)
2201
;
2202
WaitForKeybdAck:
2203
        tsr             TICK,r3
2204
wkbdack1:
2205
        tsr             TICK,r4
2206
        sub             r4,r4,r3
2207
        cmp             r4,#1000000
2208
        bcs             wkbdbad
2209
        lda             KEYBD
2210
        bit             #$8000
2211
        beq             wkbdack1
2212
;       lda             KEYBD+8
2213
        and             #$ff
2214
wkbdbad:
2215
        rts
2216
 
2217
; Wait for keyboard to respond with an ACK (FA)
2218
; This routine picks up the ack status left by the
2219
; keyboard IRQ routine.
2220
; r2 = 0xFA (could also be 0xEE for echo command)
2221
;
2222
WaitForKeybdAck2:
2223 26 robfinch
        phx
2224
        ldx             RunningTCB
2225
WaitForKeybdAck2a:
2226
        lda             KeybdAck,x
2227 15 robfinch
        cmp             r1,r2
2228 26 robfinch
        bne             WaitForKeybdAck2a
2229
        stz             KeybdAck,x
2230
        plx
2231 15 robfinch
        rts
2232
 
2233
;------------------------------------------------------------------------------
2234
; Normal keyboard interrupt, the lowest priority interrupt in the system.
2235
; Grab the character from the keyboard device and store it in a buffer.
2236 26 robfinch
; The buffer of the task with the input focus is updated.
2237 15 robfinch
;------------------------------------------------------------------------------
2238
;
2239 26 robfinch
message "KeybdIRQ"
2240 15 robfinch
KeybdIRQ:
2241 26 robfinch
        cld
2242 15 robfinch
        pha
2243
        phx
2244
        phy
2245 26 robfinch
        push    r4
2246
 
2247
        ; support EhBASIC's IRQ functionality
2248
        ; code derived from minimon.asm
2249
        lda             #15                             ; Keyboard is IRQ #15
2250
        sta             IrqSource
2251
        lb              r1,IrqBase              ; get the IRQ flag byte
2252
        lsr             r2,r1
2253
        or              r1,r1,r2
2254
        and             #$E0
2255
        sb              r1,IrqBase              ; save the new IRQ flag byte
2256
 
2257 28 robfinch
        ld              r4,IOFocusNdx   ; get the task with the input focus
2258 26 robfinch
 
2259 15 robfinch
        ldx             KEYBD                           ; get keyboard character
2260
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
2261
        txy                                                     ; check for a keyboard ACK code
2262
        and             r3,r3,#$ff
2263
        cmp             r3,#$FA
2264
        bne             KeybdIrq1
2265 26 robfinch
        sty             KeybdAck,r4
2266 15 robfinch
        bra             KeybdIRQc
2267
KeybdIrq1:
2268
        bit             r2,#$800                                ; test bit #11
2269
        bne             KeybdIRQc                               ; ignore keyup messages for now
2270 26 robfinch
KeybdIrq2:
2271
        lda             KeybdHead,r4
2272 15 robfinch
        ina                                                             ; increment head pointer
2273
        and             #$f                                             ; limit
2274 26 robfinch
        ldy             KeybdTail,r4                    ; check for room in the keyboard buffer
2275 15 robfinch
        cmp             r1,r3
2276
        beq             KeybdIRQc                               ; if no room, the newest char will be lost
2277 26 robfinch
        sta             KeybdHead,r4
2278 15 robfinch
        dea
2279
        and             #$f
2280 26 robfinch
        stx             KeybdLocks,r4
2281
        asl             r4,r4,#4                                        ; * 16
2282
        add             r1,r1,r4
2283 15 robfinch
        stx             KeybdBuffer,r1                  ; store character in buffer
2284
KeybdIRQc:
2285 26 robfinch
        pop             r4
2286 15 robfinch
        ply
2287
        plx
2288
        pla
2289
        rti
2290
 
2291
KeybdRstIRQ:
2292 26 robfinch
        jmp             start
2293 15 robfinch
 
2294
;------------------------------------------------------------------------------
2295
; r1 0=echo off, non-zero = echo on
2296
;------------------------------------------------------------------------------
2297
SetKeyboardEcho:
2298 26 robfinch
        phx
2299
        ldx             RunningTCB
2300
        sta             KeybdEcho,x
2301
        plx
2302 15 robfinch
        rts
2303
 
2304 26 robfinch
;------------------------------------------------------------------------------
2305
; Get a bit from the I/O focus table.
2306
;------------------------------------------------------------------------------
2307
GetIOFocusBit:
2308
        phx
2309
        phy
2310
        tax
2311
        and             r1,r1,#$1F              ; get bit index into word
2312
        lsr             r2,r2,#5                ; get word index into table
2313 28 robfinch
        ldy             IOFocusTbl,x
2314 26 robfinch
        lsr             r3,r3,r1                ; extract bit
2315
        and             r1,r3,#1
2316
        ply
2317
        plx
2318
        rts
2319
 
2320
;------------------------------------------------------------------------------
2321
; SwitchIOFocus
2322 28 robfinch
; Switches the IO focus to the next task requesting the I/O focus. This
2323
; routine may be called when a task releases the I/O focus as well as when
2324
; the user presses ALT-TAB on the keyboard.
2325 26 robfinch
;------------------------------------------------------------------------------
2326
;
2327
SwitchIOFocus:
2328 28 robfinch
        pha
2329 26 robfinch
        phx
2330 28 robfinch
        phy
2331 26 robfinch
 
2332 28 robfinch
        ; First check if it's even possible to switch the focus to another
2333
        ; task. The I/O focus list could be empty or there may be only a
2334
        ; single task in the list. In either case it's not possible to
2335
        ; switch.
2336
        ldy             IOFocusNdx              ; Get the task at the head of the list.
2337
        bmi             siof3                   ; Is the list empty ?
2338
        lda             TCB_iof_next,y  ; Get the next task on the list.
2339
        cmp             r1,r3                   ; Will the list head change ?
2340
        beq             siof3                   ; If not then no switch will occur
2341
 
2342
        ; Check if outgoing task still wants the focus. If the task doesn't
2343
        ; want the focus there's no reason to set the status as waiting or
2344
        ; remove it from the ready list.
2345
        tya
2346
        jsr             GetIOFocusBit   ; don't set the 'waiting for focus' status
2347
        cmp             #0                              ; if not.
2348
        beq             siof1
2349
        lda             TCB_Status,y    ; Set outgoing task status to 'waiting for focus'
2350 26 robfinch
        or              r1,r1,#TS_WAITFOCUS
2351
        sta             TCB_Status,y
2352 28 robfinch
        tya                                             ; The outgoing task will now be waiting for the focus
2353 26 robfinch
        jsr             RemoveTaskFromReadyList
2354 28 robfinch
siof1:
2355
        ; Copy the current task's screen to it's virtual screen buffer.
2356
        jsr             CopyScreenToVirtualScreen
2357 26 robfinch
 
2358 28 robfinch
        lda             TCB_iof_next,y  ; Get the next task on the list.
2359
        sta             IOFocusNdx              ; Make task the new head of list.
2360
        tay
2361
        lda             TCB_Status,y
2362
        beq             siof2                   ; Check: task is exiting (status==0) so don't add it back
2363
        and             #~TS_WAITFOCUS  ; to the ready list.
2364 26 robfinch
        sta             TCB_Status,y
2365
        tya
2366
        jsr             AddTaskToReadyList
2367 28 robfinch
siof2:
2368 26 robfinch
        ; Copy the virtual screen of the task recieving the I/O focus to the
2369
        ; text screen.
2370
        jsr             CopyVirtualScreenToScreen
2371 28 robfinch
siof3:
2372
        ply
2373 26 robfinch
        plx
2374 28 robfinch
        pla
2375 26 robfinch
        rts
2376
 
2377
;------------------------------------------------------------------------------
2378 15 robfinch
; Get character from keyboard buffer
2379
; return character in acc or -1 if no
2380 26 robfinch
; characters available.
2381
; Also check for ALT-TAB and switch the I/O focus.
2382
;------------------------------------------------------------------------------
2383
message "KeybdGetChar"
2384 15 robfinch
KeybdGetChar:
2385
        phx
2386 26 robfinch
        push    r4
2387
        php
2388
        sei
2389
        ld              r4,RunningTCB
2390
        ldx             KeybdTail,r4    ; if keybdTail==keybdHead then there are no
2391
        lda             KeybdHead,r4    ; characters in the keyboard buffer
2392 15 robfinch
        cmp             r1,r2
2393
        beq             nochar
2394 26 robfinch
        asl             r4,r4,#4                        ; * 16
2395
        phx
2396
        add             r2,r2,r4
2397 15 robfinch
        lda             KeybdBuffer,x
2398 26 robfinch
        plx
2399
        bit             #$200                                   ; check for ALT-tab
2400
        beq             kgc4
2401
        and             #$FF
2402
        cmp             #TAB                                    ; if we find an ALT-tab
2403
        bne             kgc4
2404
        jsr             SwitchIOFocus
2405
        ; Now eat up the ALT-TAB character
2406 28 robfinch
        ; Flush the keyboard buffer
2407
        lsr             r4,r4,#4
2408
        stz             KeybdTail,r4
2409
        stz             KeybdHead,r4
2410 26 robfinch
        bra             nochar
2411
kgc4:
2412 15 robfinch
        and             r1,r1,#$ff              ; mask off control bits
2413
        inx                                             ; increment index
2414
        and             r2,r2,#$0f
2415 26 robfinch
        lsr             r4,r4,#4                        ; / 16
2416
        stx             KeybdTail,r4
2417
        ldx             KeybdEcho,r4
2418 15 robfinch
        beq             kgc3
2419
        cmp             #CR
2420 26 robfinch
        bne             kgc8
2421 15 robfinch
        jsr             CRLF                    ; convert CR keystroke into CRLF
2422
        bra             kgc3
2423 26 robfinch
kgc8:
2424 15 robfinch
        jsr             DisplayChar
2425
        bra             kgc3
2426
nochar:
2427
        lda             #-1
2428
kgc3:
2429 26 robfinch
        plp
2430
        pop             r4
2431 15 robfinch
        plx
2432
        rts
2433
 
2434
;------------------------------------------------------------------------------
2435
; Check if there is a keyboard character available in the keyboard buffer.
2436 26 robfinch
; Returns
2437
; r1 = 1, Z=0 if there is a key available, otherwise
2438
; r1 = 0, Z=1 if there is not a key available
2439 15 robfinch
;------------------------------------------------------------------------------
2440
;
2441 26 robfinch
message "KeybdCheckForKey"
2442 15 robfinch
KeybdCheckForKey:
2443
        phx
2444 26 robfinch
        push    r4
2445
        php
2446
        sei
2447
        ld              r4,RunningTCB
2448
        lda             KeybdTail,r4
2449
        ldx             KeybdHead,r4
2450 15 robfinch
        sub             r1,r1,r2
2451
        bne             kcfk1
2452 26 robfinch
        plp
2453
        pop             r4
2454 15 robfinch
        plx
2455 26 robfinch
        lda             #0
2456 15 robfinch
        rts
2457
kcfk1
2458 26 robfinch
        plp
2459
        pop             r4
2460
        plx
2461 15 robfinch
        lda             #1
2462
        rts
2463
;------------------------------------------------------------------------------
2464
; Check if there is a keyboard character available. If so return true (1)
2465
; otherwise return false (0) in r1.
2466
;------------------------------------------------------------------------------
2467
;
2468 26 robfinch
message "KeybdCheckForKeyDirect"
2469 15 robfinch
KeybdCheckForKeyDirect:
2470
        lda             KEYBD
2471
        and             #$8000
2472
        beq             kcfkd1
2473
        lda             #1
2474
kcfkd1
2475
        rts
2476
 
2477
;------------------------------------------------------------------------------
2478
; Get character directly from keyboard. This routine blocks until a key is
2479
; available.
2480
;------------------------------------------------------------------------------
2481
;
2482
KeybdGetCharDirect:
2483
        phx
2484
kgc1:
2485
        lda             KEYBD
2486
        bit             #$8000
2487
        beq             kgc1
2488
        ld              r0,KEYBD+1              ; clear keyboard strobe
2489
        bit             #$800                   ; is it a keydown event ?
2490
        bne             kgc1
2491 26 robfinch
        bit             #$200                           ; check for ALT-tab
2492
        bne             kgc2
2493
        and             r2,r1,#$7f
2494
        cmp             r2,#TAB                                 ; if we find an ALT-tab
2495
        bne             kgc2
2496
        jsr             SwitchIOFocus
2497
        bra             kgc1
2498
kgc2:
2499 15 robfinch
        and             #$ff                    ; remove strobe bit
2500
        ldx             KeybdEcho               ; is keyboard echo on ?
2501
        beq             gk1
2502
        cmp             #CR
2503
        bne             gk2                             ; convert CR keystroke into CRLF
2504
        jsr             CRLF
2505
        bra             gk1
2506
gk2:
2507
        jsr             DisplayChar
2508
gk1:
2509
        plx
2510
        rts
2511
 
2512
 
2513 26 robfinch
;==============================================================================
2514
; Serial port
2515
;==============================================================================
2516 15 robfinch
;------------------------------------------------------------------------------
2517 26 robfinch
; Initialize the serial port
2518
; r1 = low 28 bits = baud rate
2519
; r2 = other settings
2520
; The desired baud rate must fit in 28 bits or less.
2521
;------------------------------------------------------------------------------
2522
;
2523
SerialInit:
2524
;       asl             r1,r1,#4                        ; * 16
2525
;       shlui   r1,r1,#32                       ; * 2^32
2526
;       inhu    r2,CR_CLOCK                     ; get clock frequency from config record
2527
;       divu    r1,r1,r2                        ; / clock frequency
2528
 
2529
        lsr             r1,r1,#8                        ; drop the lowest 8 bits
2530
        sta             UART_CM1                        ; set LSB
2531
        lsr             r1,r1,#8
2532
        sta             UART_CM2                        ; set middle bits
2533
        lsr             r1,r1,#8
2534
        sta             UART_CM3                        ; set MSB
2535
        stz             Uart_rxhead                     ; reset buffer indexes
2536
        stz             Uart_rxtail
2537
        lda             #0x1f0
2538
        sta             Uart_foff                       ; set threshold for XOFF
2539
        lda             #0x010
2540
        sta             Uart_fon                        ; set threshold for XON
2541
        lda             #1
2542
        sta             UART_IE                         ; enable receive interrupt only
2543
        stz             Uart_rxrts                      ; no RTS/CTS signals available
2544
        stz             Uart_txrts                      ; no RTS/CTS signals available
2545
        stz             Uart_txdtr                      ; no DTR signals available
2546
        stz             Uart_rxdtr                      ; no DTR signals available
2547
        lda             #1
2548
        sta             Uart_txxon                      ; for now
2549
        lda             #1
2550
        sta             SERIAL_SEMA
2551
        rts
2552
 
2553
;---------------------------------------------------------------------------------
2554
; Get character directly from serial port. Blocks until a character is available.
2555
;---------------------------------------------------------------------------------
2556
;
2557
SerialGetCharDirect:
2558
sgc1:
2559
        lda             UART_LS         ; uart status
2560
        and             #rxfull         ; is there a char available ?
2561
        beq             sgc1
2562
        lda             UART
2563
        rts
2564
 
2565
;------------------------------------------------
2566
; Check for a character at the serial port
2567
; returns r1 = 1 if char available, 0 otherwise
2568
;------------------------------------------------
2569
;
2570
SerialCheckForCharDirect:
2571
        lda             UART_LS                 ; uart status
2572
        and             #rxfull                 ; is there a char available ?
2573
        rts
2574
 
2575
;-----------------------------------------
2576
; Put character to serial port
2577
; r1 = char to put
2578
;-----------------------------------------
2579
;
2580
SerialPutChar:
2581
        phx
2582
        phy
2583
        push    r4
2584
        push    r5
2585
 
2586
        ldx             UART_MC
2587
        or              r2,r2,#3                ; assert DTR / RTS
2588
        stx             UART_MC
2589
        ldx             Uart_txrts
2590
        beq             spcb1
2591
        ld              r4,Milliseconds
2592
        ldy             #1000                   ; delay count (1 s)
2593
spcb3:
2594
        ldx             UART_MS
2595
        and             r2,r2,#$10              ; is CTS asserted ?
2596
        bne             spcb1
2597
        ld              r5,Milliseconds
2598
        cmp             r4,r5
2599
        beq             spcb3
2600
        ld              r4,r5
2601
        dey
2602
        bne             spcb3
2603
        bra             spcabort
2604
spcb1:
2605
        ldx             Uart_txdtr
2606
        beq             spcb2
2607
        ld              r4,Milliseconds
2608
        ldy             #1000                   ; delay count
2609
spcb4:
2610
        ldx             UART_MS
2611
        and             r2,r2,#$20              ; is DSR asserted ?
2612
        bne             spcb2
2613
        ld              r5,Milliseconds
2614
        cmp             r4,r5
2615
        beq             spcb4
2616
        ld              r4,r5
2617
        dey
2618
        bne             spcb4
2619
        bra             spcabort
2620
spcb2:
2621
        ldx             Uart_txxon
2622
        beq             spcb5
2623
spcb6:
2624
        ldx             Uart_txxonoff
2625
        beq             spcb5
2626
        ld              r4,UART_MS
2627
        and             r4,r4,#0x80                     ; DCD ?
2628
        bne             spcb6
2629
spcb5:
2630
        ld              r4,Milliseconds
2631
        ldy             #1000                           ; wait up to 1s
2632
spcb8:
2633
        ldx             UART_LS
2634
        and             r2,r2,#0x20                     ; tx not full ?
2635
        bne             spcb7
2636
        ld              r5,Milliseconds
2637
        cmp             r4,r5
2638
        beq             spcb8
2639
        ld              r4,r5
2640
        dey
2641
        bne             spcb8
2642
        bra             spcabort
2643
spcb7:
2644
        sta             UART
2645
spcabort:
2646
        pop             r5
2647
        pop             r4
2648
        ply
2649
        plx
2650
        rts
2651
 
2652
;-------------------------------------------------
2653
; Compute number of characters in recieve buffer.
2654
; r4 = number of chars
2655
;-------------------------------------------------
2656
CharsInRxBuf:
2657
        ld              r4,Uart_rxhead
2658
        ldx             Uart_rxtail
2659
        sub             r4,r4,r2
2660
        bpl             cirxb1
2661
        ld              r4,#0x200
2662
        add             r4,r4,r2
2663
        ldx             Uart_rxhead
2664
        sub             r4,r4,r2
2665
cirxb1:
2666
        rts
2667
 
2668
;----------------------------------------------
2669
; Get character from rx fifo
2670
; If the fifo is empty enough then send an XON
2671
;----------------------------------------------
2672
;
2673
SerialGetChar:
2674
        phx
2675
        phy
2676
        push    r4
2677
 
2678
        ldy             Uart_rxhead
2679
        ldx             Uart_rxtail
2680
        cmp             r2,r3
2681
        beq             sgcfifo1                ; is there a char available ?
2682
        lda             Uart_rxfifo,x   ; get the char from the fifo into r1
2683
        inx                                             ; increment the fifo pointer
2684
        and             r2,r2,#$1ff
2685
        stx             Uart_rxtail
2686
        ldx             Uart_rxflow             ; using flow control ?
2687
        beq             sgcfifo2
2688
        ldy             Uart_fon                ; enough space in Rx buffer ?
2689
        jsr             CharsInRxBuf
2690
        cmp             r4,r3
2691
        bpl             sgcfifo2
2692
        stz             Uart_rxflow             ; flow off
2693
        ld              r4,Uart_rxrts
2694
        beq             sgcfifo3
2695
        ld              r4,UART_MC              ; set rts bit in MC
2696
        or              r4,r4,#2
2697
        st              r4,UART_MC
2698
sgcfifo3:
2699
        ld              r4,Uart_rxdtr
2700
        beq             sgcfifo4
2701
        ld              r4,UART_MC              ; set DTR
2702
        or              r4,r4,#1
2703
        st              r4,UART_MC
2704
sgcfifo4:
2705
        ld              r4,Uart_rxxon
2706
        beq             sgcfifo5
2707
        ld              r4,#XON
2708
        st              r4,UART
2709
sgcfifo5:
2710
sgcfifo2:                                       ; return with char in r1
2711
        pop             r4
2712
        ply
2713
        plx
2714
        rts
2715
sgcfifo1:
2716
        lda             #-1                             ; no char available
2717
        pop             r4
2718
        ply
2719
        plx
2720
        rts
2721
 
2722
 
2723
;-----------------------------------------
2724
; Serial port IRQ
2725
;-----------------------------------------
2726
;
2727
SerialIRQ:
2728
        pha
2729
        phx
2730
        phy
2731
        push    r4
2732
 
2733
        lda             UART_IS                 ; get interrupt status
2734
        bpl             sirq1                   ; no interrupt
2735
        and             #0x7f                   ; switch on interrupt type
2736
        cmp             #4
2737
        beq             srxirq
2738
        cmp             #$0C
2739
        beq             stxirq
2740
        cmp             #$10
2741
        beq             smsirq
2742
        ; unknown IRQ type
2743
sirq1:
2744
        pop             r4
2745
        ply
2746
        plx
2747
        pla
2748
        rti
2749
 
2750
 
2751
; Get the modem status and record it
2752
smsirq:
2753
        lda             UART_MS
2754
        sta             Uart_ms
2755
        bra             sirq1
2756
 
2757
stxirq:
2758
        bra             sirq1
2759
 
2760
; Get a character from the uart and store it in the rx fifo
2761
srxirq:
2762
srxirq1:
2763
        lda             UART                            ; get the char (clears interrupt)
2764
        ldx             Uart_txxon
2765
        beq             srxirq3
2766
        cmp             #XOFF
2767
        bne             srxirq2
2768
        lda             #1
2769
        sta             Uart_txxonoff
2770
        bra             srxirq5
2771
srxirq2:
2772
        cmp             #XON
2773
        bne             srxirq3
2774
        stz             Uart_txxonoff
2775
        bra             srxirq5
2776
srxirq3:
2777
        stz             Uart_txxonoff
2778
        ldx             Uart_rxhead
2779
        sta             Uart_rxfifo,x           ; store in buffer
2780
        inx
2781
        and             r2,r2,#$1ff
2782
        stx             Uart_rxhead
2783
srxirq5:
2784
        lda             UART_LS                         ; check for another ready character
2785
        and             #rxfull
2786
        bne             srxirq1
2787
        lda             Uart_rxflow                     ; are we using flow controls?
2788
        bne             srxirq8
2789
        jsr             CharsInRxBuf
2790
        lda             Uart_foff
2791
        cmp             r4,r1
2792
        bmi             srxirq8
2793
        lda             #1
2794
        sta             Uart_rxflow
2795
        lda             Uart_rxrts
2796
        beq             srxirq6
2797
        lda             UART_MC
2798
        and             #$FD                    ; turn off RTS
2799
        sta             UART_MC
2800
srxirq6:
2801
        lda             Uart_rxdtr
2802
        beq             srxirq7
2803
        lda             UART_MC
2804
        and             #$FE                    ; turn off DTR
2805
        sta             UART_MC
2806
srxirq7:
2807
        lda             Uart_rxxon
2808
        beq             srxirq8
2809
        lda             #XOFF
2810
        sta             UART
2811
srxirq8:
2812
        bra             sirq1
2813
 
2814
 
2815
;------------------------------------------------------------------------------
2816 11 robfinch
; Display nybble in r1
2817
;------------------------------------------------------------------------------
2818
;
2819
DisplayNybble:
2820
        pha
2821
        and             #$0F
2822
        add             #'0'
2823 15 robfinch
        cmp             #'9'+1
2824 11 robfinch
        bcc             dispnyb1
2825
        add             #7
2826
dispnyb1:
2827
        jsr             DisplayChar
2828
        pla
2829
        rts
2830
 
2831
;------------------------------------------------------------------------------
2832
; Display the byte in r1
2833
;------------------------------------------------------------------------------
2834
;
2835
DisplayByte:
2836
        pha
2837 18 robfinch
        lsr             r1,r1,#4
2838 11 robfinch
        jsr             DisplayNybble
2839
        pla
2840
        jmp             DisplayNybble   ; tail rts
2841 15 robfinch
message "785"
2842
;------------------------------------------------------------------------------
2843
; Display the half-word in r1
2844
;------------------------------------------------------------------------------
2845
;
2846
DisplayHalf:
2847
        pha
2848 18 robfinch
        lsr             r1,r1,#8
2849 15 robfinch
        jsr             DisplayByte
2850
        pla
2851
        jsr             DisplayByte
2852
        rts
2853 11 robfinch
 
2854 15 robfinch
message "797"
2855 11 robfinch
;------------------------------------------------------------------------------
2856 15 robfinch
; Display the half-word in r1
2857 11 robfinch
;------------------------------------------------------------------------------
2858 15 robfinch
;
2859
DisplayWord:
2860
        pha
2861 18 robfinch
        lsr             r1,r1,#16
2862 15 robfinch
        jsr             DisplayHalf
2863
        pla
2864
        jsr             DisplayHalf
2865
        rts
2866
message "810"
2867
;------------------------------------------------------------------------------
2868
; Display memory pointed to by r2.
2869
; destroys r1,r3
2870
;------------------------------------------------------------------------------
2871
;
2872
DisplayMemW:
2873
        pha
2874
        lda             #':'
2875
        jsr             DisplayChar
2876
        txa
2877
        jsr             DisplayWord
2878
        lda             #' '
2879
        jsr             DisplayChar
2880
        lda             (x)
2881
        jsr             DisplayWord
2882
        inx
2883
        lda             #' '
2884
        jsr             DisplayChar
2885
        lda             (x)
2886
        jsr             DisplayWord
2887
        inx
2888
        lda             #' '
2889
        jsr             DisplayChar
2890
        lda             (x)
2891
        jsr             DisplayWord
2892
        inx
2893
        lda             #' '
2894
        jsr             DisplayChar
2895
        lda             (x)
2896
        jsr             DisplayWord
2897
        inx
2898
        jsr             CRLF
2899
        pla
2900
        rts
2901 26 robfinch
 
2902
message "Monitor"
2903 15 robfinch
;==============================================================================
2904
; System Monitor Program
2905 26 robfinch
; The system monitor is task#0
2906 15 robfinch
;==============================================================================
2907
;
2908
Monitor:
2909 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer
2910 15 robfinch
        txs
2911 28 robfinch
        lda             #0                                      ; turn off keyboard echo
2912
        jsr             SetKeyboardEcho
2913
        jsr             RequestIOFocus
2914 15 robfinch
PromptLn:
2915
        jsr             CRLF
2916
        lda             #'$'
2917
        jsr             DisplayChar
2918
 
2919
; Get characters until a CR is keyed
2920
;
2921
Prompt3:
2922 28 robfinch
        jsr             RequestIOFocus
2923 15 robfinch
;       lw              r1,#2                   ; get keyboard character
2924
;       syscall #417
2925 26 robfinch
;       jsr             KeybdCheckForKeyDirect
2926
;       cmp             #0
2927
        jsr             KeybdGetChar
2928
        cmp             #-1
2929 15 robfinch
        beq             Prompt3
2930 26 robfinch
;       jsr             KeybdGetCharDirect
2931 15 robfinch
        cmp             #CR
2932
        beq             Prompt1
2933
        jsr             DisplayChar
2934
        bra             Prompt3
2935
 
2936
; Process the screen line that the CR was keyed on
2937
;
2938
Prompt1:
2939 26 robfinch
        ldx             RunningTCB
2940
        stz             TCB_CursorCol,x ; go back to the start of the line
2941 15 robfinch
        jsr             CalcScreenLoc   ; r1 = screen memory location
2942
        tay
2943
        lda             (y)
2944
        iny
2945
        jsr             ScreenToAscii
2946
        cmp             #'$'
2947
        bne             Prompt2                 ; skip over '$' prompt character
2948
        lda             (y)
2949
        iny
2950
        jsr             ScreenToAscii
2951
 
2952
; Dispatch based on command character
2953
;
2954
Prompt2:
2955
        cmp             #':'
2956
        beq             EditMem
2957
        cmp             #'D'
2958 18 robfinch
        bne             Prompt8
2959
        lda             (y)
2960
        iny
2961
        jsr             ScreenToAscii
2962
        cmp             #'R'
2963
        beq             DumpReg
2964
        dey
2965
        bra             DumpMem
2966
Prompt8:
2967 15 robfinch
        cmp             #'F'
2968 28 robfinch
        bne             Prompt7
2969
        lda             (y)
2970
        iny
2971
        jsr             ScreenToAscii
2972
        cmp             #'L'
2973
        bne             Prompt8a
2974
        jsr             DumpIOFocusList
2975
        jmp             Monitor
2976
Prompt8a:
2977
        dey
2978
        bra             FillMem
2979 15 robfinch
Prompt7:
2980
        cmp             #'B'                    ; $B - start tiny basic
2981
        bne             Prompt4
2982 26 robfinch
        lda             #3
2983
        ldy             #CSTART
2984
        ldx             #0
2985
        jsr             StartTask
2986
;       jsr             CSTART
2987 15 robfinch
        bra             Monitor
2988
Prompt4:
2989
        cmp             #'b'
2990
        bne             Prompt5
2991 26 robfinch
        lda             #3                              ; priority level 3
2992
        ldy             #$C000                  ; start address $C000
2993
        ldx             #$20000000              ; flags: emmulation mode set
2994
        jsr             StartTask
2995
        bra             Monitor
2996 15 robfinch
        emm
2997
        cpu             W65C02
2998
        jml             $0C000
2999
        cpu             rtf65002
3000
Prompt5:
3001
        cmp             #'J'                    ; $J - execute code
3002
        beq             ExecuteCode
3003 26 robfinch
        cmp             #'L'                    ; $L - load dector
3004
        beq             LoadSector
3005
        cmp             #'W'
3006
        beq             WriteSector
3007 15 robfinch
Prompt9:
3008
        cmp             #'?'                    ; $? - display help
3009
        bne             Prompt10
3010
        lda             #HelpMsg
3011
        jsr             DisplayStringB
3012
        jmp             Monitor
3013
Prompt10:
3014
        cmp             #'C'                    ; $C - clear screen
3015
        beq             TestCLS
3016 26 robfinch
        cmp             #'r'
3017 15 robfinch
        bne             Prompt12
3018 26 robfinch
        lda             #4                              ; priority level 4
3019
        ldx             #0                              ; zero all flags at startup
3020
        ldy             #RandomLines    ; task address
3021
        jsr             (y)
3022
;       jsr             StartTask
3023
        jmp             Monitor
3024
;       jmp             RandomLinesCall
3025 15 robfinch
Prompt12:
3026
Prompt13:
3027
        cmp             #'P'
3028
        bne             Prompt14
3029
        jmp             Piano
3030
Prompt14:
3031
        cmp             #'T'
3032
        bne             Prompt15
3033 26 robfinch
        jsr             DumpTaskList
3034
        jmp             Monitor
3035 15 robfinch
Prompt15:
3036
        cmp             #'S'
3037
        bne             Prompt16
3038 28 robfinch
        lda             (y)
3039
        iny
3040
        jsr             ScreenToAscii
3041
        cmp             #'P'
3042
        bne             Prompt18
3043
        jsr             ignBlanks
3044
        jsr             GetHexNumber
3045
        sta             SPSave
3046
        jmp             Monitor
3047
Prompt18:
3048
        dey
3049 15 robfinch
        jsr             spi_init
3050
        cmp             #0
3051
        bne             Monitor
3052
        jsr             spi_read_part
3053
        cmp             #0
3054
        bne             Monitor
3055
        jsr             spi_read_boot
3056
        cmp             #0
3057
        bne             Monitor
3058
        jsr             loadBootFile
3059
        jmp             Monitor
3060
Prompt16:
3061 26 robfinch
        cmp             #'e'
3062
        bne             Prompt17
3063
        jsr             eth_main
3064
Prompt17:
3065
        cmp             #'R'
3066
        bne             Monitor
3067
        lda             (y)
3068
        iny
3069
        jsr             ScreenToAscii
3070
        cmp             #'S'
3071 28 robfinch
        beq             LoadSector
3072 26 robfinch
        dey
3073
        bra             SetRegValue
3074 15 robfinch
        jmp             Monitor
3075
message "Prompt16"
3076
RandomLinesCall:
3077 26 robfinch
;       jsr             RandomLines
3078 15 robfinch
        jmp             Monitor
3079
 
3080
TestCLS:
3081
        lda             (y)
3082
        iny
3083
        jsr             ScreenToAscii
3084
        cmp             #'L'
3085
        bne             Monitor
3086
        lda             (y)
3087
        iny
3088
        jsr             ScreenToAscii
3089
        cmp             #'S'
3090
        bne             Monitor
3091
        jsr     ClearScreen
3092 26 robfinch
        ldx             RunningTCB
3093
        stz             TCB_CursorCol,x
3094
        stz             TCB_CursorRow,x
3095 15 robfinch
        jsr             CalcScreenLoc
3096
        jmp             Monitor
3097 26 robfinch
message "HelpMsg"
3098 15 robfinch
HelpMsg:
3099
        db      "? = Display help",CR,LF
3100
        db      "CLS = clear screen",CR,LF
3101
        db      "S = Boot from SD Card",CR,LF
3102
        db      ": = Edit memory bytes",CR,LF
3103 26 robfinch
        db      "L = Load sector",CR,LF
3104
        db      "W = Write sector",CR,LF
3105 18 robfinch
        db  "DR = Dump registers",CR,LF
3106 15 robfinch
        db      "D = Dump memory",CR,LF
3107
        db      "F = Fill memory",CR,LF
3108 28 robfinch
        db  "FL = Dump I/O Focus List",CR,LF
3109 15 robfinch
        db      "B = start tiny basic",CR,LF
3110
        db      "b = start EhBasic 6502",CR,LF
3111
        db      "J = Jump to code",CR,LF
3112 18 robfinch
        db      "R[n] = Set register value",CR,LF
3113 26 robfinch
        db      "r = random lines - test bitmap",CR,LF
3114
        db      "e = ethernet test",CR,LF
3115
        db      "T = Dump task list",CR,LF
3116 15 robfinch
        db      "P = Piano",CR,LF,0
3117
 
3118
;------------------------------------------------------------------------------
3119
; Ignore blanks in the input
3120
; r3 = text pointer
3121
; r1 destroyed
3122
;------------------------------------------------------------------------------
3123
;
3124
ignBlanks:
3125
ignBlanks1:
3126
        lda             (y)
3127
        iny
3128
        jsr             ScreenToAscii
3129
        cmp             #' '
3130
        beq             ignBlanks1
3131
        dey
3132
        rts
3133
 
3134
;------------------------------------------------------------------------------
3135
; Edit memory byte(s).
3136
;------------------------------------------------------------------------------
3137
;
3138
EditMem:
3139
        jsr             ignBlanks
3140
        jsr             GetHexNumber
3141
        or              r5,r1,r0
3142
        ld              r4,#3
3143
edtmem1:
3144
        jsr             ignBlanks
3145
        jsr             GetHexNumber
3146
        sta             (r5)
3147
        add             r5,r5,#1
3148
        dec             r4
3149
        bne             edtmem1
3150
        jmp             Monitor
3151
 
3152
;------------------------------------------------------------------------------
3153
; Execute code at the specified address.
3154
;------------------------------------------------------------------------------
3155
;
3156 26 robfinch
message "ExecuteCode"
3157 15 robfinch
ExecuteCode:
3158
        jsr             ignBlanks
3159
        jsr             GetHexNumber
3160 18 robfinch
        st              r1,JMPTMP
3161
        lda             #xcret                  ; push return address so we can do an indirect jump
3162
        pha
3163
        ld              r1,R1Save
3164
        ld              r2,R2Save
3165
        ld              r3,R3Save
3166
        ld              r4,R4Save
3167
        ld              r5,R5Save
3168
        ld              r6,R6Save
3169
        ld              r7,R7Save
3170
        ld              r8,R8Save
3171
        ld              r9,R9Save
3172
        ld              r10,R10Save
3173
        ld              r11,R11Save
3174
        ld              r12,R12Save
3175
        ld              r13,R13Save
3176
        ld              r14,R14Save
3177
        ld              r15,R15Save
3178
        jmp             (JMPTMP)
3179
xcret:
3180
        php
3181
        st              r1,R1Save
3182
        st              r2,R2Save
3183
        st              r3,R3Save
3184
        st              r4,R4Save
3185
        st              r5,R5Save
3186
        st              r6,R6Save
3187
        st              r7,R7Save
3188
        st              r8,R8Save
3189
        st              r9,R9Save
3190
        st              r10,R10Save
3191
        st              r11,R11Save
3192
        st              r12,R12Save
3193
        st              r13,R13Save
3194
        st              r14,R14Save
3195
        st              r15,R15Save
3196
        tsr             sp,r1
3197 28 robfinch
        st              r1,SPSave
3198 18 robfinch
        tsr             sp8,r1
3199 28 robfinch
        st              r1,SP8Save
3200 18 robfinch
        pla
3201
        sta             SRSave
3202 15 robfinch
        jmp     Monitor
3203
 
3204
LoadSector:
3205
        jsr             ignBlanks
3206 26 robfinch
        jsr             GetDecNumber
3207
        pha
3208
        jsr             ignBlanks
3209 15 robfinch
        jsr             GetHexNumber
3210 26 robfinch
        tax
3211
        phx
3212
;       ld              r2,#0x3800
3213
        jsr             spi_init
3214
        plx
3215
        pla
3216 15 robfinch
        jsr             spi_read_sector
3217
        jmp             Monitor
3218
 
3219 26 robfinch
WriteSector:
3220
        jsr             ignBlanks
3221
        jsr             GetDecNumber
3222
        pha
3223
        jsr             ignBlanks
3224
        jsr             GetHexNumber
3225
        tax
3226
        phx
3227
        jsr             spi_init
3228
        plx
3229
        pla
3230
        jsr             spi_write_sector
3231
        jmp             Monitor
3232
 
3233 15 robfinch
;------------------------------------------------------------------------------
3234 18 robfinch
; Dump the register set.
3235
;------------------------------------------------------------------------------
3236 26 robfinch
message "DumpReg"
3237 18 robfinch
DumpReg:
3238
        ldy             #0
3239
DumpReg1:
3240
        jsr             CRLF
3241
        lda             #':'
3242
        jsr             DisplayChar
3243
        lda             #'R'
3244
        jsr             DisplayChar
3245 26 robfinch
        ldx             #1
3246 18 robfinch
        tya
3247 26 robfinch
        ina
3248 18 robfinch
        jsr             PRTNUM
3249
        lda             #' '
3250
        jsr             DisplayChar
3251
        lda             R1Save,y
3252
        jsr             DisplayWord
3253
        iny
3254
        cpy             #15
3255
        bne             DumpReg1
3256
        jsr             CRLF
3257
        lda             #':'
3258
        jsr             DisplayChar
3259
        lda             #'S'
3260
        jsr             DisplayChar
3261
        lda             #'P'
3262
        jsr             DisplayChar
3263
        lda             #' '
3264
        jsr             DisplayChar
3265 26 robfinch
        lda             TCB_SPSave
3266 18 robfinch
        jsr             DisplayWord
3267
        jsr             CRLF
3268 26 robfinch
        jmp             Monitor
3269
;------------------------------------------------------------------------------
3270
;------------------------------------------------------------------------------
3271
SetRegValue:
3272
        jsr             GetDecNumber
3273
        cmp             #15
3274
        bpl             Monitor
3275
        pha
3276
        jsr             ignBlanks
3277
        jsr             GetHexNumber
3278
        ply
3279
        sta             R1Save,y
3280
        jmp             Monitor
3281 18 robfinch
 
3282
;------------------------------------------------------------------------------
3283 15 robfinch
; Do a memory dump of the requested location.
3284
;------------------------------------------------------------------------------
3285
;
3286
DumpMem:
3287
        jsr             ignBlanks
3288
        jsr             GetHexNumber    ; get start address of dump
3289
        tax
3290
        jsr             ignBlanks
3291
        jsr             GetHexNumber    ; get number of words to dump
3292
        lsr                                             ; 1/4 as many dump rows
3293
        lsr
3294
        bne             Dumpmem2
3295
        lda             #1                              ; dump at least one row
3296
Dumpmem2:
3297
        jsr             CRLF
3298
        bra             DumpmemW
3299
DumpmemW:
3300
        jsr             DisplayMemW
3301
        dea
3302
        bne             DumpmemW
3303
        jmp             Monitor
3304
 
3305
 
3306
        bra             Monitor
3307 26 robfinch
message "FillMem"
3308 15 robfinch
FillMem:
3309
        jsr             ignBlanks
3310
        jsr             GetHexNumber    ; get start address of dump
3311
        tax
3312
        jsr             ignBlanks
3313
        jsr             GetHexNumber    ; get number of bytes to fill
3314 26 robfinch
        ld              r5,r1
3315 15 robfinch
        jsr             ignBlanks
3316
        jsr             GetHexNumber    ; get the fill byte
3317
FillmemW:
3318
        sta             (x)
3319
        inx
3320
        dec             r5
3321
        bne             FillmemW
3322
        jmp             Monitor
3323
 
3324
;------------------------------------------------------------------------------
3325
; Get a hexidecimal number. Maximum of eight digits.
3326
; R3 = text pointer (updated)
3327
; R1 = hex number
3328
;------------------------------------------------------------------------------
3329
;
3330
GetHexNumber:
3331
        phx
3332
        push    r4
3333
        ldx             #0
3334
        ld              r4,#8
3335
gthxn2:
3336
        lda             (y)
3337
        iny
3338
        jsr             ScreenToAscii
3339
        jsr             AsciiToHexNybble
3340
        cmp             #-1
3341
        beq             gthxn1
3342 18 robfinch
        asl             r2,r2,#4
3343 15 robfinch
        and             #$0f
3344
        or              r2,r2,r1
3345
        dec             r4
3346
        bne             gthxn2
3347
gthxn1:
3348
        txa
3349
        pop             r4
3350
        plx
3351
        rts
3352
 
3353 26 robfinch
GetDecNumber:
3354
        phx
3355
        push    r4
3356
        push    r5
3357
        ldx             #0
3358
        ld              r4,#10
3359
        ld              r5,#10
3360
gtdcn2:
3361
        lda             (y)
3362
        iny
3363
        jsr             ScreenToAscii
3364
        jsr             AsciiToDecNybble
3365
        cmp             #-1
3366
        beq             gtdcn1
3367
        mul             r2,r2,r5
3368
        add             r2,r2,r1
3369
        dec             r4
3370
        bne             gtdcn2
3371
gtdcn1:
3372
        txa
3373
        pop             r5
3374
        pop             r4
3375
        plx
3376
        rts
3377
 
3378 15 robfinch
;------------------------------------------------------------------------------
3379
; Convert ASCII character in the range '0' to '9', 'a' to 'f' or 'A' to 'F'
3380
; to a hex nybble.
3381
;------------------------------------------------------------------------------
3382
;
3383
AsciiToHexNybble:
3384
        cmp             #'0'
3385
        bcc             gthx3
3386
        cmp             #'9'+1
3387
        bcs             gthx5
3388
        sub             #'0'
3389
        rts
3390
gthx5:
3391
        cmp             #'A'
3392
        bcc             gthx3
3393
        cmp             #'F'+1
3394
        bcs             gthx6
3395
        sub             #'A'
3396
        add             #10
3397
        rts
3398
gthx6:
3399
        cmp             #'a'
3400
        bcc             gthx3
3401
        cmp             #'z'+1
3402
        bcs             gthx3
3403
        sub             #'a'
3404
        add             #10
3405
        rts
3406
gthx3:
3407
        lda             #-1             ; not a hex number
3408
        rts
3409
 
3410 26 robfinch
AsciiToDecNybble:
3411
        cmp             #'0'
3412
        bcc             gtdc3
3413
        cmp             #'9'+1
3414
        bcs             gtdc3
3415
        sub             #'0'
3416
        rts
3417
gtdc3:
3418
        lda             #-1
3419
        rts
3420
 
3421
 
3422 15 robfinch
;------------------------------------------------------------------------------
3423
;------------------------------------------------------------------------------
3424 11 robfinch
ClearBmpScreen:
3425
        pha
3426
        phx
3427
        phy
3428
        ldx             #(1364*768)>>2          ; x = # words to clear
3429
        lda             #0x29292929                     ; acc = color for four pixels
3430
        ldy             #BITMAPSCR                      ; y = screen address
3431 15 robfinch
cbsj4
3432 11 robfinch
        sta             (y)                                     ; store pixel data
3433
        iny                                                     ; advance screen address
3434
        dex                                                     ; decrement pixel count and loop back
3435 15 robfinch
        bne             cbsj4
3436 11 robfinch
        ply
3437
        plx
3438
        pla
3439
        rts
3440
 
3441
;==============================================================================
3442
;==============================================================================
3443 28 robfinch
;--------------------------------------------------------------------------
3444
; Setup the AC97/LM4550 audio controller. Check keyboard for a CTRL-C
3445
; interrupt which may be necessary if the audio controller isn't
3446
; responding.
3447
;--------------------------------------------------------------------------
3448 11 robfinch
;
3449 28 robfinch
SetupAC97:
3450
        pha
3451
        phx
3452
        phy
3453
        push    r4
3454
        ld              r4,Milliseconds
3455
sac974:
3456
        stz             AC97+0x26               ; trigger a read of register 26 (status reg)
3457
sac971:                                         ; wait for status to register 0xF (all ready)
3458
        ld              r3,Milliseconds
3459
        sub             r3,r3,r4
3460
        cmp             r3,#1000
3461
        bpl             sac97Abort
3462
        jsr             KeybdGetChar    ; see if we needed to CTRL-C
3463
        cmp             #CTRLC
3464
        beq             sac973
3465
        lda             AC97+0x68               ; wait for dirty bit to clear
3466
        bne             sac971
3467
        lda             AC97+0x26               ; check status at reg h26, wait for
3468
        and             #0x0F                   ; analogue to be ready
3469
        cmp             #$0F
3470
        bne             sac974
3471
sac973:
3472
        stz             AC97+2                  ; master volume, 0db attenuation, mute off
3473
        stz             AC97+4                  ; headphone volume, 0db attenuation, mute off
3474
        stz             AC97+0x18               ; PCM gain (mixer) mute off, no attenuation
3475
        stz             AC97+0x0A               ; mute PC beep
3476
        lda             #0x8000                 ; bypass 3D sound
3477
        sta             AC97+0x20
3478
        ld              r4,Milliseconds
3479
sac972:
3480
        ld              r3,Milliseconds
3481
        sub             r3,r3,r4
3482
        cmp             r3,#1000
3483
        bpl             sac97Abort
3484
        jsr             KeybdGetChar
3485
        cmp             #CTRLC
3486
        beq             sac975
3487
        lda             AC97+0x68               ; wait for dirty bits to clear
3488
        bne             sac972                  ; wait a while for the settings to take effect
3489
sac975:
3490
        pop             r4
3491
        ply
3492
        plx
3493
        pla
3494
        rts
3495
sac97Abort:
3496
        lda             #msgAC97bad
3497
        jsr             DisplayStringCRLFB
3498
        pop             r4
3499
        ply
3500
        plx
3501
        pla
3502
        rts
3503
 
3504
msgAC97bad:
3505
        db      "The AC97 controller is not responding.",CR,LF,0
3506
 
3507
;--------------------------------------------------------------------------
3508
; Sound a 800 Hz beep
3509
;--------------------------------------------------------------------------
3510
;
3511
Beep:
3512
        pha
3513
        lda             #15                             ; master volume to max
3514
        sta             PSG+128
3515
        lda             #13422                  ; 800Hz
3516
        sta             PSGFREQ0
3517
        ; decay  (16.384 ms)2
3518
        ; attack (8.192 ms)1
3519
        ; release (1.024 s)A
3520
        ; sustain level C
3521
        lda             #0xCA12
3522
        sta             PSGADSR0
3523
        lda             #0x1104                 ; gate, output enable, triangle waveform
3524
        sta             PSGCTRL0
3525
        lda             #2500000                ; delay about 1s
3526
beep1:
3527
        dea
3528
        bne             beep1
3529
        lda             #0x0104                 ; gate off, output enable, triangle waveform
3530
        sta             PSGCTRL0
3531
        lda             #2500000                ; delay about 1s
3532
beep2:
3533
        dea
3534
        bne             beep2
3535
        lda             #0x0000                 ; gate off, output enable off, no waveform
3536
        sta             PSGCTRL0
3537
        pla
3538
        rts
3539
 
3540
;--------------------------------------------------------------------------
3541
;--------------------------------------------------------------------------
3542
;
3543
Piano:
3544
        lda             #15                             ; master volume to max
3545
        sta             PSG+128
3546
playnt:
3547
        jsr             KeybdGetChar
3548
        cmp             #CTRLC
3549
        beq             Monitor
3550
        cmp             #'a'
3551
        beq             playnt1a
3552
        cmp             #'b'
3553
        beq             playnt1b
3554
        cmp             #'c'
3555
        beq             playnt1c
3556
        cmp             #'d'
3557
        beq             playnt1d
3558
        cmp             #'e'
3559
        beq             playnt1e
3560
        cmp             #'f'
3561
        beq             playnt1f
3562
        cmp             #'g'
3563
        beq             playnt1g
3564
        bra             playnt
3565
 
3566
playnt1a:
3567
        lda             #7217
3568
        jsr             Tone
3569
        bra             playnt
3570
playnt1b:
3571
        lda             #8101
3572
        jsr             Tone
3573
        bra             playnt
3574
playnt1c:
3575
        lda             #4291
3576
        jsr             Tone
3577
        bra             playnt
3578
playnt1d:
3579
        lda             #4817
3580
        jsr             Tone
3581
        bra             playnt
3582
playnt1e:
3583
        lda             #5407
3584
        jsr             Tone
3585
        bra             playnt
3586
playnt1f:
3587
        lda             #5728
3588
        jsr             Tone
3589
        bra             playnt
3590
playnt1g:
3591
        lda             #6430
3592
        jsr             Tone
3593
        bra             playnt
3594
 
3595
Tone:
3596
        pha
3597
        sta             PSGFREQ0
3598
        ; decay  (16.384 ms)2
3599
        ; attack (8.192 ms)1
3600
        ; release (1.024 s)A
3601
        ; sustain level C
3602
        lda             #0xCA12
3603
        sta             PSGADSR0
3604
        lda             #0x1104                 ; gate, output enable, triangle waveform
3605
        sta             PSGCTRL0
3606
        lda             #1                              ; delay about 10ms
3607
        jsr             Sleep
3608
        lda             #0x0104                 ; gate off, output enable, triangle waveform
3609
        sta             PSGCTRL0
3610
        lda             #1                              ; delay about 10ms
3611
        jsr             Sleep
3612
        lda             #0x0000                 ; gate off, output enable off, no waveform
3613
        sta             PSGCTRL0
3614
        pla
3615
        rts
3616
 
3617
;==============================================================================
3618
;==============================================================================
3619
;
3620 11 robfinch
; Initialize the SD card
3621
; Returns
3622
; acc = 0 if successful, 1 otherwise
3623 26 robfinch
; Z=1 if successful, otherwise Z=0
3624 11 robfinch
;
3625 26 robfinch
message "spi_init"
3626 11 robfinch
spi_init
3627
        lda             #SPI_INIT_SD
3628
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
3629
        lda             #SPI_TRANS_START
3630
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
3631
        nop
3632
spi_init1
3633
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
3634
        nop
3635
        nop
3636
        cmp             #SPI_TRANS_BUSY
3637
        beq             spi_init1
3638
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
3639
        and             #3
3640
        cmp             #SPI_INIT_NO_ERROR
3641
        bne             spi_error
3642 15 robfinch
        lda             #spi_init_ok_msg
3643 11 robfinch
        jsr             DisplayStringB
3644
        lda             #0
3645 26 robfinch
        rts
3646 11 robfinch
spi_error
3647
        jsr             DisplayByte
3648 15 robfinch
        lda             #spi_init_error_msg
3649 11 robfinch
        jsr             DisplayStringB
3650
        lda             SPIMASTER+SPI_RESP_BYTE1
3651
        jsr             DisplayByte
3652
        lda             SPIMASTER+SPI_RESP_BYTE2
3653
        jsr             DisplayByte
3654
        lda             SPIMASTER+SPI_RESP_BYTE3
3655
        jsr             DisplayByte
3656
        lda             SPIMASTER+SPI_RESP_BYTE4
3657
        jsr             DisplayByte
3658
        lda             #1
3659
        rts
3660
 
3661 26 robfinch
spi_delay:
3662
        nop
3663
        nop
3664
        rts
3665 11 robfinch
 
3666
 
3667
; SPI read sector
3668
;
3669
; r1= sector number to read
3670
; r2= address to place read data
3671
; Returns:
3672
; r1 = 0 if successful
3673
;
3674
spi_read_sector:
3675
        phx
3676
        phy
3677
        push    r4
3678
 
3679
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
3680 18 robfinch
        lsr             r1,r1,#8
3681 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
3682 18 robfinch
        lsr             r1,r1,#8
3683 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
3684 18 robfinch
        lsr             r1,r1,#8
3685 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
3686
 
3687
        ld              r4,#20  ; retry count
3688
 
3689
spi_read_retry:
3690
        ; Force the reciever fifo to be empty, in case a prior error leaves it
3691
        ; in an unknown state.
3692
        lda             #1
3693
        sta             SPIMASTER+SPI_RX_FIFO_CTRL_REG
3694
 
3695
        lda             #RW_READ_SD_BLOCK
3696
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
3697
        lda             #SPI_TRANS_START
3698
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
3699
        nop
3700
spi_read_sect1:
3701
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
3702 26 robfinch
        jsr             spi_delay                       ; just a delay between consecutive status reg reads
3703 11 robfinch
        cmp             #SPI_TRANS_BUSY
3704
        beq             spi_read_sect1
3705
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
3706
        lsr
3707
        lsr
3708
        and             #3
3709
        cmp             #SPI_READ_NO_ERROR
3710
        bne             spi_read_error
3711
        ldy             #512            ; read 512 bytes from fifo
3712
spi_read_sect2:
3713
        lda             SPIMASTER+SPI_RX_FIFO_DATA_REG
3714 15 robfinch
        sb              r1,0,x
3715 11 robfinch
        inx
3716
        dey
3717
        bne             spi_read_sect2
3718
        lda             #0
3719
        bra             spi_read_ret
3720
spi_read_error:
3721 15 robfinch
        dec             r4
3722 11 robfinch
        bne             spi_read_retry
3723
        jsr             DisplayByte
3724 15 robfinch
        lda             #spi_read_error_msg
3725 11 robfinch
        jsr             DisplayStringB
3726
        lda             #1
3727
spi_read_ret:
3728
        pop             r4
3729
        ply
3730
        plx
3731
        rts
3732
 
3733
; SPI write sector
3734
;
3735
; r1= sector number to write
3736
; r2= address to get data from
3737
; Returns:
3738
; r1 = 0 if successful
3739
;
3740
spi_write_sector:
3741
        phx
3742
        phy
3743
        pha
3744
        ; Force the transmitter fifo to be empty, in case a prior error leaves it
3745
        ; in an unknown state.
3746
        lda             #1
3747
        sta             SPIMASTER+SPI_TX_FIFO_CTRL_REG
3748
        nop                     ; give I/O time to respond
3749
        nop
3750
 
3751
        ; now fill up the transmitter fifo
3752
        ldy             #512
3753
spi_write_sect1:
3754 15 robfinch
        lb              r1,0,x
3755 11 robfinch
        sta             SPIMASTER+SPI_TX_FIFO_DATA_REG
3756
        nop                     ; give the I/O time to respond
3757
        nop
3758
        inx
3759
        dey
3760
        bne             spi_write_sect1
3761
 
3762
        ; set the sector number in the spi master address registers
3763
        pla
3764
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
3765 18 robfinch
        lsr             r1,r1,#8
3766 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
3767 18 robfinch
        lsr             r1,r1,#8
3768 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
3769 18 robfinch
        lsr             r1,r1,#8
3770 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
3771
 
3772
        ; issue the write command
3773
        lda             #RW_WRITE_SD_BLOCK
3774
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
3775
        lda             #SPI_TRANS_START
3776
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
3777
        nop
3778
spi_write_sect2:
3779
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
3780
        nop                                                     ; just a delay between consecutive status reg reads
3781
        nop
3782
        cmp             #SPI_TRANS_BUSY
3783
        beq             spi_write_sect2
3784
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
3785 18 robfinch
        lsr             r1,r1,#4
3786 11 robfinch
        and             #3
3787
        cmp             #SPI_WRITE_NO_ERROR
3788
        bne             spi_write_error
3789
        lda             #0
3790
        bra             spi_write_ret
3791
spi_write_error:
3792
        jsr             DisplayByte
3793 15 robfinch
        lda             #spi_write_error_msg
3794 11 robfinch
        jsr             DisplayStringB
3795
        lda             #1
3796
 
3797
spi_write_ret:
3798
        ply
3799
        plx
3800
        rts
3801
 
3802 28 robfinch
; SPI write multiple sector
3803
;
3804
; r1= sector number to write
3805
; r2= address to get data from
3806
; r3= number of sectors to write
3807
;
3808
; Returns:
3809
; r1 = 0 if successful
3810
;
3811
spi_write_multiple:
3812
        push    r4
3813
spi_wm1:
3814
        pha
3815
        jsr             spi_write_sector
3816
        add             r4,r4,r1                ; accumulate an error count
3817
        add             r2,r2,#512              ; 512 bytes per sector
3818
        pla
3819
        ina
3820
        dey
3821
        bne             spi_wm1
3822
        ld              r1,r4
3823
        pop             r4
3824
        rts
3825
 
3826 15 robfinch
; read the partition table to find out where the boot sector is.
3827 26 robfinch
; Returns
3828
; r1 = 0 everything okay, 1=read error
3829
; also Z=1=everything okay, Z=0=read error
3830 15 robfinch
;
3831
spi_read_part:
3832
        phx
3833
        stz             startSector                                             ; default starting sector
3834
        lda             #0                                                              ; r1 = sector number (#0)
3835 26 robfinch
        ldx             #BYTE_SECTOR_BUF                                ; r2 = target address (word to byte address)
3836 15 robfinch
        jsr             spi_read_sector
3837 18 robfinch
        cmp             #0
3838
        bne             spi_rp1
3839 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1C9
3840 18 robfinch
        asl             r1,r1,#8
3841 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C8
3842 18 robfinch
        asl             r1,r1,#8
3843 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C7
3844 18 robfinch
        asl             r1,r1,#8
3845 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C6
3846
        sta             startSector                                             ; r1 = 0, for okay status
3847 18 robfinch
        plx
3848 15 robfinch
        lda             #0
3849 18 robfinch
        rts
3850
spi_rp1:
3851 15 robfinch
        plx
3852 18 robfinch
        lda             #1
3853 15 robfinch
        rts
3854
 
3855
; Read the boot sector from the disk.
3856
; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.
3857 26 robfinch
; Returns:
3858
; r1 = 0 means this card is bootable
3859
; r1 = 1 means a read error occurred
3860
; r1 = 2 means the card is not bootable
3861 15 robfinch
;
3862
spi_read_boot:
3863
        phx
3864
        phy
3865
        push    r5
3866
        lda             startSector                                     ; r1 = sector number
3867
        ldx             #BYTE_SECTOR_BUF                        ; r2 = target address
3868
        jsr             spi_read_sector
3869 26 robfinch
        cmp             #0
3870
        bne             spi_read_boot_err
3871 15 robfinch
        lb              r1,BYTE_SECTOR_BUF
3872
        cmp             #$EB
3873 26 robfinch
        bne             spi_eb_err
3874 15 robfinch
spi_read_boot2:
3875
        lda             #msgFoundEB
3876
        jsr             DisplayStringB
3877
        lb              r1,BYTE_SECTOR_BUF+$1FE         ; check for 0x55AA signature
3878
        cmp             #$55
3879 26 robfinch
        bne             spi_eb_err
3880 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1FF         ; check for 0x55AA signature
3881
        cmp             #$AA
3882 26 robfinch
        bne             spi_eb_err
3883
        pop             r5
3884
        ply
3885
        plx
3886 15 robfinch
        lda             #0                                              ; r1 = 0, for okay status
3887 26 robfinch
        rts
3888
spi_read_boot_err:
3889 15 robfinch
        pop             r5
3890
        ply
3891
        plx
3892 26 robfinch
        lda             #1
3893 15 robfinch
        rts
3894 26 robfinch
spi_eb_err:
3895
        lda             #msgNotFoundEB
3896
        jsr             DisplayStringB
3897
        pop             r5
3898
        ply
3899
        plx
3900
        lda             #2
3901
        rts
3902 15 robfinch
 
3903
msgFoundEB:
3904
        db      "Found EB code.",CR,LF,0
3905 26 robfinch
msgNotFoundEB:
3906
        db      "EB/55AA Code missing.",CR,LF,0
3907 15 robfinch
 
3908
; Load the root directory from disk
3909
; r2 = where to place root directory in memory
3910
;
3911
loadBootFile:
3912
        lb              r1,BYTE_SECTOR_BUF+$17                  ; sectors per FAT
3913 18 robfinch
        asl             r1,r1,#8
3914 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$16
3915
        bne             loadBootFile7
3916
        lb              r1,BYTE_SECTOR_BUF+$27                  ; sectors per FAT, FAT32
3917 18 robfinch
        asl             r1,r1,#8
3918 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$26
3919 18 robfinch
        asl             r1,r1,#8
3920 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$25
3921 18 robfinch
        asl             r1,r1,#8
3922 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$24
3923
loadBootFile7:
3924
        lb              r4,BYTE_SECTOR_BUF+$10                  ; number of FATs
3925
        mul             r3,r1,r4                                                ; offset
3926
        lb              r1,BYTE_SECTOR_BUF+$F                   ; r1 = # reserved sectors before FAT
3927 18 robfinch
        asl             r1,r1,#8
3928 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$E
3929
        add             r3,r3,r1                                                ; r3 = root directory sector number
3930
        ld              r6,startSector
3931
        add             r5,r3,r6                                                ; r5 = root directory sector number
3932
        lb              r1,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
3933
        add             r3,r1,r5                                                ; r3 = first cluster after first cluster of directory
3934
        bra             loadBootFile6
3935
 
3936
loadBootFile6:
3937
        ; For now we cheat and just go directly to sector 512.
3938
        bra             loadBootFileTmp
3939
 
3940
loadBootFileTmp:
3941
        ; We load the number of sectors per cluster, then load a single cluster of the file.
3942
        ; This is 16kib
3943
        ld              r5,r3                                                   ; r5 = start sector of data area
3944
        ld              r2,#PROG_LOAD_AREA                              ; where to place file in memory
3945
        lb              r3,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
3946
loadBootFile1:
3947
        ld              r1,r5                                                   ; r1=sector to read
3948
        jsr             spi_read_sector
3949
        inc             r5                                              ; r5 = next sector
3950
        add             r2,r2,#512
3951
        dec             r3
3952
        bne             loadBootFile1
3953 26 robfinch
        lda             PROG_LOAD_AREA>>2               ; make sure it's bootable
3954 15 robfinch
        cmp             #$544F4F42
3955
        bne             loadBootFile2
3956
        lda             #msgJumpingToBoot
3957
        jsr             DisplayStringB
3958 26 robfinch
        lda             (PROG_LOAD_AREA>>2)+$1
3959 15 robfinch
        jsr             (r1)
3960
        jmp             Monitor
3961
loadBootFile2:
3962
        lda             #msgNotBootable
3963
        jsr             DisplayStringB
3964
        ldx             #PROG_LOAD_AREA>>2
3965
        jsr             DisplayMemW
3966
        jsr             DisplayMemW
3967
        jsr             DisplayMemW
3968
        jsr             DisplayMemW
3969
        jmp             Monitor
3970
 
3971 11 robfinch
msgJumpingToBoot:
3972
        db      "Jumping to boot",0
3973
msgNotBootable:
3974
        db      "SD card not bootable.",0
3975
spi_init_ok_msg:
3976
        db "SD card initialized okay.",0
3977
spi_init_error_msg:
3978
        db      ": error occurred initializing the SD card.",0
3979
spi_boot_error_msg:
3980 26 robfinch
        db      "SD card boot error",CR,LF,0
3981 11 robfinch
spi_read_error_msg:
3982 26 robfinch
        db      "SD card read error",CR,LF,0
3983 11 robfinch
spi_write_error_msg:
3984
        db      "SD card write error",0
3985
 
3986 26 robfinch
;==============================================================================
3987
; Ethernet
3988
;==============================================================================
3989
my_MAC1 EQU     0x00
3990
my_MAC2 EQU     0xFF
3991
my_MAC3 EQU     0xEE
3992
my_MAC4 EQU     0xF0
3993
my_MAC5 EQU     0xDA
3994
my_MAC6 EQU     0x42
3995
 
3996
; Initialize the ethmac controller.
3997
; Supply a MAC address, set MD clock
3998
;
3999
message "eth_init"
4000
eth_init:
4001
        pha
4002
        phy
4003
        ldy             #ETHMAC
4004
        lda             #0x64                           ; 100
4005
        sta             ETH_MIIMODER,y
4006
        lda             #7                                      ; PHY address
4007
        sta             ETH_MIIADDRESS,y
4008
        lda             #0xEEF0DA42
4009
        sta             ETH_MAC_ADDR0,y         ; MAC0
4010
        lda             #0x00FF
4011
        sta             ETH_MAC_ADDR1,y         ; MAC1
4012
        ply
4013
        pla
4014
        rts
4015
 
4016
; Request a packet and display on screen
4017
; r1 = address where to put packet
4018
;
4019
message "eth_request_packet"
4020
eth_request_packet:
4021
        phx
4022
        phy
4023
        push    r4
4024
        push    r5
4025
        ldy             #ETHMAC
4026
        ldx             #4                                      ; clear rx interrupt
4027
        stx             ETH_INT_SOURCE,y
4028
        sta             0x181,y                         ; storage address
4029
        ldx             #0xe000                         ; enable interrupt
4030
        stx             0x180,y
4031
eth1:
4032
        nop
4033
        ldx             ETH_INT_SOURCE,y
4034
        and             r2,r2,#4                        ; get bit #2
4035
        beq             eth1
4036
        ldx             0x180,y                         ; get from descriptor
4037
        lsr             r2,r2,#16
4038
        ldy             #0
4039
        ld              r4,#TEXTSCR+3780        ; second last line of screen
4040
eth20:
4041
        add             r5,r1,r3
4042
        ldx             (r5)                            ; get byte
4043
        add             r5,r4,r3
4044
        stx             (r5)                            ; store to screen
4045
        iny
4046
        cpy             #83
4047
        bne             eth20
4048
        pop             r5
4049
        pop             r4
4050
        ply
4051
        plx
4052
        rts
4053
 
4054
; r1 = packet address
4055
;
4056
message "eth_interpret_packet"
4057
eth_interpret_packet:
4058
        phx
4059
        phy
4060
        lb              r2,12,r1
4061
        lb              r3,13,r1
4062
        cpx             #8                                      ; 0x806 ?
4063
        bne             eth2
4064
        cpy             #6
4065
        bne             eth2
4066
        lda             #2                                      ; return r1 = 2 for ARP
4067
eth5:
4068
        ply
4069
        plx
4070
        rts
4071
eth2:
4072
        cpx             #8
4073
        bne             eth3                            ; 0x800 ?
4074
        cpy             #0
4075
        bne             eth3
4076
        lb              r2,23,r1
4077
        cpx             #1
4078
        bne             eth4
4079
        lda             #1
4080
        bra             eth5                            ; return 1 ICMP
4081
eth4:
4082
        cpx             #$11
4083
        bne             eth6
4084
        lda             #3                                      ; return 3 for UDP
4085
        bra             eth5
4086
eth6:
4087
        cpx             #6
4088
        bne             eth7
4089
        lda             #4                                      ; return 4 for TCP
4090
        bra             eth5
4091
eth7:
4092
eth3:
4093
        eor             r1,r1,r1                        ; return zero for unknown
4094
        ply
4095
        plx
4096
        rts
4097
 
4098
; r1 = address of packet to send
4099
; r2 = packet length
4100
;
4101
message "eth_send_packet"
4102
eth_send_packet:
4103
        phx
4104
        phy
4105
        push    r4
4106
        ldy             #ETHMAC
4107
        ; wait for tx buffer to be clear
4108
eth8:
4109
        ld              r4,0x100,y
4110
        and             r4,r4,#$8000
4111
        bne             eth8
4112
        ld              r4,#1                   ; clear tx interrupt
4113
        st              r4,ETH_INT_SOURCE,y
4114
        ; set address
4115
        sta             0x101,y
4116
        ; set the packet length field and enable interrupts
4117
        asl             r2,r2,#16
4118
        or              r2,r2,#0xF000
4119
        stx             0x100,y
4120
        pop             r4
4121
        ply
4122
        plx
4123
        rts
4124
 
4125
; Only for IP type packets (not ARP)
4126
; r1 = rx buffer address
4127
; r2 = swap flag
4128
; Returns:
4129
; r1 = data start index
4130
;
4131
message "eth_build_packet"
4132
eth_build_packet:
4133
        phy
4134
        push    r4
4135
        push    r5
4136
        push    r6
4137
        push    r7
4138
        push    r8
4139
        push    r9
4140
        push    r10
4141
 
4142
        lb              r3,6,r1
4143
        lb              r4,7,r1
4144
        lb              r5,8,r1
4145
        lb              r6,9,r1
4146
        lb              r7,10,r1
4147
        lb              r8,11,r1
4148
        ; write to destination header
4149
        sb              r3,0,r1
4150
        sb              r4,1,r1
4151
        sb              r5,2,r1
4152
        sb              r6,3,r1
4153
        sb              r7,4,r1
4154
        sb              r8,5,r1
4155
        ; write to source header
4156
        ld              r3,#my_MAC1
4157
        sb              r3,6,r1
4158
        ld              r3,#my_MAC2
4159
        sb              r3,7,r1
4160
        ld              r3,#my_MAC3
4161
        sb              r3,8,r1
4162
        ld              r3,#my_MAC4
4163
        sb              r3,9,r1
4164
        ld              r3,#my_MAC5
4165
        sb              r3,10,r1
4166
        ld              r3,#my_MAC6
4167
        sb              r3,11,r1
4168
        cmp             r2,#1
4169
        bne             eth16                   ; if (swap)
4170
        lb              r3,26,r1
4171
        lb              r4,27,r1
4172
        lb              r5,28,r1
4173
        lb              r6,29,r1
4174
        ; read destination
4175
        lb              r7,30,r1
4176
        lb              r8,31,r1
4177
        lb              r9,32,r1
4178
        lb              r10,33,r1
4179
        ; write to sender
4180
        sb              r7,26,r1
4181
        sb              r8,27,r1
4182
        sb              r9,28,r1
4183
        sb              r10,29,r1
4184
        ; write destination
4185
        sb              r3,30,r1
4186
        sb              r4,31,r1
4187
        sb              r5,32,r1
4188
        sb              r6,33,r1
4189
eth16:
4190
        ldy             eth_unique_id
4191
        iny
4192
        sty             eth_unique_id
4193
        sb              r3,19,r1
4194
        lsr             r3,r3,#8
4195
        sb              r3,18,r1
4196
        lb              r3,14,r1
4197
        and             r3,r3,#0xF
4198
        asl             r3,r3,#2                ; *4
4199
        add             r1,r3,#14               ; return datastart in r1
4200
        pop             r10
4201
        pop             r9
4202
        pop             r8
4203
        pop             r7
4204
        pop             r6
4205
        pop             r5
4206
        pop             r4
4207
        ply
4208
        rts
4209
 
4210
; Compute IPv4 checksum of header
4211
; r1 = packet address
4212
; r2 = data start
4213
;
4214
message "eth_checksum"
4215
eth_checksum:
4216
        phy
4217
        push    r4
4218
        push    r5
4219
        push    r6
4220
        ; set checksum to zero
4221
        stz             24,r1
4222
        stz             25,r1
4223
        eor             r3,r3,r3                ; r3 = sum = zero
4224
        ld              r4,#14
4225
eth15:
4226
        ld              r5,r2
4227
        dec             r5                              ; r5 = datastart - 1
4228
        cmp             r4,r5
4229
        bpl             eth14
4230
        add             r6,r1,r4
4231
        lb              r5,0,r6                 ; shi = [rx_addr+i]
4232
        lb              r6,1,r6             ; slo = [rx_addr+i+1]
4233
        asl     r5,r5,#8
4234
        or              r5,r5,r6                ; shilo
4235
        add             r3,r3,r5                ; sum = sum + shilo
4236
        add             r4,r4,#2                ; i = i + 2
4237
        bra             eth15
4238
eth14:
4239
        ld              r5,r3                   ; r5 = sum
4240
        and             r3,r3,#0xffff
4241
        lsr             r5,r5,#16
4242
        add             r3,r3,r5
4243
        eor             r3,r3,#-1
4244
        sb              r3,25,r1                ; low byte
4245
        lsr             r3,r3,#8
4246
        sb              r3,24,r1                ; high byte
4247
        pop             r6
4248
        pop             r5
4249
        pop             r4
4250
        ply
4251
        rts
4252
 
4253
; r1 = packet address
4254
; returns r1 = 1 if this IP
4255
;
4256
message "eth_verifyIP"
4257
eth_verifyIP:
4258
        phx
4259
        phy
4260
        push    r4
4261
        push    r5
4262
        lb              r2,30,r1
4263
        lb              r3,31,r1
4264
        lb              r4,32,r1
4265
        lb              r5,33,r1
4266
        ; Check for general broadcast
4267
        cmp             r2,#$FF
4268
        bne             eth11
4269
        cmp             r3,#$FF
4270
        bne             eth11
4271
        cmp             r4,#$FF
4272
        bne             eth11
4273
        cmp             r5,#$FF
4274
        bne             eth11
4275
eth12:
4276
        lda             #1
4277
eth13:
4278
        pop             r5
4279
        pop             r4
4280
        ply
4281
        plx
4282
        rts
4283
eth11:
4284
        ld              r1,r2
4285
        asl             r1,r1,#8
4286
        or              r1,r1,r3
4287
        asl             r1,r1,#8
4288
        or              r1,r1,r4
4289
        asl             r1,r1,#8
4290
        or              r1,r1,r5
4291
        cmp             #$C0A8012A              ; 192.168.1.42
4292
        beq             eth12
4293
        eor             r1,r1,r1
4294
        bra             eth13
4295
 
4296
message "eth_main"
4297
eth_main:
4298
        jsr             eth_init
4299
eth_loop:
4300
        jsr             KeybdGetChar
4301
        cmp             #-1
4302
        beq             eth17
4303
        cmp             #CTRLC
4304
        bne             eth17
4305
        rts
4306
eth17
4307
        lda             #eth_rx_buffer<<2               ; memory address zero
4308
        jsr             eth_request_packet
4309
        jsr             eth_interpret_packet    ; r1 = packet type
4310
 
4311
        cmp             #1
4312
        bne             eth10
4313
        ld              r2,r1                                   ; save off r1, r2 = packet type
4314
        lda             #eth_rx_buffer<<2               ; memory address zero
4315
        jsr             eth_verifyIP
4316
        tay
4317
        txa                                                             ; r1 = packet type again
4318
        cpy             #1
4319
        bne             eth10
4320
 
4321
        lda             #eth_rx_buffer<<2               ; memory address zero
4322
        ldx             #1
4323
        jsr             eth_build_packet
4324
        tay                                                             ; y = icmpstart
4325
        lda             #eth_rx_buffer<<2               ; memory address zero
4326
        add             r4,r1,r3
4327
        sb              r0,0,r4                                 ; [rx_addr+icmpstart] = 0
4328
        lb              r2,17,r1
4329
        add             r2,r2,#14                               ; r2 = len
4330
        ld              r6,r2                                   ; r6 = len
4331
        add             r15,r1,r3
4332
        lb              r4,2,r15                                ; shi
4333
        lb              r5,3,r15                                ; slo
4334
        asl             r4,r4,#8
4335
        or              r4,r4,r5                                ; sum = {shi,slo};
4336
        eor             r4,r4,#-1                               ; sum = ~sum
4337
        sub             r4,r4,#0x800                    ; sum = sum - 0x800
4338
        eor             r4,r4,#-1                               ; sum = ~sum
4339
        add             r15,r1,r3
4340
        sb              r4,3,r15
4341
        lsr             r4,r4,#8
4342
        sb              r4,2,r15
4343
        tyx
4344
        jsr             eth_checksum
4345
        lda             #eth_rx_buffer<<2               ; memory address zero
4346
        ld              r2,r6
4347
        jsr             eth_send_packet
4348
        jmp             eth_loop
4349
eth10:
4350
        ; r2 = rx_addr
4351
        cmp             #2
4352
        bne             eth_loop                ; Do we have ARP ?
4353
;       xor             r2,r2,r2                        ; memory address zero
4354
        ldx             #eth_rx_buffer<<2
4355
        ; get the opcode
4356
        lb              r13,21,x
4357
        cmp             r13,#1
4358
        bne             eth_loop                ; ARP request
4359
        ; get destination IP address
4360
        lb              r9,38,x
4361
        lb              r10,39,x
4362
        lb              r11,40,x
4363
        lb              r12,41,x
4364
        ; set r15 = destination IP
4365
        ld              r15,r9
4366
        asl             r15,r15,#8
4367
        or              r15,r15,r10
4368
        asl             r15,r15,#8
4369
        or              r15,r15,r11
4370
        asl             r15,r15,#8
4371
        or              r15,r15,r12
4372
        ; Is it our IP ?
4373
        cmp             r15,#$C0A8012A  ; //192.168.1.42
4374
        bne             eth_loop
4375
        ; get source IP address
4376
        lb              r5,28,x
4377
        lb              r6,29,x
4378
        lb              r7,30,x
4379
        lb              r8,31,x
4380
        ; set r14 = source IP
4381
        ld              r14,r5
4382
        asl             r14,r14,#8
4383
        or              r14,r14,r6
4384
        asl             r14,r14,#8
4385
        or              r14,r14,r7
4386
        asl             r14,r14,#8
4387
        or              r14,r14,r8
4388
        ; Get the source MAC address
4389
        push    r6
4390
        push    r7
4391
        push    r8
4392
        push    r9
4393
        push    r10
4394
        push    r11
4395
        lb              r6,22,x
4396
        lb              r7,23,x
4397
        lb              r8,24,x
4398
        lb              r9,25,x
4399
        lb              r10,26,x
4400
        lb              r11,27,x
4401
        ; write to destination header
4402
        sb              r6,0,x
4403
        sb              r7,1,x
4404
        sb              r8,2,x
4405
        sb              r9,3,x
4406
        sb              r10,4,x
4407
        sb              r11,5,x
4408
        ; and write to ARP destination
4409
        sb              r6,32,x
4410
        sb              r7,33,x
4411
        sb              r8,34,x
4412
        sb              r9,35,x
4413
        sb              r10,36,x
4414
        sb              r11,37,x
4415
        pop             r11
4416
        pop             r10
4417
        pop             r9
4418
        pop             r8
4419
        pop             r7
4420
        pop             r6
4421
        ; write to source header
4422
;       stbc    #0x00,6[r2]
4423
;       stbc    #0xFF,7[r2]
4424
;       stbc    #0xEE,8[r2]
4425
;       stbc    #0xF0,9[r2]
4426
;       stbc    #0xDA,10[r2]
4427
;       stbc    #0x42,11[r2]
4428
        sb              r0,6,x
4429
        lda             #0xFF
4430
        sb              r1,7,x
4431
        lda             #0xEE
4432
        sb              r1,8,x
4433
        lda             #0xF0
4434
        sb              r1,9,x
4435
        lda             #0xDA
4436
        sb              r1,10,x
4437
        lda             #0x42
4438
        sb              r1,11,x
4439
        ; write to ARP source
4440
;       stbc    #0x00,22[r2]
4441
;       stbc    #0xFF,23[r2]
4442
;       stbc    #0xEE,24[r2]
4443
;       stbc    #0xF0,25[r2]
4444
;       stbc    #0xDA,26[r2]
4445
;       stbc    #0x42,27[r2]
4446
        sb              r0,22,x
4447
        lda             #0xFF
4448
        sb              r1,23,x
4449
        lda             #0xEE
4450
        sb              r1,24,x
4451
        lda             #0xF0
4452
        sb              r1,25,x
4453
        lda             #0xDA
4454
        sb              r1,26,x
4455
        lda             #0x42
4456
        sb              r1,27,x
4457
        ; swap sender / destination IP
4458
        ; write sender
4459
        sb              r9,28,x
4460
        sb              r10,29,x
4461
        sb              r11,30,x
4462
        sb              r12,31,x
4463
        ; write destination
4464
        sb              r5,38,x
4465
        sb              r6,39,x
4466
        sb              r7,40,x
4467
        sb              r8,41,x
4468
        ; change request to reply
4469
;       stbc    #2,21[r2]
4470
        lda             #2
4471
        sb              r1,21,x
4472
        txa                                             ; r1 = packet address
4473
        ldx             #0x2A                   ; r2 = packet length
4474
        jsr             eth_send_packet
4475
        jmp             eth_loop
4476
 
4477
;--------------------------------------------------------------------------
4478
; Initialize sprite image caches with random data.
4479
;--------------------------------------------------------------------------
4480
RandomizeSprram:
4481
        ldx             #SPRRAM
4482
        ld              r4,#14336               ; number of chars to initialize
4483
rsr1:
4484
        tsr             LFSR,r1
4485
        sta             (x)
4486
        inx
4487
        dec             r4
4488
        bne             rsr1
4489
        rts
4490
 
4491
;--------------------------------------------------------------------------
4492
; Draw random lines on the bitmap screen.
4493
;--------------------------------------------------------------------------
4494
;
4495
RandomLines:
4496
        pha
4497
        phx
4498
        phy
4499
        push    r4
4500
        push    r5
4501
        jsr             RequestIOFocus
4502
rl5:
4503
        tsr             LFSR,r1
4504
        tsr             LFSR,r2
4505
        jsr             DrawPixel
4506
        tsr             LFSR,r1
4507
        sta             LineColor               ; select a random color
4508
rl1:                                            ; random X0
4509
        tsr             LFSR,r1
4510
        ld              r5,#1364
4511
        mod             r1,r1,r5
4512
rl2:                                            ; random X1
4513
        tsr             LFSR,r3
4514
        mod             r3,r3,r5
4515
rl3:                                            ; random Y0
4516
        tsr             LFSR,r2
4517
        ld              r5,#768
4518
        mod             r2,r2,r5
4519
rl4:                                            ; random Y1
4520
        tsr             LFSR,r4
4521
        ld              r5,#768
4522
        mod             r4,r4,r5
4523
rl8:
4524
        jsr             DrawLine
4525
        jsr             KeybdGetChar
4526
        cmp             #CTRLC
4527
        beq             rl7
4528
        bra             rl5
4529
rl7:
4530
        jsr             ReleaseIOFocus
4531
        pop             r5
4532
        pop             r4
4533
        ply
4534
        plx
4535
        pla
4536
        rts
4537
 
4538 28 robfinch
;--------------------------------------------------------------------------
4539
; Draw a pixel on the bitmap screen.
4540
; r1 = x coordinate
4541
; r2 = y coordinate
4542
; r3 = color
4543
;--------------------------------------------------------------------------
4544 26 robfinch
DrawPixel:
4545
        pha
4546
        phx
4547
        push    r4
4548
        ld              r4,#768
4549
        mod             r2,r2,r4
4550
        ld              r4,#1364
4551
        mod             r1,r1,r4
4552
        mul             r2,r2,r4        ; y * 1364
4553
        add             r1,r1,r2        ; + x
4554
        sb              r3,BITMAPSCR<<2,r1
4555
        pop             r4
4556
        plx
4557
        pla
4558
        rts
4559 28 robfinch
 
4560
;--------------------------------------------------------------------------
4561
; Draw a line on the bitmap screen.
4562
;--------------------------------------------------------------------------
4563 26 robfinch
;50 REM DRAWLINE
4564
;100 dx = ABS(xb-xa)
4565
;110 dy = ABS(yb-ya)
4566
;120 sx = SGN(xb-xa)
4567
;130 sy = SGN(yb-ya)
4568
;140 er = dx-dy
4569
;150 PLOT xa,ya
4570
;160 if xa<>xb goto 200
4571
;170 if ya=yb goto 300
4572
;200 ee = er * 2
4573
;210 if ee <= -dy goto 240
4574
;220 er = er - dy
4575
;230 xa = xa + sx
4576
;240 if ee >= dx goto 270
4577
;250 er = er + dx
4578
;260 ya = ya + sy
4579
;270 GOTO 150
4580
;300 RETURN
4581
 
4582
DrawLine:
4583
        pha
4584
        phx
4585
        phy
4586
        push    r4
4587
        push    r5
4588
        push    r6
4589
        push    r7
4590
        push    r8
4591
        push    r9
4592
        push    r10
4593
        push    r11
4594
 
4595
        sub             r5,r3,r1        ; dx = abs(x2-x1)
4596
        bpl             dln1
4597
        sub             r5,r0,r5
4598
dln1:
4599
        sub             r6,r4,r2        ; dy = abs(y2-y1)
4600
        bpl             dln2
4601
        sub             r6,r0,r6
4602
dln2:
4603
 
4604
        sub             r7,r3,r1        ; sx = sgn(x2-x1)
4605
        beq             dln5
4606
        bpl             dln4
4607
        ld              r7,#-1
4608
        bra             dln5
4609
dln4:
4610
        ld              r7,#1
4611
dln5:
4612
 
4613
        sub             r8,r4,r2        ; sy = sgn(y2-y1)
4614
        beq             dln8
4615
        bpl             dln7
4616
        ld              r8,#-1
4617
        bra             dln8
4618
dln7:
4619
        ld              r8,#1
4620
 
4621
dln8:
4622
        sub             r9,r5,r6        ; er = dx-dy
4623
dln150:
4624 28 robfinch
        phy
4625
        ldy             LineColor
4626 26 robfinch
        jsr             DrawPixel
4627 28 robfinch
        ply
4628 26 robfinch
        cmp             r1,r3           ; if (xa <> xb)
4629
        bne             dln200          ;    goto 200
4630
        cmp             r2,r4           ; if (ya==yb)
4631
        beq             dln300          ;    goto 300
4632
dln200:
4633
        asl             r10,r9          ; ee = er * 2
4634
        sub             r11,r0,r6       ; r11 = -dy
4635
        cmp             r10,r11         ; if (ee <= -dy)
4636
        bmi             dln240          ;     goto 240
4637
        beq             dln240
4638
        sub             r9,r9,r6        ; er = er - dy
4639
        add             r1,r1,r7        ; xa = xa + sx
4640
dln240:
4641
        cmp             r10,r5          ; if (ee >= dx)
4642
        bpl             dln150          ;    goto 150
4643
        add             r9,r9,r5        ; er = er + dx
4644
        add             r2,r2,r8        ; ya = ya + sy
4645
        bra             dln150          ; goto 150
4646
 
4647
dln300:
4648
        pop             r11
4649
        pop             r10
4650
        pop             r9
4651
        pop             r8
4652
        pop             r7
4653
        pop             r6
4654
        pop             r5
4655
        pop             r4
4656
        ply
4657
        plx
4658
        pla
4659
        rts
4660
 
4661
;include "float.asm"
4662
 
4663 15 robfinch
;------------------------------------------------------------------------------
4664 26 robfinch
; Bus Error Routine
4665
; This routine display a message then restarts the BIOS.
4666
;------------------------------------------------------------------------------
4667
;
4668
message "bus_err_rout"
4669
bus_err_rout:
4670
        cld
4671
        pla                                                     ; get rid of the stacked flags
4672
        ply                                                     ; get the error PC
4673
        ldx             #$05FFFFF8                      ; setup stack pointer top of memory
4674
        txs
4675
        jsr             CRLF
4676
        lda             #msgBusErr
4677
        jsr             DisplayStringB
4678
        tya
4679
        jsr             DisplayWord                     ; display the originating PC address
4680
        lda             #msgDataAddr
4681
        jsr             DisplayStringB
4682
        tsr             #9,r1
4683
        jsr             DisplayWord
4684
        cli                                                     ; enable interrupts so we can get a char
4685 28 robfinch
ber1:
4686 26 robfinch
        jsr             KeybdGetChar
4687 28 robfinch
        cmp             #-1
4688
        beq             ber1
4689 26 robfinch
        jmp             start
4690
 
4691
msgBusErr:
4692
        db              "Bus error at: ",0
4693
msgDataAddr:
4694
        db              " data address: ",0
4695
 
4696
strStartQue:
4697
        db              1,0,0,0,2,0,0,0,3,1,0,0,4,0,0,0
4698
 
4699
;------------------------------------------------------------------------------
4700 15 robfinch
; 100 Hz interrupt
4701
; - takes care of "flashing" the cursor
4702 26 robfinch
; - switching tasks
4703 15 robfinch
;------------------------------------------------------------------------------
4704
;
4705
p100Hz:
4706 26 robfinch
        ; Handle every other interrupt because 100Hz interrupts may be too fast.
4707
        pha
4708
        lda             IRQFlag
4709
        ina
4710
        sta             IRQFlag
4711
        ror
4712
        bcc             p100Hz11
4713 28 robfinch
        stz             0xFFDCFFFC              ; clear interrupt
4714 26 robfinch
        pla
4715
        rti
4716
 
4717
p100Hz11:
4718
 
4719
        cld             ; clear extended precision mode
4720
 
4721
        ; save off regs on the stack
4722
        phx
4723
        phy
4724
        push    r4
4725
        push    r5
4726
        push    r6
4727
        push    r7
4728
        push    r8
4729
        push    r9
4730
        push    r10
4731
        push    r11
4732
        push    r12
4733
        push    r13
4734
        push    r14
4735
        push    r15
4736
        ldx             RunningTCB
4737
        and             r2,r2,#$FF
4738
        tsa                                             ; save off the stack pointer
4739
        sta             TCB_SPSave,x
4740
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
4741
        sta             TCB_SP8Save,x
4742 28 robfinch
        lda             TCB_Status,x    ; set the task status to PREEMPT
4743
        and             r1,r1,#~TS_RUNNING
4744
        or              r1,r1,#TS_PREEMPT
4745
        sta             TCB_Status,x
4746 26 robfinch
 
4747
        ; support EhBASIC's IRQ functionality
4748
        ; code derived from minimon.asm
4749
        lda             #3                              ; Timer is IRQ #3
4750
        sta             IrqSource               ; stuff a byte indicating the IRQ source for PEEK()
4751
        lb              r1,IrqBase              ; get the IRQ flag byte
4752
        lsr             r2,r1
4753
        or              r1,r1,r2
4754
        and             #$E0
4755
        sb              r1,IrqBase
4756
 
4757
 
4758
        inc             TEXTSCR+83              ; update IRQ live indicator on screen
4759 15 robfinch
        stz             0xFFDCFFFC              ; clear interrupt
4760 26 robfinch
 
4761
        ; flash the cursor
4762
        lda             CursorFlash             ; test if we want a flashing cursor
4763
        beq             p100Hz1a
4764
        jsr             CalcScreenLoc   ; compute cursor location in memory
4765
        tay
4766
        lda             $10000,y                ; get color code $10000 higher in memory
4767
        ldx             IRQFlag                 ; get counter
4768
        lsr             r2,r2
4769
        and             r2,r2,#$0F              ; limit to low order nybble
4770
        and             #$F0                    ; prepare to or in new value, mask off foreground color
4771
        or              r1,r1,r2                ; set new foreground color for cursor
4772
        sta             $10000,y                ; store the color code back to memory
4773
p100Hz1a
4774
 
4775
        ; Check the timeout list to see if there are items ready to be removed from
4776
        ; the list. Also decrement the timeout of the item at the head of the list.
4777
 
4778
p100Hz15:
4779
        ldx             TimeoutList
4780
        bmi             p100Hz12                                ; are there any entries in the timeout list ?
4781
        lda             TCB_Timeout,x
4782
        bne             p100Hz14                                ; has this entry timed out ?
4783
        txa
4784
        jsr             RemoveFromTimeoutList
4785
        jsr             AddTaskToReadyList
4786
        bra             p100Hz15                                ; go back and see if there's another task to be removed
4787
 
4788
p100Hz14:
4789
        dea                                                             ; decrement the entries timeout
4790
        sta             TCB_Timeout,x
4791
 
4792
p100Hz12:
4793
SelectTaskToRun:
4794
        ; Search the ready queues for a ready task.
4795
        ; The search is occasionally started at a lower priority queue in order
4796
        ; to prevent starvation of lower priority tasks. This is managed by
4797
        ; using a tick count as an index to a string containing the start que.
4798
 
4799
        ld              r6,#5                   ; number of queues to search
4800
        ldy             IRQFlag                 ; use the IRQFlag as a buffer index
4801
        lsr             r3,r3,#1                ; the LSB is always the same
4802
        and             r3,r3,#$0F              ; counts from 0 to 15
4803
        lb              r3,strStartQue,y        ; get the queue to start search at
4804
p100Hz2:
4805
        lda             HeadRdy0,y
4806
        bmi             p100Hz1
4807
        ; Move the head of the ready queue to the tail
4808
        jsr             RemoveTaskFromReadyList ; remove task
4809
        jsr             AddTaskToReadyList              ; add it back (automatically goes to tail spot)
4810
        ldx             TCB_Status,r1           ; the task is no longer running
4811
        and             r2,r2,#~TS_RUNNING
4812
        stx             TCB_Status,r1
4813
        lda             HeadRdy0,y
4814
        sta             RunningTCB
4815
        ldx             TCB_Status,r1           ; flag the task as the running task
4816 28 robfinch
        or              r2,r2,#TS_RUNNING       ; task is now running and not preempt
4817
        and             r2,r2,#~TS_PREEMPT
4818 26 robfinch
        stx             TCB_Status,r1
4819
        bra             p100Hz3
4820
p100Hz1:
4821
        iny
4822
        cpy             #5
4823
        bne             p100Hz5
4824
        ldy             #0
4825
p100Hz5
4826
        dec             r6
4827
        bne             p100Hz2
4828
 
4829
        ; here there were no tasks ready
4830
        stz             RunningTCB                      ; select BIOS task
4831
        ldx             TCB_Status              ; flag the task as the running task
4832
        or              r2,r2,#TS_RUNNING
4833 28 robfinch
        and             r2,r2,#~TS_PREEMPT
4834 26 robfinch
        stx             TCB_Status
4835
p100Hz3:
4836
p100Hz10
4837
        ldx             RunningTCB
4838
        and             r2,r2,#$FF
4839
        lda             TCB_SP8Save,x           ; get back eight bit stack pointer
4840
        trs             r1,sp8
4841
        ldx             TCB_SPSave,x            ; get back stack pointer
4842
        txs
4843
        ; restore registers
4844
        pop             r15
4845
        pop             r14
4846
        pop             r13
4847
        pop             r12
4848
        pop             r11
4849
        pop             r10
4850
        pop             r9
4851
        pop             r8
4852
        pop             r7
4853
        pop             r6
4854
        pop             r5
4855
        pop             r4
4856
        ply
4857
        plx
4858
        pla
4859 15 robfinch
        rti
4860
 
4861 26 robfinch
 
4862 15 robfinch
;------------------------------------------------------------------------------
4863
; 1000 Hz interrupt
4864
; This IRQ must be fast.
4865 26 robfinch
; Increments the millisecond counter
4866 15 robfinch
;------------------------------------------------------------------------------
4867
;
4868
p1000Hz:
4869
        stz             0xFFDCFFFD                              ; acknowledge interrupt
4870
        inc             Milliseconds                    ; increment milliseconds count
4871
        rti
4872
 
4873
slp_rout:
4874
        rti
4875
brk_rout:
4876
        rti
4877 11 robfinch
nmirout
4878
        rti
4879 15 robfinch
message "1298"
4880
include "TinyBasic65002.asm"
4881 18 robfinch
message "1640"
4882 11 robfinch
        org $0FFFFFFF4          ; NMI vector
4883
        dw      nmirout
4884
 
4885
        org     $0FFFFFFF8              ; reset vector, native mode
4886
        dw      start
4887
 
4888
        end
4889
 

powered by: WebSVN 2.1.0

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