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

Subversion Repositories rtf65002

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

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

powered by: WebSVN 2.1.0

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