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

Subversion Repositories rtf65002

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

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

Line No. Rev Author Line
1 34 robfinch
 
2 11 robfinch
; ============================================================================
3
;        __
4
;   \\__/ o\    (C) 2013  Robert Finch, Stratford
5
;    \  __ /    All rights reserved.
6
;     \/_//     robfinch@opencores.org
7
;       ||
8
;
9
;
10
; This source file is free software: you can redistribute it and/or modify
11
; it under the terms of the GNU Lesser General Public License as published
12
; by the Free Software Foundation, either version 3 of the License, or
13
; (at your option) any later version.
14
;
15
; This source file is distributed in the hope that it will be useful,
16
; but WITHOUT ANY WARRANTY; without even the implied warranty of
17
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
; GNU General Public License for more details.
19
;
20
; You should have received a copy of the GNU General Public License
21
; along with this program.  If not, see .
22
;
23
; ============================================================================
24
;
25
CR      EQU     0x0D            ;ASCII equates
26
LF      EQU     0x0A
27
TAB     EQU     0x09
28
CTRLC   EQU     0x03
29
CTRLH   EQU     0x08
30
CTRLI   EQU     0x09
31
CTRLJ   EQU     0x0A
32
CTRLK   EQU     0x0B
33
CTRLM   EQU 0x0D
34
CTRLS   EQU     0x13
35
CTRLX   EQU     0x18
36
XON             EQU     0x11
37
XOFF    EQU     0x13
38
 
39 26 robfinch
; error codes
40
E_Ok            =               0x00
41
E_Arg           =               0x01
42
E_BadMbx        =               0x04
43
E_QueFull       =               0x05
44
E_NoThread      =               0x06
45
E_NotAlloc      =               0x09
46
E_NoMsg         =               0x0b
47
E_Timeout       =               0x10
48
E_BadAlarm      =               0x11
49
E_NotOwner      =               0x12
50
; resource errors
51
E_NoMoreMbx     =               0x40
52
E_NoMoreMsgBlks =       0x41
53
E_NoMoreAlarmBlks       =0x44
54
E_NoMoreTCBs    =       0x45
55
 
56
; task status
57
TS_NONE     =0
58
TS_TIMEOUT      =1
59
TS_WAITMSG      =2
60 28 robfinch
TS_PREEMPT      =4
61 26 robfinch
TS_RUNNING      =8
62
TS_READY        =16
63 31 robfinch
TS_SLEEP        =32
64 26 robfinch
 
65 31 robfinch
MAX_TASKNO      = 255
66 26 robfinch
 
67 31 robfinch
DIRENT_NAME             =0x00   ; file name
68
DIRENT_EXT              =0x1C   ; file name extension
69
DIRENT_ATTR             =0x20   ; attributes
70
DIRENT_DATETIME =0x28
71
DIRENT_CLUSTER  =0x30   ; starting cluster of file
72
DIRENT_SIZE             =0x34   ; file size (6 bytes)
73
 
74
; One FCB is allocated and filled out for each file that is open.
75
;
76
nFCBs   = 128
77
FCB_DE_NAME             =0x00
78
FCB_DE_EXT              =0x1C
79
FCB_DE_ATTR             =0x20
80
FCB_DE_DATETIME =0x28
81
FCB_DE_CLUSTER  =0x30   ; starting cluster of file
82
FCB_DE_SIZE             =0x34   ; 6 byte file size
83 34 robfinch
 
84 31 robfinch
FCB_DIR_SECTOR  =0x40   ; LBA directory sector this is from
85
FCB_DIR_ENT             =0x44   ; offset in sector for dir entry
86
FCB_LDRV                =0x48   ; logical drive this is on
87
FCB_MODE                =0x49   ; 0 read, 1=modify
88
FCB_NUSERS              =0x4A   ; number of users of this file
89
FCB_FMOD                =0x4B   ; flag: this file was modified
90
FCB_RESV                =0x4C   ; padding out to 80 bytes
91
FCB_SIZE                =0x50
92
 
93
FUB_JOB         =0x00   ; User's job umber
94
FUB_iFCB        =0x02   ; FCB number for this file
95
FUB_CrntLFA     =0x04   ; six byte current logical file address
96
FUB_pBuf        =0x0C   ; pointer to buffer if in stream mode
97
FUB_sBuf        =0x10   ; size of buffer for stream file
98
FUB_LFABuf      =0x14   ; S-First LFA in Clstr Buffer
99
FUB_LFACluster  =0x18   ; LFA of cluster
100
FUB_Clstr       = 0x20          ; The last cluster read
101
FUB_fModified   = 0x24  ; data in buffer was modified
102
FUB_fStream             = 0x25  ; non-zero for stream mode
103
FUB_PAD         =0x26
104
FUB_SIZE        =0x30
105
 
106
; Boot sector info (62 byte structure) */
107
BSI_JMP         = 0x00
108
BSI_OEMName     = 0x03
109
BSI_bps         = 0x0B
110
BSI_SecPerCluster       = 0x0D
111
BSI_ResSectors  = 0x0E
112
BSI_FATS        = 0x10
113
BSI_RootDirEnts = 0x11
114
BSI_Sectors     = 0x13
115
BSI_Media       = 0x15
116
BSI_SecPerFAT   = 0x16
117
BSI_SecPerTrack = 0x18
118
BSI_Heads       = 0x1A
119
BSI_HiddenSecs  = 0x1C
120
BSI_HugeSecs    = 0x1E
121
 
122
BSI_DriveNum    = 0x24
123
BSI_Rsvd1               = 0x25
124
BSI_BootSig             = 0x26
125
BSI_VolID               = 0x27
126
BSI_VolLabel    = 0x2B
127
BSI_FileSysType = 0x36
128
 
129
 
130
MEM_CHK         =0
131
MEM_FLAG        =1
132
MEM_PREV        =2
133
MEM_NEXT        =3
134
 
135 26 robfinch
; message queuing strategy
136
MQS_UNLIMITED   =0      ; unlimited queue size
137
MQS_NEWEST              =1      ; buffer queue size newest messages
138
MQS_OLDEST              =2      ; buffer queue size oldest messages
139
 
140 31 robfinch
LEDS            EQU             0xFFDC0600
141 11 robfinch
TEXTSCR         EQU             0xFFD00000
142
COLORSCR        EQU             0xFFD10000
143
TEXTREG         EQU             0xFFDA0000
144
TEXT_COLS       EQU             0x0
145
TEXT_ROWS       EQU             0x1
146
TEXT_CURPOS     EQU             11
147
KEYBD           EQU             0xFFDC0000
148
KEYBDCLR        EQU             0xFFDC0001
149 15 robfinch
PIC                     EQU             0xFFDC0FF0
150
PIC_IE          EQU             0xFFDC0FF1
151 31 robfinch
PIC_ES          EQU             0xFFDC0FF4
152
PIC_RSTE        EQU             0xFFDC0FF5
153 26 robfinch
TASK_SELECT     EQU             0xFFDD0008
154
RQ_SEMA         EQU             0xFFDB0000
155
TO_SEMA         EQU             0xFFDB0010
156
SERIAL_SEMA     EQU             0xFFDB0020
157
KEYBD_SEMA      EQU             0xFFDB0030
158
IOF_LIST_SEMA   EQU     0xFFDB0040
159
MBX_SEMA        EQU             0xFFDB0050
160 31 robfinch
MEM_SEMA        EQU             0xFFDB0060
161 11 robfinch
 
162
SPIMASTER       EQU             0xFFDC0500
163
SPI_MASTER_VERSION_REG  EQU     0x00
164
SPI_MASTER_CONTROL_REG  EQU     0x01
165
SPI_TRANS_TYPE_REG      EQU             0x02
166
SPI_TRANS_CTRL_REG      EQU             0x03
167
SPI_TRANS_STATUS_REG    EQU     0x04
168
SPI_TRANS_ERROR_REG             EQU     0x05
169
SPI_DIRECT_ACCESS_DATA_REG              EQU     0x06
170
SPI_SD_SECT_7_0_REG             EQU     0x07
171
SPI_SD_SECT_15_8_REG    EQU     0x08
172
SPI_SD_SECT_23_16_REG   EQU     0x09
173
SPI_SD_SECT_31_24_REG   EQU     0x0a
174
SPI_RX_FIFO_DATA_REG    EQU     0x10
175
SPI_RX_FIFO_DATA_COUNT_MSB      EQU     0x12
176
SPI_RX_FIFO_DATA_COUNT_LSB  EQU 0x13
177
SPI_RX_FIFO_CTRL_REG            EQU     0x14
178
SPI_TX_FIFO_DATA_REG    EQU     0x20
179
SPI_TX_FIFO_CTRL_REG    EQU     0x24
180
SPI_RESP_BYTE1                  EQU     0x30
181
SPI_RESP_BYTE2                  EQU     0x31
182
SPI_RESP_BYTE3                  EQU     0x32
183
SPI_RESP_BYTE4                  EQU     0x33
184
SPI_INIT_SD                     EQU             0x01
185
SPI_TRANS_START         EQU             0x01
186
SPI_TRANS_BUSY          EQU             0x01
187
SPI_INIT_NO_ERROR       EQU             0x00
188
SPI_READ_NO_ERROR       EQU             0x00
189 15 robfinch
SPI_WRITE_NO_ERROR      EQU             0x00
190 11 robfinch
RW_READ_SD_BLOCK        EQU             0x02
191
RW_WRITE_SD_BLOCK       EQU             0x03
192
 
193 26 robfinch
UART            EQU             0xFFDC0A00
194
UART_LS         EQU             0xFFDC0A01
195
UART_MS         EQU             0xFFDC0A02
196
UART_IS         EQU             0xFFDC0A03
197
UART_IE         EQU             0xFFDC0A04
198
UART_MC         EQU             0xFFDC0A06
199
UART_CM1        EQU             0xFFDC0A09
200
UART_CM2        EQU             0xFFDC0A0A
201
UART_CM3        EQU             0xFFDC0A0B
202
txempty         EQU             0x40
203
rxfull          EQU             0x01
204
 
205
CONFIGREC       EQU             0xFFDCFFF0
206
CR_CLOCK        EQU             0xFFDCFFF4
207
GACCEL          EQU             0xFFDAE000
208 34 robfinch
GA_X0           EQU             0xFFDAE002
209
GA_Y0           EQU             0xFFDAE003
210
GA_PEN          EQU             0xFFDAE000
211
GA_X1           EQU             0xFFDAE004
212
GA_Y1           EQU             0xFFDAE005
213
GA_STATE        EQU             0xFFDAE00E
214
GA_CMD          EQU             0xFFDAE00F
215
 
216 28 robfinch
AC97            EQU             0xFFDC1000
217
PSG                     EQU             0xFFD50000
218
PSGFREQ0        EQU             0xFFD50000
219
PSGPW0          EQU             0xFFD50001
220
PSGCTRL0        EQU             0xFFD50002
221
PSGADSR0        EQU             0xFFD50003
222 26 robfinch
 
223
ETHMAC          EQU             0xFFDC2000
224
ETH_MODER               EQU             0x00
225
ETH_INT_SOURCE  EQU             0x01
226
ETH_INT_MASK    EQU             0x02
227
ETH_IPGT                EQU             0x03
228
ETH_IPGR1               EQU             0x04
229
ETH_IPGR2               EQU             0x05
230
ETH_PACKETLEN   EQU             0x06
231
ETH_COLLCONF    EQU             0x07
232
ETH_TX_BD_NUM   EQU             0x08
233
ETH_CTRLMODER   EQU             0x09
234
ETH_MIIMODER    EQU             0x0A
235
ETH_MIICOMMAND  EQU             0x0B
236
ETH_MIIADDRESS  EQU             0x0C
237
ETH_MIITX_DATA  EQU             0x0D
238
ETH_MIIRX_DATA  EQU             0x0E
239
ETH_MIISTATUS   EQU             0x0F
240
ETH_MAC_ADDR0   EQU             0x10
241
ETH_MAC_ADDR1   EQU             0x11
242
ETH_HASH0_ADDR  EQU             0x12
243
ETH_HASH1_ADDR  EQU             0x13
244
ETH_TXCTRL              EQU             0x14
245
 
246 34 robfinch
ETH_WCTRLDATA   EQU             4
247
ETH_MIICOMMAND_RSTAT    EQU     2
248
ETH_MIISTATUS_BUSY      EQU             2
249
ETH_MIIMODER_RST        EQU             $200
250
ETH_MODER_RST       EQU         $800
251
ETH_MII_BMCR            EQU             0                ; basic mode control register
252
ETH_MII_ADVERTISE       EQU             4
253
ETH_MII_EXPANSION       =6
254
ETH_MII_CTRL1000        =9
255
ETH_ADVERTISE_ALL       EQU             $1E0
256
ETH_ADVERTISE_1000FULL      =0x0200  ; Advertise 1000BASE-T full duplex
257
ETH_ADVERTISE_1000HALF      =0x0100  ; Advertise 1000BASE-T half duplex
258
ETH_ESTATUS_1000_TFULL  =0x2000 ; Can do 1000BT Full
259
ETH_ESTATUS_1000_THALF  =0x1000 ; Can do 1000BT Half
260
ETH_BMCR_ANRESTART      =    0x0200  ; Auto negotiation restart
261
ETH_BMCR_ISOLATE        =    0x0400  ; Disconnect DP83840 from MII
262
ETH_BMCR_PDOWN          =    0x0800  ; Powerdown the DP83840
263
ETH_BMCR_ANENABLE       =    0x1000  ; Enable auto negotiation
264
 
265
ETH_PHY         =7
266
 
267
MMU                     EQU             0xFFDC4000
268
MMU_KVMMU       EQU             0xFFDC4800
269
MMU_FUSE        EQU             0xFFDC4811
270
MMU_AKEY        EQU             0xFFDC4812
271
MMU_OKEY        EQU             0xFFDC4813
272
MMU_MAPEN       EQU             0xFFDC4814
273
 
274
DATETIME        EQU             0xFFDC0400
275
DATETIME_TIME           EQU             0xFFDC0400
276
DATETIME_DATE           EQU             0xFFDC0401
277
DATETIME_ALMTIME        EQU             0xFFDC0402
278
DATETIME_ALMDATE        EQU             0xFFDC0403
279
DATETIME_CTRL           EQU             0xFFDC0404
280
DATETIME_SNAPSHOT       EQU             0xFFDC0405
281
 
282 26 robfinch
SPRITEREGS      EQU             0xFFDAD000
283
SPRRAM          EQU             0xFFD80000
284
 
285
THRD_AREA       EQU             0x04000000      ; threading area 0x04000000-0x40FFFFF
286
BITMAPSCR       EQU             0x04100000
287
SECTOR_BUF      EQU             0x05FBEC00
288
BIOS_STACKS     EQU             0x05FC0000      ; room for 256 1kW stacks
289
BIOS_SCREENS    EQU     0x05C00000      ; 0x05C00000 to 0x05DFFFFF
290
 
291 15 robfinch
BYTE_SECTOR_BUF EQU     SECTOR_BUF<<2
292 26 robfinch
PROG_LOAD_AREA  EQU             0x4180000<<2
293 11 robfinch
 
294 31 robfinch
FCBs                    EQU             0x5F40000       ; room for 128 FCB's
295 28 robfinch
 
296 31 robfinch
FATOFFS                 EQU             0x5F50000       ; offset into FAT on card
297
FATBUF                  EQU             0x5F60000
298
DIRBUF                  EQU             0x5F70000
299 26 robfinch
eth_rx_buffer   EQU             0x5F80000
300
eth_tx_buffer   EQU             0x5F84000
301 11 robfinch
 
302 26 robfinch
; Mailboxes, room for 2048
303
MBX_LINK        EQU             0x05F90000
304
MBX_TQ_HEAD     EQU             0x05F90800
305
MBX_TQ_TAIL     EQU             0x05F91000
306
MBX_MQ_HEAD     EQU             0x05F91800
307
MBX_MQ_TAIL     EQU             0x05F92000
308
MBX_TQ_COUNT    EQU     0x05F92800
309
MBX_MQ_SIZE     EQU             0x05F93000
310
MBX_MQ_COUNT    EQU     0x05F93800
311
MBX_MQ_MISSED   EQU     0x05F94000
312
MBX_OWNER               EQU     0x05F94800
313
MBX_MQ_STRATEGY EQU     0x05F95000
314
MBX_RESV                EQU     0x05F95800
315 11 robfinch
 
316 26 robfinch
; Messages, room for 8kW (8,192) messages
317
MSG_LINK        EQU             0x05FA0000
318
MSG_D1          EQU             0x05FA2000
319
MSG_D2          EQU             0x05FA4000
320
MSG_TYPE        EQU             0x05FA6000
321
 
322
; Task control blocks, room for 256 tasks
323
TCB_NxtRdy              EQU             0x05FBE100      ; next task on ready / timeout list
324
TCB_PrvRdy              EQU             0x05FBE200      ; previous task on ready / timeout list
325
TCB_NxtTCB              EQU             0x05FBE300
326
TCB_Timeout             EQU             0x05FBE400
327
TCB_Priority    EQU             0x05FBE500
328
TCB_MSGPTR_D1   EQU             0x05FBE600
329
TCB_MSGPTR_D2   EQU             0x05FBE700
330
TCB_hJCB                EQU             0x05FBE800
331
TCB_Status              EQU             0x05FBE900
332
TCB_CursorRow   EQU             0x05FBD100
333
TCB_CursorCol   EQU             0x05FBD200
334
TCB_hWaitMbx    EQU             0x05FBD300      ; handle of mailbox task is waiting at
335
TCB_mbq_next    EQU             0x05FBD400      ; mailbox queue next
336
TCB_mbq_prev    EQU             0x05FBD500      ; mailbox queue previous
337 28 robfinch
TCB_iof_next    EQU             0x05FBD600
338
TCB_iof_prev    EQU             0x05FBD700
339
TCB_SP8Save             EQU             0x05FBD800      ; TCB_SP8Save area
340
TCB_SPSave              EQU             0x05FBD900      ; TCB_SPSave area
341 31 robfinch
TCB_ABS8Save    EQU             0x05FBDA00
342 34 robfinch
TCB_mmu_map             EQU             0x05FBDB00
343 26 robfinch
 
344
KeybdHead       EQU             0x05FBEA00
345
KeybdTail       EQU             0x05FBEB00
346
KeybdEcho       EQU             0x05FBEC00
347
KeybdBad        EQU             0x05FBED00
348
KeybdAck        EQU             0x05FBEE00
349
KeybdLocks      EQU             0x05FBEF00
350
KeybdBuffer     EQU             0x05FBF000      ; buffer is 16 chars
351
 
352 31 robfinch
HeapStart       EQU             0x04200000
353 34 robfinch
HeapEnd         EQU             0x043FFFFF
354 31 robfinch
 
355 28 robfinch
; Bitmap of tasks requesting the I/O focus
356
;
357
IOFocusTbl      EQU             0x05FBD000
358 26 robfinch
 
359 28 robfinch
; EhBASIC vars:
360 15 robfinch
;
361 26 robfinch
NmiBase         EQU             0xDC
362
IrqBase         EQU             0xDF
363
 
364 28 robfinch
; BIOS vars at the top of the 8kB scratch memory
365
;
366
; TinyBasic AREA = 0xF00 to 0xF7F
367 26 robfinch
 
368 34 robfinch
QNdx0           EQU             0xF80
369
QNdx1           EQU             QNdx0+1
370
QNdx2           EQU             QNdx1+1
371
QNdx3           EQU             QNdx2+1
372
QNdx4           EQU             QNdx3+1
373
FreeTCB         EQU             QNdx4+1
374 26 robfinch
TimeoutList     EQU             FreeTCB+1
375
RunningTCB              EQU             TimeoutList+1
376
FreeMbx         EQU             RunningTCB + 1
377
nMailbox        EQU             FreeMbx + 1
378
FreeMsg         EQU             nMailbox + 1
379
nMsgBlk         EQU             FreeMsg + 1
380
 
381 28 robfinch
; The IO focus list is a doubly linked list formed into a ring.
382
;
383
IOFocusNdx      EQU             nMsgBlk + 1
384 26 robfinch
 
385 28 robfinch
IrqSource       EQU             0xF98
386 15 robfinch
 
387 28 robfinch
JMPTMP          EQU             0xFA0
388
SP8Save         EQU             0xFAE
389
SRSave          EQU             0xFAF
390
R1Save          EQU             0xFB0
391
R2Save          EQU             0xFB1
392
R3Save          EQU             0xFB2
393
R4Save          EQU             0xFB3
394
R5Save          EQU             0xFB4
395
R6Save          EQU             0xFB5
396
R7Save          EQU             0xFB6
397
R8Save          EQU             0xFB7
398
R9Save          EQU             0xFB8
399
R10Save         EQU             0xFB9
400
R11Save         EQU             0xFBA
401
R12Save         EQU             0xFBB
402
R13Save         EQU             0xFBC
403
R14Save         EQU             0xFBD
404
R15Save         EQU             0xFBE
405
SPSave          EQU             0xFBF
406 15 robfinch
 
407 28 robfinch
CharColor       EQU             0xFC0
408
ScreenColor     EQU             0xFC1
409
CursorRow       EQU             0xFC2
410
CursorCol       EQU             0xFC3
411
CursorFlash     EQU             0xFC4
412
Milliseconds    EQU             0xFC5
413
IRQFlag         EQU             0xFC6
414
RdyQueTick      EQU             0xFC7
415
eth_unique_id   EQU             0xFC8
416
LineColor       EQU             0xFC9
417 31 robfinch
QIndex          EQU             0xFCA
418 34 robfinch
ROMcs           EQU             0xFCB
419
mmu_present     EQU             0xFCC
420
TestTask        EQU             0xFCD
421
KeybdIsSetup    EQU             0xFCE
422 28 robfinch
 
423 26 robfinch
Uart_rxfifo             EQU             0x05FBC000
424 28 robfinch
Uart_rxhead             EQU             0xFD0
425
Uart_rxtail             EQU             0xFD1
426
Uart_ms                 EQU             0xFD2
427
Uart_rxrts              EQU             0xFD3
428
Uart_rxdtr              EQU             0xFD4
429
Uart_rxxon              EQU             0xFD5
430
Uart_rxflow             EQU             0xFD6
431
Uart_fon                EQU             0xFD7
432
Uart_foff               EQU             0xFD8
433
Uart_txrts              EQU             0xFD9
434
Uart_txdtr              EQU             0xFDA
435
Uart_txxon              EQU             0xFDB
436
Uart_txxonoff   EQU             0xFDC
437 15 robfinch
 
438 28 robfinch
startSector     EQU             0xFF0
439 15 robfinch
 
440
 
441 11 robfinch
        cpu             rtf65002
442
        code
443 15 robfinch
 
444 26 robfinch
message "jump table"
445 15 robfinch
        ; jump table of popular BIOS routines
446 31 robfinch
        org             $FFFF8000
447 34 robfinch
ROMStart:
448 15 robfinch
        dw      DisplayChar
449
        dw      KeybdCheckForKeyDirect
450
        dw      KeybdGetCharDirect
451 26 robfinch
        dw      KeybdGetChar
452
        dw      KeybdCheckForKey
453
        dw      RequestIOFocus
454
        dw      ReleaseIOFocus
455
        dw      ClearScreen
456
        dw      HomeCursor
457
        dw      ExitTask
458
        dw      SetKeyboardEcho
459 28 robfinch
        dw      Sleep
460 31 robfinch
        dw      do_load
461
        dw      do_save
462 15 robfinch
 
463 31 robfinch
        org             $FFFF8400               ; leave room for 256 vectors
464 26 robfinch
message "cold start point"
465 15 robfinch
KeybdRST
466 11 robfinch
start
467
        sei                                             ; disable interrupts
468
        cld                                             ; disable decimal mode
469 31 robfinch
        lda             #1
470
        sta             LEDS
471 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer top of memory
472 11 robfinch
        txs
473 31 robfinch
        trs             r0,abs8                 ; set 8 bit mode absolute address offset
474 34 robfinch
        lda             #3
475
        trs             r1,cc                   ; enable dcache and icache
476
        jsr             ROMChecksum
477
        sta             ROMcs
478
        stz             mmu_present             ; assume no mmu
479
        lda             CONFIGREC
480
        bit             #4096
481
        beq             st_nommu
482
        jsr             InitMMU                 ; setup the maps and enable the mmu
483
        lda             #1
484
        sta             mmu_present
485
st_nommu:
486 31 robfinch
        jsr             MemInit                 ; Initialize the heap
487
 
488
        lda             #2
489
        sta             LEDS
490
 
491 15 robfinch
        ; setup interrupt vectors
492 26 robfinch
        ldx             #$05FB0001              ; interrupt vector table from $5FB0000 to $5FB01FF
493 18 robfinch
                                                        ; also sets nmoi policy (native mode on interrupt)
494 15 robfinch
        trs             r2,vbr
495 18 robfinch
        dex
496 34 robfinch
        phx
497
        txy                                             ; y = pointer to vector table
498
        lda             #511                    ; 512 vectors to setup
499
        ldx             #brk_rout               ; point vector to brk routine
500
        stos
501
 
502
        plx
503 15 robfinch
        lda             #brk_rout
504
        sta             (x)
505
        lda             #slp_rout
506
        sta             1,x
507 34 robfinch
        lda             #reschedule
508
        sta             2,x
509 15 robfinch
        lda             #KeybdRST
510
        sta             448+1,x
511
        lda             #p1000Hz
512
        sta             448+2,x
513
        lda             #p100Hz
514
        sta             448+3,x
515
        lda             #KeybdIRQ
516
        sta             448+15,x
517 26 robfinch
        lda             #SerialIRQ
518
        sta             448+8,x
519 31 robfinch
        lda             #InvalidOpIRQ
520
        sta             495,x
521 26 robfinch
        lda             #bus_err_rout
522
        sta             508,x
523
        sta             509,x
524 15 robfinch
 
525 31 robfinch
        lda             #3
526
        sta             LEDS
527
 
528
        ; stay in native mode in case emulation is not supported.
529
        ldx             #$1FF                   ; set 8 bit stack pointer
530
        trs             r2,sp8
531 26 robfinch
 
532
        ldx             #0
533
        stz             IrqBase                 ; support for EhBASIC's interrupt mechanism
534
        stz             NmiBase
535 31 robfinch
 
536 26 robfinch
        lda             #-1
537
        sta             TimeoutList             ; no entries in timeout list
538 34 robfinch
        sta             QNdx0
539
        sta             QNdx1
540
        sta             QNdx2
541
        sta             QNdx3
542
        sta             QNdx4
543 26 robfinch
 
544 31 robfinch
 
545 26 robfinch
        ; Initialize IO Focus List
546
        ;
547 34 robfinch
        lda             #7
548
        ldx             #0
549
        ldy             #IOFocusTbl
550
        stos
551 26 robfinch
 
552 34 robfinch
        lda             #255
553
        ldx             #-1
554
        ldy             #TCB_iof_next
555
        stos
556
        lda             #255
557
        ldx             #-1
558
        ldy             #TCB_iof_prev
559
        stos
560 28 robfinch
 
561 26 robfinch
        ; Initialize free message list
562
        lda             #8192
563
        sta             nMsgBlk
564
        stz             FreeMsg
565
        ldx             #0
566
        lda             #1
567
st4:
568
        sta             MSG_LINK,x
569
        ina
570
        inx
571
        cpx             #8192
572
        bne             st4
573
        lda             #-1
574
        sta             MBX_LINK+8191
575
 
576
        ; Initialize free mailbox list
577
        lda             #2048
578
        sta             nMailbox
579
 
580
        stz             FreeMbx
581
        ldx             #0
582
        lda             #1
583
st3:
584
        sta             MBX_LINK,x
585
        ina
586
        inx
587
        cpx             #2048
588
        bne             st3
589
        lda             #-1
590
        sta             MBX_LINK+2047
591
 
592
        ; Initialize the FreeTCB list
593
        lda             #1                              ; the next available TCB
594
        sta             FreeTCB
595
        ldx             #1
596
        lda             #2
597
st2:
598
        sta             TCB_NxtTCB,x
599
        ina
600
        inx
601
        cpx             #256
602
        bne             st2
603
        lda             #-1
604
        sta             TCB_NxtTCB+255
605 31 robfinch
        lda             #4
606
        sta             LEDS
607 26 robfinch
 
608 31 robfinch
        ; Manually setup the BIOS task
609
        stz             RunningTCB              ; BIOS is task #0
610 34 robfinch
        stz             TCB_NxtRdy              ; manually build the ready list
611
        stz             TCB_PrvRdy
612
        stz             QNdx0                   ; insert at priority 0
613 31 robfinch
        stz             TCB_iof_next    ; manually build the IO focus list
614
        stz             TCB_iof_prev
615
        stz             IOFocusNdx              ; task #0 has the focus
616 26 robfinch
        lda             #1
617 31 robfinch
        sta             IOFocusTbl              ; set the task#0 request bit
618
        lda             #0
619
        sta             TCB_Priority
620 34 robfinch
        stz             TCB_Timeout
621 31 robfinch
        lda             #TS_RUNNING|TS_READY
622
        sta             TCB_Status
623
        stz             TCB_CursorRow
624
        stz             TCB_CursorCol
625 34 robfinch
 
626 31 robfinch
        lda             #1
627 26 robfinch
        sta             MBX_SEMA
628
        sta             IOF_LIST_SEMA
629
        sta             RQ_SEMA                 ; set ready queue semaphore
630
        sta             TO_SEMA                 ; set timeout list semaphore
631 31 robfinch
 
632 11 robfinch
        lda             #$CE                    ; CE =blue on blue FB = grey on grey
633
        sta             ScreenColor
634
        sta             CharColor
635 26 robfinch
        sta             CursorFlash
636 11 robfinch
        jsr             ClearScreen
637 15 robfinch
        jsr             ClearBmpScreen
638 34 robfinch
        jsr             PICInit
639
        ; Enable interrupts
640
        ; This will likely cause an interrupt right away because the timer
641
        ; pulses run since power-up.
642
        cli
643 31 robfinch
        lda             #4
644
        ldx             #0
645
        ldy             #IdleTask
646
        jsr             StartTask
647
        lda             CONFIGREC               ; do we have a serial port ?
648
        bit             #32
649
        beq             st7
650
        ; 19200 * 16
651
        ;-------------
652
        ; 25MHz / 2^32
653
        lda             #$03254E6E              ; constant for 19,200 baud at 25MHz
654
        jsr             SerialInit
655
st7:
656
        lda             #5
657
        sta             LEDS
658 28 robfinch
        lda             CONFIGREC               ; do we have sprites ?
659
        bit             #1
660
        beq             st8
661 26 robfinch
        lda             #$3FFF                  ; turn on sprites
662
        sta             SPRITEREGS+120
663
        jsr             RandomizeSprram
664 28 robfinch
st8:
665 31 robfinch
        ; Enable interrupts.
666
        ; Keyboard initialization must take place after interrupts are
667
        ; enabled.
668
        cli
669
        lda             #14
670
        sta             LEDS
671 15 robfinch
        jsr             KeybdInit
672
        lda             #1
673
        sta             KeybdEcho
674 31 robfinch
        lda             #6
675
        sta             LEDS
676
 
677 28 robfinch
        ; The following must be after interrupts are enabled.
678 31 robfinch
        lda             #9
679
        sta             LEDS
680
        jsr             HomeCursor
681
        lda             #msgStart
682
        jsr             DisplayStringB
683
        jsr             ReportMemFree
684 34 robfinch
        lda             #msgChecksum
685
        jsr             DisplayStringB
686
        lda             ROMcs
687
        jsr             DisplayWord
688
        jsr             CRLF
689 31 robfinch
        lda             #10
690
        sta             LEDS
691
 
692 28 robfinch
        ; The AC97 setup uses the millisecond counter and the
693
        ; keyboard.
694
        lda             CONFIGREC               ; do we have a sound generator ?
695
        bit             #4
696
        beq             st6
697
        jsr             SetupAC97
698 34 robfinch
        lda             #4
699 31 robfinch
        ldx             #0
700
        ldy             #Beep
701 34 robfinch
;       jsr             StartTask
702 28 robfinch
st6:
703 31 robfinch
        lda             #11
704
        sta             LEDS
705 15 robfinch
        jmp             Monitor
706
st1
707
        jsr             KeybdGetCharDirect
708
        bra             st1
709 11 robfinch
        stp
710
        bra             start
711
 
712
msgStart
713
        db              "RTF65002 system starting.",$0d,$0a,00
714
 
715 34 robfinch
;------------------------------------------------------------------------------
716
; InitMMU
717
;
718
; Initialize the 64 maps of the MMU.
719
; Initially all the maps are set the same:
720
; Virtual Page  Physical Page
721
; 000-255                000-255
722
; 256-511               1792-2047
723
; Note that there are only 512 virtual pages per map, and 2048 real
724
; physical pages of memory. This limits maps to 32MB.
725
; This range includes the BIOS assigned stacks for the tasks and tasks
726
; virtual video buffers. It also includes the bitmap screen buffer.
727
; Note that physical pages 256 to 1791 are not mapped, but do exist.
728
; If changing the maps the last 128 pages (8MB) of the map should always point
729
; to the BIOS area. Don't change map entries 384-511 or the system may
730
; crash.
731
; If the rts at the end of this routine works, then memory was mapped
732
; successfully.
733
;------------------------------------------------------------------------------
734
InitMMU:
735
        lda             #1
736
        sta             MMU_KVMMU+1
737
        dea
738
        sta             MMU_KVMMU
739
immu1:
740
        sta             MMU_AKEY        ; set access key for map
741
        ldy             #0              ;
742
        ldx             #0
743
immu2:
744
        ; set the first 256 pages to physical page 0-255
745
        ; set the last 256 pages to physical page 1792-2047
746
        ld              r4,r3
747
        bit             r3,#$0100
748
        beq             immu3
749
        add             r4,r4,#1536
750
immu3:
751
        st              r4,MMU,x
752
        iny
753
        inx
754
        cpx             #512
755
        bne             immu2
756
        ina
757
        cmp             #64                     ; 64 MMU maps
758
        bne             immu1
759
        stz             MMU_OKEY        ; set operating key to map #0
760
        lda             #2
761
        sta             MMU_FUSE        ; set fuse to 2 clocks before mapping starts
762
        nop
763
        nop
764
 
765
EnableMMUMapping:
766
        pha
767
        lda             #1
768
        sta             MMU_MAPEN
769
        pla
770
        rts
771
DisableMMUMapping:
772
        stz             MMU_MAPEN
773
        rts
774
 
775
;------------------------------------------------------------------------------
776
; The ROM contents are summed up to ensure the ROM is okay.
777
;------------------------------------------------------------------------------
778
ROMChecksum:
779
        lda             #0
780
        ldx             #ROMStart>>2
781
idc1:
782
        add             (x)
783
        inx
784
        cpx             #$100000000>>2
785
        bne             idc1
786
        cmp             #0                      ; The sum of all the words in the
787
                                                ; ROM should be zero.
788
        rts
789
 
790
msgChecksum:
791
        db      CR,LF,"ROM checksum: ",0
792
 
793 15 robfinch
;----------------------------------------------------------
794
; Initialize programmable interrupt controller (PIC)
795
;  0 = nmi (parity error)
796
;  1 = keyboard reset
797 31 robfinch
;  2 = 1000Hz pulse
798 15 robfinch
;  3 = 100Hz pulse (cursor flash)
799
;  4 = ethmac
800
;  8 = uart
801
; 13 = raster interrupt
802
; 15 = keyboard char
803
;----------------------------------------------------------
804 26 robfinch
message "PICInit"
805 15 robfinch
PICInit:
806 31 robfinch
        ;
807
        lda             #$000C                  ; clock pulses are edge sensitive
808
        sta             PIC_ES
809
        lda             #$000F                  ; enable nmi,kbd_rst
810 15 robfinch
        ; A10F enable serial IRQ
811
        sta             PIC_IE
812
PICret:
813
        rts
814
 
815 11 robfinch
;------------------------------------------------------------------------------
816 26 robfinch
;------------------------------------------------------------------------------
817
message "DumpTaskList"
818
DumpTaskList:
819
        pha
820
        phx
821
        phy
822
        push    r4
823
        lda             #msgTaskList
824
        jsr             DisplayStringB
825
        ldy             #0
826
        php
827
        sei
828
dtl2:
829 34 robfinch
        lda             QNdx0,y
830 26 robfinch
        ld              r4,r1
831
        bmi             dtl1
832
dtl3:
833
        ldx             #3
834
        tya
835
        jsr             PRTNUM
836
        lda             #' '
837
        jsr             DisplayChar
838
        ld              r1,r4
839
        ldx             #3
840
        jsr             PRTNUM
841
        lda             #' '
842
        jsr             DisplayChar
843
        jsr             DisplayChar
844
        jsr             DisplayChar
845
        ld              r1,r4
846
        lda             TCB_Status,r1
847
        jsr             DisplayByte
848
        lda             #' '
849
        jsr             DisplayChar
850
        ldx             #3
851
        lda             TCB_PrvRdy,r4
852
        jsr             PRTNUM
853
        lda             #' '
854
        jsr             DisplayChar
855
        ldx             #3
856
        lda             TCB_NxtRdy,r4
857
        jsr             PRTNUM
858
        lda             #' '
859
        jsr             DisplayChar
860
        lda             TCB_Timeout,r4
861
        jsr             DisplayWord
862
        jsr             CRLF
863
        ld              r4,TCB_NxtRdy,r4
864 34 robfinch
        cmp             r4,QNdx0,y
865
        bne             dtl3
866 26 robfinch
dtl1:
867
        iny
868
        cpy             #5
869
        bne             dtl2
870
        plp
871
        pop             r4
872
        ply
873
        plx
874
        pla
875
        rts
876
 
877
msgTaskList:
878
        db      CR,LF,"Pri Task Stat Prv Nxt Timeout",CR,LF,0
879
 
880
;------------------------------------------------------------------------------
881 28 robfinch
;------------------------------------------------------------------------------
882 34 robfinch
message "DumpTimeoutList"
883
DumpTimeoutList:
884
        pha
885
        phx
886
        phy
887
        push    r4
888
        lda             #msgTimeoutList
889
        jsr             DisplayStringB
890
        php
891
        sei
892
dtol2:
893
        lda             TimeoutList
894
        ld              r4,r1
895
        bmi             dtol1
896
dtol3:
897
        ld              r1,r4
898
        ldx             #3
899
        jsr             PRTNUM
900
        lda             #' '
901
        jsr             DisplayChar
902
        jsr             DisplayChar
903
        jsr             DisplayChar
904
        ld              r1,r4
905
        ldx             #3
906
        lda             TCB_PrvRdy,r4
907
        jsr             PRTNUM
908
        lda             #' '
909
        jsr             DisplayChar
910
        ldx             #3
911
        lda             TCB_NxtRdy,r4
912
        jsr             PRTNUM
913
        lda             #' '
914
        jsr             DisplayChar
915
        lda             TCB_Timeout,r4
916
        jsr             DisplayWord
917
        jsr             CRLF
918
        ld              r4,TCB_NxtRdy,r4
919
        bpl             dtol3
920
dtol1:
921
        plp
922
        pop             r4
923
        ply
924
        plx
925
        pla
926
        rts
927
 
928
msgTimeoutList:
929
        db      CR,LF,"Task Prv Nxt Timeout",CR,LF,0
930
 
931
;------------------------------------------------------------------------------
932
;------------------------------------------------------------------------------
933 28 robfinch
message "DumpIOFocusList"
934
DumpIOFocusList:
935
        pha
936
        phx
937
        phy
938
        php
939
        sei
940
        lda             #msgIOFocusList
941
        jsr             DisplayStringB
942
        lda             IOFocusNdx
943
diofl2:
944
        bmi             diofl1
945
        tay
946
        ldx             #3
947
        jsr             PRTNUM
948
        lda             #' '
949
        jsr             DisplayChar
950
        lda             TCB_iof_prev,y
951
        ldx             #3
952
        jsr             PRTNUM
953
        lda             #' '
954
        jsr             DisplayChar
955
        lda             TCB_iof_next,y
956
        ldx             #3
957
        jsr             PRTNUM
958
        jsr             CRLF
959
        lda             TCB_iof_next,y
960
        cmp             IOFocusNdx
961
        bne             diofl2
962
 
963
diofl1:
964
        plp
965
        ply
966
        plx
967
        pla
968
        rts
969
 
970
msgIOFocusList:
971
        db      CR,LF,"Task Prv Nxt",CR,LF,0
972 31 robfinch
 
973
RunningTCBErr:
974 34 robfinch
;       lda             #$FF
975
;       sta             LEDS
976 31 robfinch
        lda             #msgRunningTCB
977
        jsr             DisplayStringB
978
rtcberr1:
979
        jsr             KeybdGetChar
980
        cmp             #-1
981
        beq             rtcberr1
982
        jmp             start
983
 
984
msgRunningTCB:
985
        db      CR,LF,"RunningTCB is bad.",CR,LF,0
986
 
987 28 robfinch
;------------------------------------------------------------------------------
988 34 robfinch
; IdleTask
989
;
990 26 robfinch
; IdleTask is a low priority task that is always running. It runs when there
991
; is nothing else to run.
992 34 robfinch
; This task check for tasks that are stuck in infinite loops and kills them.
993 26 robfinch
;------------------------------------------------------------------------------
994
IdleTask:
995 34 robfinch
        stz             TestTask
996
it2:
997
        inc             TEXTSCR+111             ; increment IDLE active flag
998
        ldx             TestTask
999
        and             r2,r2,#$FF
1000
        beq             it1
1001
        lda             TCB_Status,x
1002
        cmp             #TS_SLEEP
1003
        bne             it1
1004
        txa
1005
        jsr             KillTask
1006
it1:
1007
        inc             TestTask
1008 26 robfinch
        cli                                             ; enable interrupts
1009
        wai                                             ; wait for one to happen
1010 34 robfinch
        bra             it2
1011 26 robfinch
 
1012
;------------------------------------------------------------------------------
1013 34 robfinch
; StartTask
1014
;
1015
; Startup a task. The task is automatically allocated a 1kW stack from the BIOS
1016
; stacks area. The scheduler is invoked after the task is added to the ready
1017
; list.
1018
;
1019
; Parameters:
1020
;       r1 = task priority
1021
;       r2 = start flags
1022
;       r3 = start address
1023 26 robfinch
;------------------------------------------------------------------------------
1024
message "StartTask"
1025
StartTask:
1026
        pha
1027
        phx
1028
        phy
1029
        push    r4
1030
        push    r5
1031
        push    r6
1032
        push    r7
1033
        push    r8
1034
        ld              r6,r1                           ; r6 = task priority
1035 34 robfinch
        ld              r8,r2                           ; r8 = flag register value on startup
1036 26 robfinch
 
1037
        ; get a free TCB
1038
        ;
1039 31 robfinch
        php
1040 26 robfinch
        sei
1041
        lda             FreeTCB                         ; get free tcb list pointer
1042
        bmi             stask1
1043
        tax
1044
        lda             TCB_NxtTCB,x
1045
        sta             FreeTCB                         ; update the FreeTCB list pointer
1046 31 robfinch
        plp
1047 34 robfinch
        txa                                                     ; acc = TCB index (task number)
1048 26 robfinch
 
1049
        ; setup the stack for the task
1050 34 robfinch
        ; Zap the stack memory.
1051 26 robfinch
        ld              r7,r2
1052
        asl             r2,r2,#10                       ; 1kW stack per task
1053 34 robfinch
        add             r2,r2,#BIOS_STACKS      ;+0x3ff ; add in stack base
1054
        pha
1055
        phx
1056
        phy
1057
        txy                                                     ; y = target address
1058
        ldx             #ExitTask                       ; x = fill value
1059
        lda             #$3FF                           ; acc = # words to fill -1
1060
        stos
1061
        ply
1062
        plx
1063
        pla
1064
 
1065
        add             r2,r2,#$3FF                     ; Move pointer to top of stack
1066
        php
1067
        tsr             sp,r4                           ; save off current stack pointer
1068
        sei
1069 26 robfinch
        txs
1070 34 robfinch
        ldx             #$1FF
1071 26 robfinch
        stx             TCB_SP8Save,r7
1072
        st              r6,TCB_Priority,r7
1073
        stz             TCB_Status,r7
1074
        stz             TCB_Timeout,r7
1075 31 robfinch
        ; setup virtual video for the task
1076
        stz             TCB_CursorRow,r7
1077
        stz             TCB_CursorCol,r7
1078 34 robfinch
        stz             TCB_mmu_map,r7          ; use mmu map #0
1079
        stz             TCB_ABS8Save,r7
1080 26 robfinch
 
1081
        ; setup the initial stack image for the task
1082
        ; Cause a return to the ExitTask routine when the task does a
1083
        ; final rts.
1084
        ; fake an IRQ call by stacking the return address and processor
1085
        ; flags on the stack
1086
        ldx             #ExitTask                       ; save the address of the task exit routine
1087
        phx
1088
        phy                                                     ; save start address on stack
1089
        push    r8                                      ; save processor status reg on stack
1090
 
1091
        ; now fake pushing the register set onto the stack. Registers start up
1092
        ; in an undefined state.
1093
        sub             sp,#15                          ; 15 registers
1094
        tsx
1095
        stx             TCB_SPSave,r7
1096
 
1097
        ; now restore the current stack pointer
1098
        trs             r4,sp
1099
 
1100
        ; Insert the task into the ready list
1101
        jsr             AddTaskToReadyList
1102 34 robfinch
        plp
1103
        int             #2              ; invoke the scheduler
1104 26 robfinch
stask2:
1105
        pop             r8
1106
        pop             r7
1107
        pop             r6
1108
        pop             r5
1109
        pop             r4
1110
        ply
1111
        plx
1112
        pla
1113
        rts
1114
stask1:
1115 31 robfinch
        plp
1116 26 robfinch
        lda             #msgNoTCBs
1117
        jsr             DisplayStringB
1118
        bra             stask2
1119
 
1120
msgNoTCBs:
1121
        db              "No more task control blocks available.",CR,LF,0
1122
 
1123
;------------------------------------------------------------------------------
1124 34 robfinch
; ExitTask
1125
;
1126 26 robfinch
; This routine is called when the task exits with an rts instruction. OR
1127 28 robfinch
; it may be invoked with a JMP ExitTask. In either case the task must be
1128 34 robfinch
; running so it can't be on the timeout list. The scheduler is invoked
1129
; after the task is removed from the ready list.
1130 26 robfinch
;------------------------------------------------------------------------------
1131
message "ExitTask"
1132
ExitTask:
1133
        sei
1134
        ; release any aquired resources
1135
        ; - mailboxes
1136
        ; - messages
1137 34 robfinch
        hoff
1138 26 robfinch
        lda             RunningTCB
1139 34 robfinch
        cmp             #MAX_TASKNO
1140
        bhi             xtsk1
1141 26 robfinch
        jsr             RemoveTaskFromReadyList
1142 34 robfinch
        jsr             RemoveFromTimeoutList
1143 26 robfinch
        stz             TCB_Status,r1                           ; set task status to TS_NONE
1144 28 robfinch
        jsr             ReleaseIOFocus
1145 34 robfinch
        ldx             #86
1146
        stx             LEDS
1147 28 robfinch
        ldx             FreeTCB                                         ; add the task control block to the free list
1148 26 robfinch
        stx             TCB_NxtTCB,r1
1149
        sta             FreeTCB
1150 34 robfinch
xtsk1:
1151 26 robfinch
        jmp             SelectTaskToRun
1152
 
1153
;------------------------------------------------------------------------------
1154 34 robfinch
; r1 = task number
1155
; r2 = new priority
1156
;------------------------------------------------------------------------------
1157
SetTaskPriority:
1158
        cmp             #MAX_TASKNO                                     ; make sure task number is reasonable
1159
        bhi             stp1
1160
        cpx             #5                                                      ; make sure priority is okay
1161
        bhs             stp1
1162
        phy
1163
        php
1164
        sei
1165
        ldy             TCB_Status,r1                           ; if the task is on the ready list
1166
        bit             r3,#TS_READY|TS_RUNNING         ; then remove it and re-add it.
1167
        beq             stp2                                            ; Otherwise just go set the priority field
1168
        jsr             RemoveTaskFromReadyList
1169
        stx             TCB_Priority,r1
1170
        jsr             AddTaskToReadyList
1171
        plp
1172
        ply
1173
stp1:
1174
        rts
1175
stp2:
1176
        stx             TCB_Priority,r1
1177
        plp
1178
        ply
1179
        rts
1180
 
1181
;------------------------------------------------------------------------------
1182 26 robfinch
; AddTaskToReadyList
1183 34 robfinch
;
1184
; The ready list is a group of five ready lists, one for each priority
1185
; level. Each ready list is organized as a doubly linked list to allow fast
1186
; insertions and removals. The list is organized as a ring (or bubble) with
1187
; the last entry pointing back to the first. This allows a fast task switch
1188
; to the next task. Which task is at the head of the list is maintained
1189
; in the variable QNdx for the priority level.
1190
;
1191
; Registers Affected: none
1192 26 robfinch
; Parameters:
1193 31 robfinch
;       r1 = task number
1194
; Returns:
1195
;       none
1196 26 robfinch
;------------------------------------------------------------------------------
1197 34 robfinch
;
1198 26 robfinch
message "AddTaskToReadyList"
1199
AddTaskToReadyList:
1200 31 robfinch
        php
1201 26 robfinch
        phx
1202
        phy
1203
        sei
1204 34 robfinch
        ldx             #TS_READY
1205
        stx             TCB_Status,r1
1206 31 robfinch
        ldy             TCB_Priority,r1
1207 34 robfinch
        ldx             QNdx0,y
1208
        bmi             arl5
1209
        ldy             TCB_PrvRdy,x
1210
        sta             TCB_NxtRdy,y
1211
        sty             TCB_PrvRdy,r1
1212
        sta             TCB_PrvRdy,x
1213
        stx             TCB_NxtRdy,r1
1214 26 robfinch
arl3:
1215
        ply
1216
        plx
1217 31 robfinch
        plp
1218 26 robfinch
        rts
1219
 
1220 34 robfinch
        ; Here the ready list was empty, so add at head
1221
arl5:
1222
        sta             QNdx0,y
1223
        sta             TCB_NxtRdy,r1
1224
        sta             TCB_PrvRdy,r1
1225
        ply
1226
        plx
1227
        plp
1228
        rts
1229
 
1230 26 robfinch
;------------------------------------------------------------------------------
1231
; RemoveTaskFromReadyList
1232 34 robfinch
;
1233 26 robfinch
; This subroutine removes a task from the ready list.
1234
;
1235 34 robfinch
; Registers Affected: none
1236
; Parameters:
1237
;       r1 = task number
1238
; Returns:
1239
;   r1 = task number
1240 26 robfinch
;------------------------------------------------------------------------------
1241 34 robfinch
 
1242 26 robfinch
message "RemoveTaskFromReadyList"
1243
RemoveTaskFromReadyList:
1244 31 robfinch
        php                                             ; save off interrupt mask state
1245 28 robfinch
        phx
1246 26 robfinch
        phy
1247
        push    r4
1248
        push    r5
1249
 
1250
        sei
1251 34 robfinch
        ldy             TCB_Status,r1   ; is the task on the ready list ?
1252
        bit             r3,#TS_READY|TS_RUNNING
1253
        beq             rfr2
1254
        stz             TCB_Status,r1           ; task status = TS_NONE
1255 26 robfinch
        ld              r4,TCB_NxtRdy,r1        ; Get previous and next fields.
1256 34 robfinch
        ld              r5,TCB_PrvRdy,r1
1257 26 robfinch
        st              r4,TCB_NxtRdy,r5
1258
        st              r5,TCB_PrvRdy,r4
1259
        ldy             TCB_Priority,r1
1260 34 robfinch
        cmp             r1,QNdx0,y                      ; Are we removing the QNdx task ?
1261
        bne             rfr2
1262
        st              r4,QNdx0,y
1263
        ; Now we test for the case where the task being removed was the only one
1264
        ; on the ready list of that priority level. We can tell because the
1265
        ; NxtRdy would point to the task itself.
1266
        cmp             r4,r1
1267
        bne             rfr2
1268
        ldx             #-1                                     ; Make QNdx negative
1269
        stx             QNdx0,y
1270
        stx             TCB_NxtRdy,r1
1271
        stx             TCB_PrvRdy,r1
1272 28 robfinch
rfr2:
1273 26 robfinch
        pop             r5
1274
        pop             r4
1275
        ply
1276 28 robfinch
        plx
1277 31 robfinch
        plp
1278 26 robfinch
        rts
1279 28 robfinch
 
1280 26 robfinch
;------------------------------------------------------------------------------
1281 28 robfinch
; AddToTimeoutList
1282
; AddToTimeoutList adds a task to the timeout list. The task is placed in the
1283
; list depending on it's timeout value.
1284
;
1285 34 robfinch
; Registers Affected: none
1286 28 robfinch
; Parameters:
1287
;       r1 = task
1288
;       r2 = timeout value
1289 26 robfinch
;------------------------------------------------------------------------------
1290
message "AddToTimeoutList"
1291
AddToTimeoutList:
1292 34 robfinch
        php
1293 26 robfinch
        phx
1294
        push    r4
1295
        push    r5
1296
        sei
1297
 
1298
        ld              r5,#-1
1299
        ld              r4,TimeoutList  ; are there any tasks on the timeout list ?
1300 34 robfinch
        cmp             r4,#MAX_TASKNO
1301
        bhi             attl1
1302 26 robfinch
attl_check_next:
1303
        sub             r2,r2,TCB_Timeout,r4    ; is this timeout > next
1304
        bmi             attl_insert_before
1305
        ld              r5,r4
1306
        ld              r4,TCB_NxtRdy,r4
1307 34 robfinch
        cmp             r4,#MAX_TASKNO
1308
        bls             attl_check_next
1309 26 robfinch
 
1310
        ; Here we scanned until the end of the timeout list and didn't find a
1311
        ; timeout of a greater value. So we add the task to the end of the list.
1312
attl_add_at_end:
1313
        st              r4,TCB_NxtRdy,r1        ; r4 was = -1
1314
        st              r1,TCB_NxtRdy,r5
1315
        st              r5,TCB_PrvRdy,r1
1316
        st              r2,TCB_Timeout,r1
1317
        bra             attl_exit
1318
 
1319
attl_insert_before:
1320 34 robfinch
        cmp             r5,#MAX_TASKNO
1321
        bhi             attl2
1322 26 robfinch
        st              r4,TCB_NxtRdy,r1        ; next on list goes after this task
1323
        st              r5,TCB_PrvRdy,r1        ; set previous link
1324
        st              r1,TCB_NxtRdy,r5
1325
        st              r1,TCB_PrvRdy,r4
1326
        bra             attl3
1327
 
1328
        ; Here there is no previous entry in the timeout list
1329
        ; Add at start
1330
attl2:
1331
        sta             TCB_PrvRdy,r4
1332
        st              r5,TCB_PrvRdy,r1        ; r5 = -1
1333
        st              r4,TCB_NxtRdy,r1
1334
        sta             TimeoutList             ; update the head pointer
1335
attl3:
1336
        add             r2,r2,TCB_Timeout,r4    ; get back timeout
1337
        stx             TCB_Timeout,r1
1338
        ld              r5,TCB_Timeout,r4       ; adjust the timeout of the next task
1339
        sub             r5,r5,r2
1340
        st              r5,TCB_Timeout,r4
1341
        bra             attl_exit
1342
 
1343
        ; Here there were no tasks on the timeout list, so we add at the
1344
        ; head of the list.
1345
attl1:
1346
        sta             TimeoutList             ; set the head of the timeout list
1347
        stx             TCB_Timeout,r1
1348
        ldx             #-1                             ; flag no more entries in timeout list
1349
        stx             TCB_NxtRdy,r1           ; no next entries
1350
        stx             TCB_PrvRdy,r1           ; and no prev entries
1351
attl_exit:
1352 34 robfinch
        ldx             #TS_TIMEOUT                     ; set the task's status as timing out
1353 28 robfinch
        stx             TCB_Status,r1
1354 26 robfinch
        pop             r5
1355
        pop             r4
1356
        plx
1357 34 robfinch
        plp
1358 26 robfinch
        rts
1359 34 robfinch
msgTimeout1:
1360
        db      CR,LF,"Adding to timeout list:",CR,LF,0
1361
 
1362 26 robfinch
;------------------------------------------------------------------------------
1363 34 robfinch
; RemoveFromTimeoutList
1364
;
1365 28 robfinch
; This subroutine is called from within the timer ISR when the task's
1366 34 robfinch
; timeout expires. It may also be called when a task is killed.
1367 26 robfinch
;
1368 34 robfinch
; Registers Affected: none
1369
; Parameters:
1370
;        r1 = task number
1371 26 robfinch
;------------------------------------------------------------------------------
1372
message "RemoveFromTimeoutList"
1373
RemoveFromTimeoutList:
1374 34 robfinch
        php
1375 26 robfinch
        phx
1376
        push    r4
1377
        push    r5
1378
        sei
1379
 
1380 34 robfinch
        ld              r4,TCB_Status,r1                ; Is the task even on the timeout list ?
1381
        bit             #TS_TIMEOUT
1382
        beq             rftl5
1383
        cmp             TimeoutList                             ; Are we removing the head of the list ?
1384
        beq             rftl2
1385 26 robfinch
        ld              r4,TCB_PrvRdy,r1                ; adjust the links of the next and previous
1386 34 robfinch
        bmi             rftl3                                   ; no previous link - list corrupt?
1387 26 robfinch
        ld              r5,TCB_NxtRdy,r1                ; tasks on the list to point around the task
1388
        st              r5,TCB_NxtRdy,r4
1389 34 robfinch
        bmi             rftl3
1390 26 robfinch
        st              r4,TCB_PrvRdy,r5
1391
        ldx             TCB_Timeout,r1                  ; update the timeout of the next on list
1392
        add             r2,r2,TCB_Timeout,r5    ; with any remaining timeout in the task
1393
        stx             TCB_Timeout,r5                  ; removed from the list
1394
        bra             rftl3
1395
 
1396 34 robfinch
        ; Update the head of the list.
1397 26 robfinch
rftl2:
1398
        ld              r5,TCB_NxtRdy,r1
1399
        st              r5,TimeoutList          ; store next field into list head
1400
        bmi             rftl3
1401 28 robfinch
        ld              r4,TCB_Timeout,r1               ; add any remaining timeout to the timeout
1402
        add             r4,r4,TCB_Timeout,r5    ; of the next task on the list.
1403
        st              r4,TCB_Timeout,r5
1404
        ld              r4,#-1                                  ; there is no previous item to the head
1405 26 robfinch
        sta             TCB_PrvRdy,r5
1406
 
1407
        ; Here there is no previous or next items in the list, so the list
1408
        ; will be empty once this task is removed from it.
1409
rftl3:
1410 34 robfinch
        stz             TCB_Status,r1           ; set the task status to TS_NONE
1411
        ldx             #-1                                     ; make sure the next and prev fields indicate
1412
        stx             TCB_NxtRdy,r1           ; the task is not on a list.
1413
        stx             TCB_PrvRdy,r1
1414
rftl5:
1415 26 robfinch
        pop             r5
1416
        pop             r4
1417
        plx
1418 34 robfinch
        plp
1419 26 robfinch
        rts
1420 28 robfinch
 
1421 26 robfinch
;------------------------------------------------------------------------------
1422 34 robfinch
; Sleep
1423
;
1424
; Put the currently running task to sleep for a specified time.
1425
;
1426
; Registers Affected: none
1427 28 robfinch
; Parameters:
1428 31 robfinch
; r1 = time duration in centi-seconds (1/100 second).
1429 28 robfinch
;------------------------------------------------------------------------------
1430
Sleep:
1431 34 robfinch
        php
1432
        pha
1433
        phx
1434 28 robfinch
        tax
1435
        sei
1436
        lda             RunningTCB
1437
        jsr             RemoveTaskFromReadyList
1438 34 robfinch
        jsr             AddToTimeoutList        ; The scheduler will be returning to this
1439
        int             #2                                      ; task eventually, once the timeout expires,
1440 28 robfinch
SleepRet:
1441 34 robfinch
        plx
1442
        pla
1443
        plp
1444 28 robfinch
        rts
1445
 
1446
;------------------------------------------------------------------------------
1447 34 robfinch
; KillTask
1448
;
1449
; "Kills" a task, removing it from all system lists. If the task has the
1450
; IO focus, the IO focus is switched. Task #0 is immortal and cannot be
1451
; killed.
1452
;
1453
; Registers Affected: none
1454
; Parameters:
1455
;       r1 = task number
1456
;------------------------------------------------------------------------------
1457
;
1458
KillTask:
1459
        php
1460
        phx
1461
        cmp             #1                                                      ; BIOS task and IDLE task are immortal
1462
        bls             kt1
1463
        cmp             #MAX_TASKNO
1464
        bhi             kt1
1465
        sei
1466
        jsr             ForceReleaseIOFocus
1467
        jsr             RemoveTaskFromReadyList
1468
        jsr             RemoveFromTimeoutList
1469
        stz             TCB_Status,r1                           ; set task status to TS_NONE
1470
        ldx             FreeTCB                                         ; add the task control block to the free list
1471
        stx             TCB_NxtTCB,r1
1472
        sta             FreeTCB
1473
        int             #2                                                      ; invoke scheduler to reschedule tasks
1474
kt1:
1475
        plx
1476
        plp
1477
        rts
1478
 
1479
;------------------------------------------------------------------------------
1480 26 robfinch
; Allocate a mailbox
1481
; r1 = pointer to place to store handle
1482
;------------------------------------------------------------------------------
1483
message "AllocMbx"
1484
AllocMbx:
1485
        cmp             #0
1486
        beq             ambx1
1487
        phx
1488
        phy
1489
        push    r4
1490
        ld              r4,r1
1491
        php
1492
        sei
1493
        lda             FreeMbx                 ; Get mailbox off of free mailbox list
1494
        sta             (r4)                    ; store off the mailbox number
1495
        bmi             ambx2
1496
        ldx             MBX_LINK,r1             ; and update the head of the list
1497
        stx             FreeMbx
1498
        dec             nMailbox                ; decrement number of available mailboxes
1499
        tax
1500
        ldy             RunningTCB                      ; set the mailbox owner
1501 31 robfinch
        bmi             RunningTCBErr
1502 26 robfinch
        lda             TCB_hJCB,y
1503
        sta             MBX_OWNER,x
1504
        lda             #-1                             ; initialize the head and tail of the queues
1505
        sta             MBX_TQ_HEAD,x
1506
        sta             MBX_TQ_TAIL,x
1507
        sta             MBX_MQ_HEAD,x
1508
        sta             MBX_MQ_TAIL,x
1509
        stz             MBX_TQ_COUNT,x  ; initialize counts to zero
1510
        stz             MBX_MQ_COUNT,x
1511
        stz             MBX_MQ_MISSED,x
1512
        lda             #8                              ; set the max queue size
1513
        sta             MBX_MQ_SIZE,x   ; and
1514
        lda             #MQS_NEWEST             ; queueing strategy
1515
        sta             MBX_MQ_STRATEGY,x
1516 31 robfinch
ambx3:
1517 26 robfinch
        plp
1518
        pop             r4
1519
        ply
1520
        plx
1521
        lda             #E_Ok
1522
        rts
1523
ambx1:
1524
        lda             #E_Arg
1525
        rts
1526
ambx2:
1527
        plp
1528
        pop             r4
1529
        ply
1530
        plx
1531
        lda             #E_NoMoreMbx
1532
        rts
1533
 
1534
;------------------------------------------------------------------------------
1535
; r1 = message
1536
; r2 = mailbox
1537
;------------------------------------------------------------------------------
1538
message "QueueMsgAtMbx"
1539
QueueMsgAtMbx:
1540
        pha
1541
        phx
1542
        phy
1543
        php
1544
        sei
1545
        ldy             MBX_MQ_TAIL,x
1546
        bmi             qmam1
1547
        sta             MBX_LINK,y
1548
        bra             qmam2
1549
qmam1:
1550
        sta             MBX_MQ_HEAD,x
1551
qmam2:
1552
        sta             MBX_MQ_TAIL,x
1553
        inc             MBX_MQ_COUNT,x          ; increase the queued message count
1554
        ldx             #-1
1555
        stx             MSG_LINK,r1
1556
        plp
1557
        ply
1558
        plx
1559
        pla
1560
        rts
1561
 
1562
;------------------------------------------------------------------------------
1563
; Returns
1564
; r1 = message number
1565
;------------------------------------------------------------------------------
1566
message "DequeueMsgFromMbx"
1567
DequeueMsgFromMbx:
1568
        phx
1569
        phy
1570
        php
1571
        sei
1572
        tax                                             ; x = mailbox index
1573
        lda             MBX_MQ_COUNT,x          ; are there any messages available ?
1574
        beq             dmfm1
1575
        dea
1576
        sta             MBX_MQ_COUNT,x          ; update the message count
1577
        lda             MBX_MQ_HEAD,x           ; Get the head of the list, this should not be -1
1578
        bmi             dmfm1                   ; since the message count > 0
1579
        ldy             MSG_LINK,r1             ; get the link to the next message
1580
        sty             MBX_MQ_HEAD,x           ; update the head of the list
1581
        bpl             dmfm2                   ; if there was no more messages then update the
1582
        sty             MBX_MQ_TAIL,x           ; tail of the list as well.
1583
dmfm2:
1584
        sta             MSG_LINK,r1             ; point the link to the messahe itself to indicate it's dequeued
1585
dmfm1:
1586
        plp
1587
        ply
1588
        plx
1589
        rts
1590
 
1591
;------------------------------------------------------------------------------
1592
;------------------------------------------------------------------------------
1593
DequeueThreadFromMbx:
1594
        cpx             #0
1595
        beq             dtfm1
1596
        php
1597
        sei
1598
        push    r4
1599
        ld              r4,MBX_TQ_HEAD,r1
1600
        bpl             dtfm2
1601
                pop             r4
1602
                stz             (x)
1603
                plp
1604
                lda             #E_NoThread
1605
                rts
1606
dtfm2:
1607
        push    r5
1608
        dec             MBX_TQ_COUNT,r1
1609
        st              r4,(x)
1610
        ld              r4,TCB_mbq_next,r4
1611
        st              r4,MBX_TQ_HEAD,r1
1612
        bmi             dtfm3
1613
                ld              r5,#-1
1614
                st              r5,TCB_mbq_prev,r4
1615
                bra             dtfm4
1616
dtfm3:
1617
                ld              r5,#-1
1618
                st              r5,MBX_TQ_TAIL,r1
1619
dtfm4:
1620
        stz             MBX_SEMA+1
1621
        ld              r5,(x)
1622
        lda             TCB_Status,r5
1623
        bit             #TS_TIMEOUT
1624
        beq             dtfm5
1625
                ld              r1,r5
1626
                jsr             RemoveFromTimeoutList
1627
dtfm5:
1628
        ld              r4,#-1
1629
        st              r4,TCB_mbq_next,r5
1630
        st              r4,TCB_mbq_prev,r5
1631
        stz             TCB_hWaitMbx,r5
1632 34 robfinch
        stz             TCB_Status,r5           ; set task status = TS_NONE
1633 26 robfinch
        pop             r5
1634
        pop             r4
1635
        plp
1636
        lda             #E_Ok
1637
        rts
1638
dtfm1:
1639
        lda             #E_Arg
1640
        rts
1641
 
1642
;------------------------------------------------------------------------------
1643
; r1 = handle to mailbox
1644
; r2 = message D1
1645
; r3 = message D2
1646
;------------------------------------------------------------------------------
1647
message "SendMsg"
1648
SendMsg:
1649 34 robfinch
        cmp             #2047                                   ; check the mailbox number to make sure
1650
        bhi             smsg1                                   ; that it's sensible
1651 26 robfinch
        push    r4
1652
        push    r5
1653
        push    r6
1654
        php
1655
        sei
1656
        ld              r4,MBX_OWNER,r1
1657
        bmi             smsg2                                   ; error: no owner
1658
        pha
1659
        phx
1660
        jsr             DequeueThreadFromMbx    ; r1=mbx, r2=thread (returned)
1661
        ld              r6,r2                                   ; r6 = thread
1662
        plx
1663
        pla
1664
        cmp             r6,#0
1665
        bpl             smsg3
1666
                ; Here there was no thread waiting at the mailbox, so a message needs to
1667
                ; be allocated
1668
                ld              r4,FreeMsg
1669
                bmi             smsg4           ; no more messages available
1670
                ld              r5,MSG_LINK,r4
1671
                st              r5,FreeMsg
1672
                dec             nMsgBlk         ; decrement the number of available messages
1673
                stx             MSG_D1,r4
1674
                sty             MSG_D2,r4
1675
                pha
1676
                phx
1677
                tax                                             ; x = mailbox
1678
                ld              r1,r4                   ; acc = message
1679
                jsr             QueueMsgAtMbx
1680
                plx
1681
                pla
1682
                cmp             r6,#0                   ; check if there is a thread waiting for a message
1683
                bmi             smsg5
1684
smsg3:
1685
        ld              r5,TCB_MSGPTR_D1,r6
1686
        beq             smsg6
1687
        stx             (r5)
1688
smsg6:
1689
        ld              r5,TCB_MSGPTR_D2,r6
1690
        beq             smsg7
1691
        sty             (r5)
1692
smsg7:
1693
        ld              r5,TCB_Status,r6
1694 34 robfinch
        bit             r5,#TS_TIMEOUT
1695 26 robfinch
        beq             smsg8
1696
        ld              r1,r6
1697
        jsr             RemoveFromTimeoutList
1698
smsg8:
1699
        ld              r1,r6
1700
        jsr             AddTaskToReadyList
1701 34 robfinch
        int             #2                      ; invoke the scheduler
1702 26 robfinch
smsg5:
1703
        plp
1704
        pop             r6
1705
        pop             r5
1706
        pop             r4
1707
        lda             #E_Ok
1708
        rts
1709
smsg1:
1710
        lda             #E_BadMbx
1711
        rts
1712
smsg2:
1713
        plp
1714
        pop             r6
1715
        pop             r5
1716
        pop             r4
1717
        lda             #E_NotAlloc
1718
        rts
1719
smsg4:
1720
        plp
1721
        pop             r6
1722
        pop             r5
1723
        pop             r4
1724
        lda             #E_NoMsg
1725
        rts
1726
 
1727
;------------------------------------------------------------------------------
1728
; WaitMsg
1729
; Wait at a mailbox for a message to arrive. This subroutine will block the
1730
; task until a message is available or the task times out on the timeout
1731
; list.
1732
;
1733
; Parameters
1734
;       r1=mailbox
1735
;       r2=pointer to D1
1736
;       r3=pointer to D2
1737
;       r4=timeout
1738
; Returns:
1739
;       r1=E_Ok                 if everything is ok
1740
;       r1=E_BadMbx             for a bad mailbox number
1741
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1742
;------------------------------------------------------------------------------
1743
WaitMsg:
1744 34 robfinch
        cmp             #2047                                   ; check the mailbox number to make sure
1745
        bhi             wmsg1                                   ; that it's sensible
1746 26 robfinch
        phx
1747
        phy
1748
        push    r4
1749
        push    r5
1750
        push    r6
1751
        push    r7
1752
        ld              r6,r1
1753
        php
1754
        sei
1755
        ld              r5,MBX_OWNER,r1
1756 34 robfinch
        cmp             r5,#MAX_TASKNO
1757
        bhi             wmsg2                                   ; error: no owner
1758 26 robfinch
        jsr             DequeueMsgFromMbx
1759
        cmp             #0
1760
        bpl             wmsg3
1761
 
1762
        ; Here there was no message available, remove the task from
1763
        ; the ready list, and optionally add it to the timeout list.
1764
        ; Queue the task at the mailbox.
1765
        lda             RunningTCB                              ; remove the task from the ready list
1766
        jsr             RemoveTaskFromReadyList
1767 34 robfinch
        ld              r7,#TS_WAITMSG                          ; set task status to waiting
1768 26 robfinch
        st              r7,TCB_Status,r1
1769
        st              r6,TCB_hWaitMbx,r1                      ; set which mailbox is waited for
1770
        ld              r7,#-1
1771
        st              r7,TCB_mbq_next,r1                      ; adding at tail, so there is no next
1772
        stx             TCB_MSGPTR_D1,r1                        ; save off the message pointers
1773
        sty             TCB_MSGPTR_D2,r1
1774
        ld              r7,MBX_TQ_HEAD,r1                       ; is there a task que setup at the mailbox ?
1775
        bmi             wmsg6
1776
        ld              r7,MBX_TQ_TAIL,r6
1777
        st              r7,TCB_mbq_prev,r1
1778
        sta             TCB_mbq_next,r7
1779
        sta             MBX_TQ_TAIL,r6
1780
        inc             MBX_TQ_COUNT,r6                         ; increment number of tasks queued
1781
wmsg7:
1782
        cmp             r4,#0                                           ; check for a timeout
1783
        beq             wmsg10
1784
        ld              r2,r4
1785
        jsr             AddToTimeoutList
1786
wmsg10:
1787 34 robfinch
        int             #2                      ; invoke the scheduler
1788 26 robfinch
 
1789
        ; Here there were no prior tasks queued at the mailbox
1790
wmsg6:
1791
        ld              r7,#-1
1792
        st              r7,TCB_mbq_prev,r1              ; no previous tasks
1793
        st              r7,TCB_mbq_next,r1
1794
        sta             MBX_TQ_HEAD,r6                  ; set both head and tail indexes
1795
        sta             MBX_TQ_TAIL,r6
1796
        ld              r7,#1
1797
        st              r7,MBX_TQ_COUNT,r6              ; one task queued
1798
        bra             wmsg7                                   ; check for a timeout value
1799
 
1800
        ; Store message D1 to pointer
1801
wmsg3:
1802
        cpx             #0
1803
        beq             wmsg4
1804
        ld              r7,MSG_D1,r1
1805
        st              r7,(x)
1806
        ; Store message D2 to pointer
1807
wmsg4:
1808
        cpy             #0
1809
        beq             wmsg5
1810
        ld              r7,MSG_D2,r1
1811
        st              r7,(y)
1812
        ; Add the newly dequeued message to the free messsage list
1813
wmsg5:
1814
        ld              r7,FreeMsg
1815
        st              r7,MSG_LINK,r1
1816
        sta             FreeMsg
1817
        inc             nMsgBlk
1818
wmsg8:
1819
        plp
1820
        pop             r7
1821
        pop             r6
1822
        pop             r5
1823
        pop             r4
1824
        ply
1825
        plx
1826
        lda             #E_Ok
1827
        rts
1828
wmsg1:
1829
        lda             #E_BadMbx
1830
        rts
1831
wmsg2:
1832
        plp
1833
        pop             r7
1834
        pop             r6
1835
        pop             r5
1836
        pop             r4
1837
        ply
1838
        plx
1839
        lda             #E_NotAlloc
1840
        rts
1841
 
1842
;------------------------------------------------------------------------------
1843
; CheckMsg
1844
; Check for a message at a mailbox. Does not block.
1845
;
1846
; Parameters
1847
;       r1=mailbox
1848
;       r2=pointer to D1
1849
;       r3=pointer to D2
1850
;       r4=remove from queue if present
1851
; Returns:
1852
;       r1=E_Ok                 if everything is ok
1853
;       r1=E_NoMsg              if no message is available
1854
;       r1=E_BadMbx             for a bad mailbox number
1855
;       r1=E_NotAlloc   for a mailbox that isn't allocated
1856
;------------------------------------------------------------------------------
1857
CheckMsg:
1858 34 robfinch
        cmp             #2047                                   ; check the mailbox number to make sure
1859
        bhi             cmsg1                                   ; that it's sensible
1860 26 robfinch
        phx
1861
        phy
1862
        push    r4
1863
        push    r5
1864
        php
1865
        sei
1866
        ld              r5,MBX_OWNER,r1
1867
        bmi             cmsg2                                   ; error: no owner
1868
        cmp             r4,#0                                   ; are we to dequeue the message ?
1869
        beq             cmsg3
1870
        jsr             DequeueMsgFromMbx
1871
        bra             cmsg4
1872
cmsg3:
1873 28 robfinch
        lda             MBX_MQ_HEAD,r1                  ; peek the message at the head of the messages queue
1874 26 robfinch
cmsg4:
1875
        cmp             #0
1876
        bmi             cmsg5
1877
        cpx             #0
1878
        beq             cmsg6
1879
        ld              r5,MSG_D1,r1
1880
        st              r5,(x)
1881
cmsg6:
1882
        cpy             #0
1883
        beq             cmsg7
1884
        ld              r5,MSG_D2,r1
1885
        st              r5,(y)
1886
cmsg7:
1887
        cmp             r4,#0
1888
        beq             cmsg8
1889
        ld              r5,FreeMsg
1890
        st              r5,MSG_LINK,r1
1891
        sta             FreeMsg
1892
        inc             nMsgBlk
1893
cmsg8:
1894
        plp
1895
        pop             r5
1896
        pop             r4
1897
        ply
1898
        plx
1899
        lda             #E_Ok
1900
        rts
1901
cmsg1:
1902
        lda             #E_BadMbx
1903
        rts
1904
cmsg2:
1905
        plp
1906
        pop             r5
1907
        pop             r4
1908
        ply
1909
        plx
1910
        lda             #E_NotAlloc
1911
        rts
1912
cmsg5:
1913
        plp
1914
        pop             r5
1915
        pop             r4
1916
        ply
1917
        plx
1918
        lda             #E_NoMsg
1919
        rts
1920
 
1921
;------------------------------------------------------------------------------
1922
;------------------------------------------------------------------------------
1923 34 robfinch
comment ~
1924 28 robfinch
SetIOFocusBit:
1925 31 robfinch
        and             r2,r2,#$FF
1926 28 robfinch
        and             r1,r2,#$1F              ; get bit index 0 to 31
1927
        ldy             #1
1928
        asl             r3,r3,r1                ; shift bit to proper place
1929
        lsr             r2,r2,#5                ; get word index /32 bits per word
1930
        lda             IOFocusTbl,x
1931
        or              r1,r1,r3
1932
        sta             IOFocusTbl,x
1933 26 robfinch
        rts
1934 34 robfinch
~
1935 26 robfinch
;------------------------------------------------------------------------------
1936
; The I/O focus list is an array indicating which tasks are requesting the
1937
; I/O focus. The I/O focus is user controlled by pressing ALT-TAB on the
1938
; keyboard.
1939
;------------------------------------------------------------------------------
1940
message "RequestIOFocus"
1941
RequestIOFocus:
1942
        pha
1943
        phx
1944
        phy
1945
        php
1946
        sei
1947 31 robfinch
        ldx             RunningTCB
1948 34 robfinch
        cpx             #MAX_TASKNO
1949
        bhi             riof1
1950 28 robfinch
        ldy             IOFocusNdx              ; Is the focus list empty ?
1951
        bmi             riof2
1952
riof4:
1953
        lda             TCB_iof_next,x  ; is the task already in the IO focus list ?
1954
        bpl             riof3
1955
        lda             IOFocusNdx              ; Expand the list
1956
        ldy             TCB_iof_prev,r1
1957
        stx             TCB_iof_prev,r1
1958
        sta             TCB_iof_next,x
1959
        sty             TCB_iof_prev,x
1960
        stx             TCB_iof_next,y
1961
riof3:
1962 34 robfinch
        txa
1963
        bms             IOFocusTbl
1964
;       jsr             SetIOFocusBit
1965
riof1:
1966 26 robfinch
        plp
1967
        ply
1968
        plx
1969
        pla
1970
        rts
1971 28 robfinch
 
1972
        ; Here, the IO focus list was empty. So expand it.
1973
        ; Update pointers to loop back to self.
1974
riof2:
1975
        stx             IOFocusNdx
1976
        stx             TCB_iof_next,x
1977
        stx             TCB_iof_prev,x
1978
        bra             riof3
1979
 
1980
;------------------------------------------------------------------------------
1981
; Releasing the I/O focus causes the focus to switch if the running task
1982
; had the I/O focus.
1983 34 robfinch
; ForceReleaseIOFocus forces the release of the IO focus for a task
1984
; different than the one currently running.
1985 28 robfinch
;------------------------------------------------------------------------------
1986 34 robfinch
;
1987
message "ForceReleaseIOFocus"
1988
ForceReleaseIOFocus:
1989
        php
1990
        pha
1991
        phx
1992
        phy
1993
        sei
1994
        tax
1995
        jmp             rliof4
1996 26 robfinch
message "ReleaseIOFocus"
1997
ReleaseIOFocus:
1998 34 robfinch
        php
1999 26 robfinch
        pha
2000
        phx
2001
        phy
2002
        sei
2003 28 robfinch
        ldx             RunningTCB
2004 34 robfinch
rliof4:
2005
        cpx             #MAX_TASKNO
2006
        bhi             rliof3
2007
;       phx
2008 28 robfinch
        ldy             #1
2009 34 robfinch
        txa
2010
        bmt             IOFocusTbl
2011
        beq             rliof3
2012
        bmc             IOFocusTbl
2013
comment ~
2014 26 robfinch
        and             r1,r2,#$1F              ; get bit index 0 to 31
2015
        asl             r3,r3,r1                ; shift bit to proper place
2016
        eor             r3,r3,#-1               ; invert bit mask
2017
        lsr             r2,r2,#5                ; get word index /32 bits per word
2018 28 robfinch
        lda             IOFocusTbl,x
2019 26 robfinch
        and             r1,r1,r3
2020 28 robfinch
        sta             IOFocusTbl,x
2021 34 robfinch
~
2022
;       plx
2023 28 robfinch
        cpx             IOFocusNdx              ; Does the running task have the I/O focus ?
2024
        bne             rliof1
2025
        jsr             SwitchIOFocus   ; If so, then switch the focus.
2026
rliof1:
2027
        lda             TCB_iof_next,x  ; get next and previous fields.
2028
        bmi             rliof2                  ; Is the task on the list ?
2029
        ldy             TCB_iof_prev,x
2030
        sta             TCB_iof_next,y  ; prev->next = current->next
2031
        sty             TCB_iof_prev,r1 ; next->prev = current->prev
2032
        cmp             r1,r3                   ; Check if the IO focus list is collapsing.
2033
        bne             rliof2                  ; If the list just points back to the task
2034
        cmp             r1,r2                   ; being removed, then it's the last task
2035
        bne             rliof2                  ; removed from the list, so the list is being
2036
        lda             #-1                             ; emptied.
2037
        sta             IOFocusNdx
2038
rliof2:
2039
        lda             #-1                             ; Update the next and prev fields to indicate
2040
        sta             TCB_iof_next,x  ; the task is no longer on the list.
2041
        sta             TCB_iof_prev,x
2042 31 robfinch
rliof3:
2043 26 robfinch
        ply
2044
        plx
2045
        pla
2046 34 robfinch
        plp
2047 26 robfinch
        rts
2048
 
2049
;------------------------------------------------------------------------------
2050 31 robfinch
; Get the location of the screen and screen attribute memory. The location
2051
; depends on whether or not the task has the output focus.
2052 26 robfinch
;------------------------------------------------------------------------------
2053
GetScreenLocation:
2054
        lda             RunningTCB
2055 28 robfinch
        cmp             IOFocusNdx
2056 26 robfinch
        beq             gsl1
2057 31 robfinch
        and             r1,r1,#$FF
2058 26 robfinch
        asl             r1,r1,#13                       ; 8192 words per screen
2059
        add             r1,r1,#BIOS_SCREENS
2060
        rts
2061
gsl1:
2062
        lda             #TEXTSCR
2063
        rts
2064
 
2065
GetColorCodeLocation:
2066
        lda             RunningTCB
2067 28 robfinch
        cmp             IOFocusNdx
2068 26 robfinch
        beq             gccl1
2069 31 robfinch
        and             r1,r1,#$FF
2070 26 robfinch
        asl             r1,r1,#13                       ; 8192 words per screen
2071
        add             r1,r1,#BIOS_SCREENS+4096
2072
        rts
2073
gccl1:
2074
        lda             #TEXTSCR+$10000
2075
        rts
2076
 
2077
;------------------------------------------------------------------------------
2078
;------------------------------------------------------------------------------
2079
message "CopyVirtualScreenToScreen"
2080
CopyVirtualScreenToScreen
2081
        pha
2082
        phx
2083
        phy
2084 28 robfinch
        push    r4
2085 26 robfinch
        lda             #4095                           ; number of words to copy-1
2086 28 robfinch
        ldx             IOFocusNdx                      ; compute virtual screen location
2087
        bmi             cvss3
2088 26 robfinch
        asl             r2,r2,#13                       ; 8192 words per screen
2089
        add             r2,r2,#BIOS_SCREENS     ; add in screens array base address
2090
        ldy             #TEXTSCR
2091 31 robfinch
        mvn
2092
;cvss1:
2093
;       ld              r4,(x)
2094
;       st              r4,(y)
2095
;       inx
2096
;       iny
2097
;       dea
2098
;       bne             cvss1
2099 26 robfinch
        ; now copy the color codes
2100
        lda             #4095
2101 28 robfinch
        ldx             IOFocusNdx
2102 26 robfinch
        asl             r2,r2,#13
2103
        add             r2,r2,#BIOS_SCREENS+4096        ; virtual char color array
2104
        ldy             #TEXTSCR+$10000
2105 31 robfinch
        mvn
2106
;cvss2:
2107
;       ld              r4,(x)
2108
;       st              r4,(y)
2109
;       inx
2110
;       iny
2111
;       dea
2112
;       bne             cvss2
2113 28 robfinch
cvss3:
2114
        ; reset the cursor position in the text controller
2115
        ldy             IOFocusNdx
2116
        ldx             TCB_CursorRow,y
2117
        lda             TEXTREG+TEXT_COLS
2118
        mul             r2,r2,r1
2119
        add             r2,r2,TCB_CursorCol,y
2120
        stx             TEXTREG+TEXT_CURPOS
2121
        pop             r4
2122 26 robfinch
        ply
2123
        plx
2124
        pla
2125
        rts
2126
message "CopyScreenToVirtualScreen"
2127
CopyScreenToVirtualScreen
2128
        pha
2129
        phx
2130
        phy
2131 28 robfinch
        push    r4
2132 26 robfinch
        lda             #4095
2133
        ldx             #TEXTSCR
2134 28 robfinch
        ldy             IOFocusNdx
2135
        bmi             csvs3
2136 26 robfinch
        asl             r3,r3,#13
2137
        add             r3,r3,#BIOS_SCREENS
2138 31 robfinch
        mvn
2139
;csvs1:
2140
;       ld              r4,(x)
2141
;       st              r4,(y)
2142
;       inx
2143
;       iny
2144
;       dea
2145
;       bne             csvs1
2146 26 robfinch
        lda             #4095
2147
        ldx             #TEXTSCR+$10000
2148 28 robfinch
        ldy             IOFocusNdx
2149 26 robfinch
        asl             r3,r3,#13
2150
        add             r3,r3,#BIOS_SCREENS+4096
2151 31 robfinch
        mvn
2152
;csvs2:
2153
;       ld              r4,(x)
2154
;       st              r4,(y)
2155
;       inx
2156
;       iny
2157
;       dea
2158
;       bne             csvs2
2159 28 robfinch
csvs3:
2160
        pop             r4
2161 26 robfinch
        ply
2162
        plx
2163
        pla
2164
        rts
2165
 
2166
;------------------------------------------------------------------------------
2167 11 robfinch
; Clear the screen and the screen color memory
2168
; We clear the screen to give a visual indication that the system
2169
; is working at all.
2170
;------------------------------------------------------------------------------
2171
;
2172 26 robfinch
message "ClearScreen"
2173 11 robfinch
ClearScreen:
2174
        pha                                                     ; holds a space character
2175
        phx                                                     ; loop counter
2176
        phy                                                     ; memory addressing
2177
        lda             TEXTREG+TEXT_COLS       ; calc number to clear
2178
        ldx             TEXTREG+TEXT_ROWS
2179 34 robfinch
        mul             r1,r1,r2                        ; r1 = # chars to clear
2180
        pha
2181 26 robfinch
        jsr             GetScreenLocation
2182 34 robfinch
        tay                                                     ; y = target address
2183 11 robfinch
        lda             #' '                            ; space char
2184
        jsr             AsciiToScreen
2185 34 robfinch
        tax                                                     ; x is value to store
2186
        pla                                                     ; a is count
2187
        pha
2188
        stos                                            ; clear the memory
2189
        ld              r2,ScreenColor          ; x = value to use
2190
        jsr             GetColorCodeLocation
2191
        tay                                                     ; y = targte address
2192
        pla                                                     ; a = count
2193
        stos
2194 11 robfinch
        ply
2195
        plx
2196
        pla
2197
        rts
2198
 
2199
;------------------------------------------------------------------------------
2200
; Scroll text on the screen upwards
2201
;------------------------------------------------------------------------------
2202
;
2203 26 robfinch
message "ScrollUp"
2204 11 robfinch
ScrollUp:
2205
        pha
2206
        phx
2207
        phy
2208
        push    r4
2209
        push    r5
2210 26 robfinch
        push    r6
2211 11 robfinch
        lda             TEXTREG+TEXT_COLS       ; acc = # text columns
2212
        ldx             TEXTREG+TEXT_ROWS
2213
        mul             r2,r1,r2                        ; calc number of chars to scroll
2214
        sub             r2,r2,r1                        ; one less row
2215 26 robfinch
        pha
2216
        jsr             GetScreenLocation
2217
        tay
2218
        jsr             GetColorCodeLocation
2219
        ld              r6,r1
2220
        pla
2221 11 robfinch
scrup1:
2222
        add             r5,r3,r1
2223
        ld              r4,(r5)                         ; move character
2224
        st              r4,(y)
2225 26 robfinch
        add             r5,r6,r1
2226
        ld              r4,(r5)                         ; and move color code
2227
        st              r4,(r6)
2228 11 robfinch
        iny
2229 26 robfinch
        inc             r6
2230 11 robfinch
        dex
2231
        bne             scrup1
2232
        lda             TEXTREG+TEXT_ROWS
2233
        dea
2234
        jsr             BlankLine
2235 26 robfinch
        pop             r6
2236 11 robfinch
        pop             r5
2237
        pop             r4
2238
        ply
2239
        plx
2240
        pla
2241
        rts
2242
 
2243
;------------------------------------------------------------------------------
2244
; Blank out a line on the display
2245
; line number to blank is in acc
2246
;------------------------------------------------------------------------------
2247
;
2248
BlankLine:
2249
        pha
2250
        phx
2251
        phy
2252 26 robfinch
        push    r4
2253 11 robfinch
        ldx             TEXTREG+TEXT_COLS       ; x = # chars to blank out from video controller
2254
        mul             r3,r2,r1                        ; y = screen index (row# * #cols)
2255 26 robfinch
        pha
2256
        jsr             GetScreenLocation
2257
        ld              r4,r1
2258
        pla
2259
        add             r3,r3,r4                ; y = screen address
2260 11 robfinch
        lda             #' '
2261 26 robfinch
        jsr             AsciiToScreen
2262 11 robfinch
blnkln1:
2263
        sta             (y)
2264
        iny
2265
        dex
2266
        bne             blnkln1
2267 26 robfinch
        pop             r4
2268 11 robfinch
        ply
2269
        plx
2270
        pla
2271
        rts
2272
 
2273
;------------------------------------------------------------------------------
2274
; Convert ASCII character to screen display character.
2275
;------------------------------------------------------------------------------
2276
;
2277
AsciiToScreen:
2278
        and             #$FF
2279
        cmp             #'A'
2280
        bcc             atoscr1         ; blt
2281
        cmp             #'Z'
2282
        bcc             atoscr1
2283
        beq             atoscr1
2284 15 robfinch
        cmp             #'z'+1
2285 11 robfinch
        bcs             atoscr1
2286
        cmp             #'a'
2287
        bcc             atoscr1
2288
        sub             #$60
2289
atoscr1:
2290
        or              #$100
2291
        rts
2292
 
2293
;------------------------------------------------------------------------------
2294
; Convert screen character to ascii character
2295
;------------------------------------------------------------------------------
2296
;
2297
ScreenToAscii:
2298
        and             #$FF
2299 15 robfinch
        cmp             #26+1
2300 11 robfinch
        bcs             stasc1
2301
        add             #$60
2302
stasc1:
2303
        rts
2304
 
2305
;------------------------------------------------------------------------------
2306 26 robfinch
; HomeCursor
2307
; Set the cursor location to the top left of the screen.
2308
;------------------------------------------------------------------------------
2309
HomeCursor:
2310
        phx
2311
        ldx             RunningTCB
2312 31 robfinch
        and             r2,r2,#$FF
2313 26 robfinch
        stz             TCB_CursorRow,x
2314
        stz             TCB_CursorCol,x
2315 31 robfinch
        cpx             IOFocusNdx
2316
        bne             hc1
2317
        stz             TEXTREG+TEXT_CURPOS
2318
hc1:
2319 26 robfinch
        plx
2320
        rts
2321
 
2322
;------------------------------------------------------------------------------
2323 31 robfinch
; Update the cursor position in the text controller based on the
2324
;  CursorRow,CursorCol.
2325
;------------------------------------------------------------------------------
2326
;
2327
UpdateCursorPos:
2328
        pha
2329
        phx
2330
        push    r4
2331
        ld              r4,RunningTCB
2332
        and             r4,r4,#$FF
2333
        cmp             r4,IOFocusNdx                   ; update cursor position in text controller
2334
        bne             ucp1                                    ; only for the task with the output focus
2335
        lda             TCB_CursorRow,r4
2336
        and             #$3F                                    ; limit of 63 rows
2337
        ldx             TEXTREG+TEXT_COLS
2338
        mul             r2,r2,r1
2339
        lda             TCB_CursorCol,r4
2340
        and             #$7F                                    ; limit of 127 cols
2341
        add             r2,r2,r1
2342
        stx             TEXTREG+TEXT_CURPOS
2343
ucp1:
2344
        pop             r4
2345
        plx
2346
        pla
2347
        rts
2348
 
2349
;------------------------------------------------------------------------------
2350 11 robfinch
; Calculate screen memory location from CursorRow,CursorCol.
2351
; Also refreshes the cursor location.
2352
; Returns:
2353
; r1 = screen location
2354
;------------------------------------------------------------------------------
2355
;
2356
CalcScreenLoc:
2357
        phx
2358 26 robfinch
        push    r4
2359
        ld              r4,RunningTCB
2360 31 robfinch
        and             r4,r4,#$FF
2361 26 robfinch
        lda             TCB_CursorRow,r4
2362 31 robfinch
        and             #$3F                                    ; limit to 63 rows
2363 11 robfinch
        ldx             TEXTREG+TEXT_COLS
2364
        mul             r2,r2,r1
2365 31 robfinch
        ld              r1,TCB_CursorCol,r4
2366
        and             #$7F                                    ; limit to 127 cols
2367
        add             r2,r2,r1
2368 28 robfinch
        cmp             r4,IOFocusNdx                   ; update cursor position in text controller
2369 26 robfinch
        bne             csl1                                    ; only for the task with the output focus
2370 11 robfinch
        stx             TEXTREG+TEXT_CURPOS
2371 26 robfinch
csl1:
2372
        jsr             GetScreenLocation
2373
        add             r1,r2,r1
2374 31 robfinch
        pop             r4
2375
        plx
2376
        rts
2377 26 robfinch
csl2:
2378 31 robfinch
        lda             #TEXTSCR
2379 26 robfinch
        pop             r4
2380 11 robfinch
        plx
2381
        rts
2382
 
2383
;------------------------------------------------------------------------------
2384 26 robfinch
; Display a character on the screen.
2385
; If the task doesn't have the I/O focus then the character is written to
2386
; the virtual screen.
2387 11 robfinch
; r1 = char to display
2388
;------------------------------------------------------------------------------
2389
;
2390 26 robfinch
message "DisplayChar"
2391 11 robfinch
DisplayChar:
2392 26 robfinch
        push    r4
2393
        ld              r4,RunningTCB
2394 31 robfinch
        and             r4,r4,#$FF
2395 26 robfinch
        and             #$FF                            ; mask off any higher order bits (called from eight bit mode).
2396 11 robfinch
        cmp             #'\r'                           ; carriage return ?
2397
        bne             dccr
2398 26 robfinch
        stz             TCB_CursorCol,r4        ; just set cursor column to zero on a CR
2399 31 robfinch
        jsr             UpdateCursorPos
2400
dcx14:
2401 26 robfinch
        pop             r4
2402 11 robfinch
        rts
2403
dccr:
2404
        cmp             #$91                            ; cursor right ?
2405
        bne             dcx6
2406
        pha
2407 26 robfinch
        lda             TCB_CursorCol,r4
2408 34 robfinch
        cmp             #55
2409 11 robfinch
        bcs             dcx7
2410
        ina
2411 26 robfinch
        sta             TCB_CursorCol,r4
2412 11 robfinch
dcx7:
2413 31 robfinch
        jsr             UpdateCursorPos
2414 11 robfinch
        pla
2415 26 robfinch
        pop             r4
2416 11 robfinch
        rts
2417
dcx6:
2418
        cmp             #$90                            ; cursor up ?
2419
        bne             dcx8
2420
        pha
2421 26 robfinch
        lda             TCB_CursorRow,r4
2422 11 robfinch
        beq             dcx7
2423
        dea
2424 26 robfinch
        sta             TCB_CursorRow,r4
2425 11 robfinch
        bra             dcx7
2426
dcx8:
2427
        cmp             #$93                            ; cursor left ?
2428
        bne             dcx9
2429
        pha
2430 26 robfinch
        lda             TCB_CursorCol,r4
2431 11 robfinch
        beq             dcx7
2432
        dea
2433 26 robfinch
        sta             TCB_CursorCol,r4
2434 11 robfinch
        bra             dcx7
2435
dcx9:
2436
        cmp             #$92                            ; cursor down ?
2437
        bne             dcx10
2438
        pha
2439 26 robfinch
        lda             TCB_CursorRow,r4
2440 11 robfinch
        cmp             #46
2441
        beq             dcx7
2442
        ina
2443 26 robfinch
        sta             TCB_CursorRow,r4
2444 11 robfinch
        bra             dcx7
2445
dcx10:
2446
        cmp             #$94                            ; cursor home ?
2447
        bne             dcx11
2448
        pha
2449 26 robfinch
        lda             TCB_CursorCol,r4
2450 11 robfinch
        beq             dcx12
2451 26 robfinch
        stz             TCB_CursorCol,r4
2452 11 robfinch
        bra             dcx7
2453
dcx12:
2454 26 robfinch
        stz             TCB_CursorRow,r4
2455 11 robfinch
        bra             dcx7
2456
dcx11:
2457
        pha
2458
        phx
2459
        phy
2460
        cmp             #$99                            ; delete ?
2461
        bne             dcx13
2462
        jsr             CalcScreenLoc
2463
        tay                                                     ; y = screen location
2464 26 robfinch
        lda             TCB_CursorCol,r4        ; acc = cursor column
2465 11 robfinch
        bra             dcx5
2466
dcx13
2467
        cmp             #CTRLH                          ; backspace ?
2468
        bne             dcx3
2469 26 robfinch
        lda             TCB_CursorCol,r4
2470 11 robfinch
        beq             dcx4
2471
        dea
2472 26 robfinch
        sta             TCB_CursorCol,r4
2473 11 robfinch
        jsr             CalcScreenLoc           ; acc = screen location
2474
        tay                                                     ; y = screen location
2475 26 robfinch
        lda             TCB_CursorCol,r4
2476 11 robfinch
dcx5:
2477
        ldx             $4,y
2478
        stx             (y)
2479
        iny
2480
        ina
2481
        cmp             TEXTREG+TEXT_COLS
2482
        bcc             dcx5
2483
        lda             #' '
2484
        jsr             AsciiToScreen
2485
        dey
2486
        sta             (y)
2487
        bra             dcx4
2488
dcx3:
2489
        cmp             #'\n'                   ; linefeed ?
2490
        beq             dclf
2491
        tax                                             ; save acc in x
2492
        jsr     CalcScreenLoc   ; acc = screen location
2493
        tay                                             ; y = screen location
2494
        txa                                             ; restore r1
2495
        jsr             AsciiToScreen   ; convert ascii char to screen char
2496
        sta             (y)
2497 26 robfinch
        jsr             GetScreenLocation
2498
        sub             r3,r3,r1                ; make y an index into the screen
2499
        jsr             GetColorCodeLocation
2500
        add             r3,r3,r1
2501 11 robfinch
        lda             CharColor
2502 26 robfinch
        sta             (y)
2503 11 robfinch
        jsr             IncCursorPos
2504
        bra             dcx4
2505
dclf:
2506
        jsr             IncCursorRow
2507
dcx4:
2508
        ply
2509
        plx
2510
        pla
2511 26 robfinch
        pop             r4
2512 11 robfinch
        rts
2513
 
2514
;------------------------------------------------------------------------------
2515
; Increment the cursor position, scroll the screen if needed.
2516
;------------------------------------------------------------------------------
2517
;
2518
IncCursorPos:
2519
        pha
2520
        phx
2521 26 robfinch
        push    r4
2522
        ld              r4,RunningTCB
2523 31 robfinch
        and             r4,r4,#$FF
2524 26 robfinch
        lda             TCB_CursorCol,r4
2525 11 robfinch
        ina
2526 26 robfinch
        sta             TCB_CursorCol,r4
2527 11 robfinch
        ldx             TEXTREG+TEXT_COLS
2528
        cmp             r1,r2
2529
        bcc             icc1
2530 26 robfinch
        stz             TCB_CursorCol,r4                ; column = 0
2531 11 robfinch
        bra             icr1
2532
IncCursorRow:
2533
        pha
2534
        phx
2535 26 robfinch
        push    r4
2536
        ld              r4,RunningTCB
2537 31 robfinch
        and             r4,r4,#$FF
2538 11 robfinch
icr1:
2539 26 robfinch
        lda             TCB_CursorRow,r4
2540 11 robfinch
        ina
2541 26 robfinch
        sta             TCB_CursorRow,r4
2542 11 robfinch
        ldx             TEXTREG+TEXT_ROWS
2543
        cmp             r1,r2
2544
        bcc             icc1
2545
        beq             icc1
2546
        dex                                                     ; backup the cursor row, we are scrolling up
2547 26 robfinch
        stx             TCB_CursorRow,r4
2548 11 robfinch
        jsr             ScrollUp
2549
icc1:
2550 31 robfinch
        jsr             UpdateCursorPos
2551
icc2:
2552 26 robfinch
        pop             r4
2553 11 robfinch
        plx
2554
        pla
2555
        rts
2556
 
2557
;------------------------------------------------------------------------------
2558
; Display a string on the screen.
2559
; The characters are packed 4 per word
2560
;------------------------------------------------------------------------------
2561
;
2562
DisplayStringB:
2563
        pha
2564
        phx
2565
        tax                                             ; r2 = pointer to string
2566
dspj1B:
2567 15 robfinch
        lb              r1,0,x                  ; move string char into acc
2568 11 robfinch
        inx                                             ; increment pointer
2569
        cmp             #0                              ; is it end of string ?
2570
        beq             dsretB
2571
        jsr             DisplayChar             ; display character
2572 15 robfinch
        bra             dspj1B
2573 11 robfinch
dsretB:
2574
        plx
2575
        pla
2576
        rts
2577
 
2578 31 robfinch
DisplayStringQ:
2579
        pha
2580
        phx
2581
        tax                                             ; r2 = pointer to string
2582
        lda             #TEXTSCR
2583
        sta             QIndex
2584
dspj1Q:
2585
        lb              r1,0,x                  ; move string char into acc
2586
        inx                                             ; increment pointer
2587
        cmp             #0                              ; is it end of string ?
2588
        beq             dsretQ
2589
        jsr             DisplayCharQ    ; display character
2590
        bra             dspj1Q
2591
dsretQ:
2592
        plx
2593
        pla
2594
        rts
2595
 
2596
DisplayCharQ:
2597
        pha
2598
        phx
2599
        jsr             AsciiToScreen
2600
        ldx             #0
2601
        sta             (QIndex,x)
2602
        lda             QIndex
2603
        ina
2604
        sta             QIndex
2605
;       inc             QIndex
2606
        plx
2607
        pla
2608
        rts
2609
 
2610
 
2611 11 robfinch
;------------------------------------------------------------------------------
2612
; Display a string on the screen.
2613
; The characters are packed 1 per word
2614
;------------------------------------------------------------------------------
2615
;
2616
DisplayStringW:
2617
        pha
2618
        phx
2619
        tax                                             ; r2 = pointer to string
2620
dspj1W:
2621
        lda             (x)                             ; move string char into acc
2622
        inx                                             ; increment pointer
2623
        cmp             #0                              ; is it end of string ?
2624
        beq             dsretW
2625
        jsr             DisplayChar             ; display character
2626
        bra             dspj1W                  ; go back for next character
2627
dsretW:
2628
        plx
2629
        pla
2630
        rts
2631
 
2632
DisplayStringCRLFB:
2633
        jsr             DisplayStringB
2634
CRLF:
2635
        pha
2636
        lda             #'\r'
2637
        jsr             DisplayChar
2638
        lda             #'\n'
2639
        jsr             DisplayChar
2640
        pla
2641
        rts
2642
 
2643
;------------------------------------------------------------------------------
2644 15 robfinch
; Initialize keyboard
2645
;
2646
; Issues a 'reset keyboard' command to the keyboard, then selects scan code
2647
; set #2 (the most common one). Also sets up the keyboard buffer and
2648
; initializes the keyboard semaphore.
2649
;------------------------------------------------------------------------------
2650
;
2651 26 robfinch
message "KeybdInit"
2652 15 robfinch
KeybdInit:
2653
        lda             #1                      ; setup semaphore
2654 26 robfinch
        sta             KEYBD_SEMA
2655 31 robfinch
        lda             #32
2656
        sta             LEDS
2657 26 robfinch
        ldx             #0
2658 31 robfinch
 
2659 34 robfinch
        lda             #MAX_TASKNO
2660
        ldx             #0
2661
        ldy             #KeybdHead
2662
        stos
2663
        lda             #MAX_TASKNO
2664
        ldy             #KeybdTail
2665
        stos
2666
        lda             #MAX_TASKNO
2667
        ldy             #KeybdBad
2668
        stos
2669
        lda             #MAX_TASKNO
2670
        ldx             #1                              ; turn on keyboard echo
2671
        ldy             #KeybdEcho
2672
        stos
2673
 
2674 31 robfinch
        lda             PIC_IE
2675
        or              r1,r1,#$8000            ; enable kbd_irq
2676
        sta             PIC_IE
2677
 
2678
        lda             #33
2679
        sta             LEDS
2680 15 robfinch
        lda             #$ff            ; issue keyboard reset
2681
        jsr             SendByteToKeybd
2682 31 robfinch
        lda             #38
2683
        sta             LEDS
2684 15 robfinch
        lda             #1000000                ; delay a bit
2685
kbdi5:
2686
        dea
2687 31 robfinch
        sta             LEDS
2688 15 robfinch
        bne             kbdi5
2689 31 robfinch
        lda             #34
2690
        sta             LEDS
2691 15 robfinch
        lda             #0xf0           ; send scan code select
2692
        jsr             SendByteToKeybd
2693 31 robfinch
        lda             #35
2694
        sta             LEDS
2695 15 robfinch
        ldx             #0xFA
2696
        jsr             WaitForKeybdAck
2697
        cmp             #$FA
2698
        bne             kbdi2
2699 31 robfinch
        lda             #36
2700
        sta             LEDS
2701 15 robfinch
        lda             #2                      ; select scan code set#2
2702
        jsr             SendByteToKeybd
2703 31 robfinch
        lda             #39
2704
        sta             LEDS
2705 15 robfinch
kbdi2:
2706
        rts
2707
 
2708
msgBadKeybd:
2709
        db              "Keyboard not responding.",0
2710
 
2711
SendByteToKeybd:
2712 26 robfinch
        phx
2713
        ldx             RunningTCB
2714 15 robfinch
        sta             KEYBD
2715 31 robfinch
        lda             #40
2716
        sta             LEDS
2717 15 robfinch
        tsr             TICK,r3
2718
kbdi4:                                          ; wait for transmit complete
2719
        tsr             TICK,r4
2720
        sub             r4,r4,r3
2721
        cmp             r4,#1000000
2722
        bcs             kbdbad
2723 31 robfinch
        lda             #41
2724
        sta             LEDS
2725 15 robfinch
        lda             KEYBD+3
2726
        bit             #64
2727
        beq             kbdi4
2728
        bra             sbtk1
2729
kbdbad:
2730 31 robfinch
        lda             #42
2731
        sta             LEDS
2732 26 robfinch
        lda             KeybdBad,x
2733 15 robfinch
        bne             sbtk1
2734
        lda             #1
2735 26 robfinch
        sta             KeybdBad,x
2736 31 robfinch
        lda             #43
2737
        sta             LEDS
2738 15 robfinch
        lda             #msgBadKeybd
2739
        jsr             DisplayStringCRLFB
2740
sbtk1:
2741 31 robfinch
        lda             #44
2742
        sta             LEDS
2743 26 robfinch
        plx
2744 15 robfinch
        rts
2745
 
2746
; Wait for keyboard to respond with an ACK (FA)
2747
;
2748
WaitForKeybdAck:
2749 31 robfinch
        lda             #64
2750
        sta             LEDS
2751 15 robfinch
        tsr             TICK,r3
2752
wkbdack1:
2753
        tsr             TICK,r4
2754
        sub             r4,r4,r3
2755
        cmp             r4,#1000000
2756
        bcs             wkbdbad
2757 31 robfinch
        lda             #65
2758
        sta             LEDS
2759 15 robfinch
        lda             KEYBD
2760
        bit             #$8000
2761
        beq             wkbdack1
2762
;       lda             KEYBD+8
2763
        and             #$ff
2764
wkbdbad:
2765
        rts
2766
 
2767
; Wait for keyboard to respond with an ACK (FA)
2768
; This routine picks up the ack status left by the
2769
; keyboard IRQ routine.
2770
; r2 = 0xFA (could also be 0xEE for echo command)
2771
;
2772
WaitForKeybdAck2:
2773 26 robfinch
        phx
2774
        ldx             RunningTCB
2775
WaitForKeybdAck2a:
2776
        lda             KeybdAck,x
2777 15 robfinch
        cmp             r1,r2
2778 26 robfinch
        bne             WaitForKeybdAck2a
2779
        stz             KeybdAck,x
2780
        plx
2781 15 robfinch
        rts
2782
 
2783
;------------------------------------------------------------------------------
2784 34 robfinch
; KeybdIRQ
2785
;
2786 15 robfinch
; Normal keyboard interrupt, the lowest priority interrupt in the system.
2787
; Grab the character from the keyboard device and store it in a buffer.
2788 26 robfinch
; The buffer of the task with the input focus is updated.
2789 34 robfinch
; This IRQ has to check for the ALT-tab character and take care of
2790
; switching the IO focus if detected. It can't be done in the KeybdGetChar
2791
; because the app with the IO focus may not call that routine. We know for
2792
; sure the interrupt routine will be called when a key is pressed.
2793 15 robfinch
;------------------------------------------------------------------------------
2794
;
2795 26 robfinch
message "KeybdIRQ"
2796 15 robfinch
KeybdIRQ:
2797 26 robfinch
        cld
2798 15 robfinch
        pha
2799
        phx
2800
        phy
2801 26 robfinch
        push    r4
2802
 
2803
        ; support EhBASIC's IRQ functionality
2804
        ; code derived from minimon.asm
2805
        lda             #15                             ; Keyboard is IRQ #15
2806
        sta             IrqSource
2807
        lb              r1,IrqBase              ; get the IRQ flag byte
2808
        lsr             r2,r1
2809
        or              r1,r1,r2
2810
        and             #$E0
2811
        sb              r1,IrqBase              ; save the new IRQ flag byte
2812
 
2813 28 robfinch
        ld              r4,IOFocusNdx   ; get the task with the input focus
2814 26 robfinch
 
2815 15 robfinch
        ldx             KEYBD                           ; get keyboard character
2816
        ld              r0,KEYBD+1                      ; clear keyboard strobe (turns off the IRQ)
2817
        txy                                                     ; check for a keyboard ACK code
2818 34 robfinch
 
2819
        bit             r3,#$800                                ; test bit #11
2820
        bne             KeybdIRQc                               ; ignore keyup messages for now
2821
        bit             r3,#$200                        ; check for ALT-tab
2822
        beq             KeybdIrq3
2823
        and             r3,r3,#$FF
2824
        cmp             r3,#TAB                                 ; if we find an ALT-tab
2825
        bne             KeybdIrq3
2826
        jsr             SwitchIOFocus
2827
        bra             KeybdIRQc                               ; don't store off the ALT-tab character
2828
KeybdIrq3:
2829 15 robfinch
        and             r3,r3,#$ff
2830
        cmp             r3,#$FA
2831
        bne             KeybdIrq1
2832 26 robfinch
        sty             KeybdAck,r4
2833 15 robfinch
        bra             KeybdIRQc
2834
KeybdIrq1:
2835
        bit             r2,#$800                                ; test bit #11
2836
        bne             KeybdIRQc                               ; ignore keyup messages for now
2837 26 robfinch
KeybdIrq2:
2838
        lda             KeybdHead,r4
2839 15 robfinch
        ina                                                             ; increment head pointer
2840
        and             #$f                                             ; limit
2841 26 robfinch
        ldy             KeybdTail,r4                    ; check for room in the keyboard buffer
2842 15 robfinch
        cmp             r1,r3
2843
        beq             KeybdIRQc                               ; if no room, the newest char will be lost
2844 26 robfinch
        sta             KeybdHead,r4
2845 15 robfinch
        dea
2846
        and             #$f
2847 26 robfinch
        stx             KeybdLocks,r4
2848
        asl             r4,r4,#4                                        ; * 16
2849
        add             r1,r1,r4
2850 15 robfinch
        stx             KeybdBuffer,r1                  ; store character in buffer
2851
KeybdIRQc:
2852 26 robfinch
        pop             r4
2853 15 robfinch
        ply
2854
        plx
2855
        pla
2856
        rti
2857
 
2858
KeybdRstIRQ:
2859 26 robfinch
        jmp             start
2860 15 robfinch
 
2861
;------------------------------------------------------------------------------
2862
; r1 0=echo off, non-zero = echo on
2863
;------------------------------------------------------------------------------
2864
SetKeyboardEcho:
2865 26 robfinch
        phx
2866
        ldx             RunningTCB
2867
        sta             KeybdEcho,x
2868
        plx
2869 15 robfinch
        rts
2870
 
2871 34 robfinch
comment ~
2872 26 robfinch
;------------------------------------------------------------------------------
2873
; Get a bit from the I/O focus table.
2874
;------------------------------------------------------------------------------
2875
GetIOFocusBit:
2876
        phx
2877
        phy
2878
        tax
2879
        and             r1,r1,#$1F              ; get bit index into word
2880
        lsr             r2,r2,#5                ; get word index into table
2881 28 robfinch
        ldy             IOFocusTbl,x
2882 26 robfinch
        lsr             r3,r3,r1                ; extract bit
2883
        and             r1,r3,#1
2884
        ply
2885
        plx
2886
        rts
2887 34 robfinch
~
2888
;------------------------------------------------------------------------------
2889
; ForceIOFocus
2890
;
2891
; Force the IO focus to a specific task.
2892
;------------------------------------------------------------------------------
2893
;
2894
ForceIOFocus:
2895
        php
2896
        pha
2897
        phy
2898
        ldy             IOFocusNdx
2899
        cmp             r1,r3
2900
        beq             fif1
2901
        jsr             CopyScreenToVirtualScreen
2902
        sta             IOFocusNdx
2903
        jsr             CopyVirtualScreenToScreen
2904
fif1:
2905
        ply
2906
        pla
2907
        plp
2908
        rts
2909 26 robfinch
 
2910
;------------------------------------------------------------------------------
2911
; SwitchIOFocus
2912 31 robfinch
;
2913 28 robfinch
; Switches the IO focus to the next task requesting the I/O focus. This
2914
; routine may be called when a task releases the I/O focus as well as when
2915
; the user presses ALT-TAB on the keyboard.
2916 26 robfinch
;------------------------------------------------------------------------------
2917
;
2918
SwitchIOFocus:
2919 28 robfinch
        pha
2920
        phy
2921 26 robfinch
 
2922 28 robfinch
        ; First check if it's even possible to switch the focus to another
2923
        ; task. The I/O focus list could be empty or there may be only a
2924
        ; single task in the list. In either case it's not possible to
2925
        ; switch.
2926
        ldy             IOFocusNdx              ; Get the task at the head of the list.
2927
        bmi             siof3                   ; Is the list empty ?
2928
        lda             TCB_iof_next,y  ; Get the next task on the list.
2929
        cmp             r1,r3                   ; Will the list head change ?
2930
        beq             siof3                   ; If not then no switch will occur
2931
 
2932
        ; Copy the current task's screen to it's virtual screen buffer.
2933
        jsr             CopyScreenToVirtualScreen
2934 26 robfinch
 
2935 28 robfinch
        sta             IOFocusNdx              ; Make task the new head of list.
2936 31 robfinch
 
2937 26 robfinch
        ; Copy the virtual screen of the task recieving the I/O focus to the
2938
        ; text screen.
2939
        jsr             CopyVirtualScreenToScreen
2940 28 robfinch
siof3:
2941
        ply
2942
        pla
2943 26 robfinch
        rts
2944
 
2945
;------------------------------------------------------------------------------
2946 15 robfinch
; Get character from keyboard buffer
2947
; return character in acc or -1 if no
2948 26 robfinch
; characters available.
2949
; Also check for ALT-TAB and switch the I/O focus.
2950
;------------------------------------------------------------------------------
2951
message "KeybdGetChar"
2952 15 robfinch
KeybdGetChar:
2953 34 robfinch
        php
2954 15 robfinch
        phx
2955 26 robfinch
        push    r4
2956
        sei
2957
        ld              r4,RunningTCB
2958 34 robfinch
        cmp             r4,#MAX_TASKNO
2959
        bhi             nochar
2960 26 robfinch
        ldx             KeybdTail,r4    ; if keybdTail==keybdHead then there are no
2961
        lda             KeybdHead,r4    ; characters in the keyboard buffer
2962 15 robfinch
        cmp             r1,r2
2963
        beq             nochar
2964 26 robfinch
        asl             r4,r4,#4                        ; * 16
2965
        phx
2966
        add             r2,r2,r4
2967 15 robfinch
        lda             KeybdBuffer,x
2968 26 robfinch
        plx
2969 15 robfinch
        and             r1,r1,#$ff              ; mask off control bits
2970
        inx                                             ; increment index
2971
        and             r2,r2,#$0f
2972 26 robfinch
        lsr             r4,r4,#4                        ; / 16
2973
        stx             KeybdTail,r4
2974
        ldx             KeybdEcho,r4
2975 15 robfinch
        beq             kgc3
2976
        cmp             #CR
2977 26 robfinch
        bne             kgc8
2978 15 robfinch
        jsr             CRLF                    ; convert CR keystroke into CRLF
2979
        bra             kgc3
2980 26 robfinch
kgc8:
2981 15 robfinch
        jsr             DisplayChar
2982
        bra             kgc3
2983
nochar:
2984
        lda             #-1
2985
kgc3:
2986 26 robfinch
        pop             r4
2987 15 robfinch
        plx
2988 34 robfinch
        plp
2989 15 robfinch
        rts
2990
 
2991
;------------------------------------------------------------------------------
2992
; Check if there is a keyboard character available in the keyboard buffer.
2993 26 robfinch
; Returns
2994
; r1 = 1, Z=0 if there is a key available, otherwise
2995
; r1 = 0, Z=1 if there is not a key available
2996 15 robfinch
;------------------------------------------------------------------------------
2997
;
2998 26 robfinch
message "KeybdCheckForKey"
2999 15 robfinch
KeybdCheckForKey:
3000
        phx
3001 26 robfinch
        push    r4
3002
        php
3003
        sei
3004
        ld              r4,RunningTCB
3005
        lda             KeybdTail,r4
3006
        ldx             KeybdHead,r4
3007 15 robfinch
        sub             r1,r1,r2
3008
        bne             kcfk1
3009 26 robfinch
        plp
3010
        pop             r4
3011 15 robfinch
        plx
3012 26 robfinch
        lda             #0
3013 15 robfinch
        rts
3014
kcfk1
3015 26 robfinch
        plp
3016
        pop             r4
3017
        plx
3018 15 robfinch
        lda             #1
3019
        rts
3020
;------------------------------------------------------------------------------
3021
; Check if there is a keyboard character available. If so return true (1)
3022
; otherwise return false (0) in r1.
3023
;------------------------------------------------------------------------------
3024
;
3025 26 robfinch
message "KeybdCheckForKeyDirect"
3026 15 robfinch
KeybdCheckForKeyDirect:
3027
        lda             KEYBD
3028
        and             #$8000
3029
        beq             kcfkd1
3030
        lda             #1
3031
kcfkd1
3032
        rts
3033
 
3034
;------------------------------------------------------------------------------
3035
; Get character directly from keyboard. This routine blocks until a key is
3036
; available.
3037
;------------------------------------------------------------------------------
3038
;
3039
KeybdGetCharDirect:
3040
        phx
3041
kgc1:
3042
        lda             KEYBD
3043
        bit             #$8000
3044
        beq             kgc1
3045
        ld              r0,KEYBD+1              ; clear keyboard strobe
3046
        bit             #$800                   ; is it a keydown event ?
3047
        bne             kgc1
3048 34 robfinch
;       bit             #$200                           ; check for ALT-tab
3049
;       bne             kgc2
3050
;       and             r2,r1,#$7f
3051
;       cmp             r2,#TAB                                 ; if we find an ALT-tab
3052
;       bne             kgc2
3053
;       jsr             SwitchIOFocus
3054
;       bra             kgc1
3055
;kgc2:
3056 15 robfinch
        and             #$ff                    ; remove strobe bit
3057
        ldx             KeybdEcho               ; is keyboard echo on ?
3058
        beq             gk1
3059
        cmp             #CR
3060
        bne             gk2                             ; convert CR keystroke into CRLF
3061
        jsr             CRLF
3062
        bra             gk1
3063
gk2:
3064
        jsr             DisplayChar
3065
gk1:
3066
        plx
3067
        rts
3068
 
3069
 
3070 26 robfinch
;==============================================================================
3071
; Serial port
3072
;==============================================================================
3073 15 robfinch
;------------------------------------------------------------------------------
3074 26 robfinch
; Initialize the serial port
3075
; r1 = low 28 bits = baud rate
3076
; r2 = other settings
3077
; The desired baud rate must fit in 28 bits or less.
3078
;------------------------------------------------------------------------------
3079
;
3080
SerialInit:
3081
;       asl             r1,r1,#4                        ; * 16
3082
;       shlui   r1,r1,#32                       ; * 2^32
3083
;       inhu    r2,CR_CLOCK                     ; get clock frequency from config record
3084
;       divu    r1,r1,r2                        ; / clock frequency
3085
 
3086
        lsr             r1,r1,#8                        ; drop the lowest 8 bits
3087
        sta             UART_CM1                        ; set LSB
3088
        lsr             r1,r1,#8
3089
        sta             UART_CM2                        ; set middle bits
3090
        lsr             r1,r1,#8
3091
        sta             UART_CM3                        ; set MSB
3092
        stz             Uart_rxhead                     ; reset buffer indexes
3093
        stz             Uart_rxtail
3094
        lda             #0x1f0
3095
        sta             Uart_foff                       ; set threshold for XOFF
3096
        lda             #0x010
3097
        sta             Uart_fon                        ; set threshold for XON
3098
        lda             #1
3099
        sta             UART_IE                         ; enable receive interrupt only
3100
        stz             Uart_rxrts                      ; no RTS/CTS signals available
3101
        stz             Uart_txrts                      ; no RTS/CTS signals available
3102
        stz             Uart_txdtr                      ; no DTR signals available
3103
        stz             Uart_rxdtr                      ; no DTR signals available
3104
        lda             #1
3105
        sta             Uart_txxon                      ; for now
3106
        lda             #1
3107
        sta             SERIAL_SEMA
3108
        rts
3109
 
3110
;---------------------------------------------------------------------------------
3111
; Get character directly from serial port. Blocks until a character is available.
3112
;---------------------------------------------------------------------------------
3113
;
3114
SerialGetCharDirect:
3115
sgc1:
3116
        lda             UART_LS         ; uart status
3117
        and             #rxfull         ; is there a char available ?
3118
        beq             sgc1
3119
        lda             UART
3120
        rts
3121
 
3122
;------------------------------------------------
3123
; Check for a character at the serial port
3124
; returns r1 = 1 if char available, 0 otherwise
3125
;------------------------------------------------
3126
;
3127
SerialCheckForCharDirect:
3128
        lda             UART_LS                 ; uart status
3129
        and             #rxfull                 ; is there a char available ?
3130
        rts
3131
 
3132
;-----------------------------------------
3133
; Put character to serial port
3134
; r1 = char to put
3135
;-----------------------------------------
3136
;
3137
SerialPutChar:
3138
        phx
3139
        phy
3140
        push    r4
3141
        push    r5
3142
 
3143
        ldx             UART_MC
3144
        or              r2,r2,#3                ; assert DTR / RTS
3145
        stx             UART_MC
3146
        ldx             Uart_txrts
3147
        beq             spcb1
3148
        ld              r4,Milliseconds
3149
        ldy             #1000                   ; delay count (1 s)
3150
spcb3:
3151
        ldx             UART_MS
3152
        and             r2,r2,#$10              ; is CTS asserted ?
3153
        bne             spcb1
3154
        ld              r5,Milliseconds
3155
        cmp             r4,r5
3156
        beq             spcb3
3157
        ld              r4,r5
3158
        dey
3159
        bne             spcb3
3160
        bra             spcabort
3161
spcb1:
3162
        ldx             Uart_txdtr
3163
        beq             spcb2
3164
        ld              r4,Milliseconds
3165
        ldy             #1000                   ; delay count
3166
spcb4:
3167
        ldx             UART_MS
3168
        and             r2,r2,#$20              ; is DSR asserted ?
3169
        bne             spcb2
3170
        ld              r5,Milliseconds
3171
        cmp             r4,r5
3172
        beq             spcb4
3173
        ld              r4,r5
3174
        dey
3175
        bne             spcb4
3176
        bra             spcabort
3177
spcb2:
3178
        ldx             Uart_txxon
3179
        beq             spcb5
3180
spcb6:
3181
        ldx             Uart_txxonoff
3182
        beq             spcb5
3183
        ld              r4,UART_MS
3184
        and             r4,r4,#0x80                     ; DCD ?
3185
        bne             spcb6
3186
spcb5:
3187
        ld              r4,Milliseconds
3188
        ldy             #1000                           ; wait up to 1s
3189
spcb8:
3190
        ldx             UART_LS
3191
        and             r2,r2,#0x20                     ; tx not full ?
3192
        bne             spcb7
3193
        ld              r5,Milliseconds
3194
        cmp             r4,r5
3195
        beq             spcb8
3196
        ld              r4,r5
3197
        dey
3198
        bne             spcb8
3199
        bra             spcabort
3200
spcb7:
3201
        sta             UART
3202
spcabort:
3203
        pop             r5
3204
        pop             r4
3205
        ply
3206
        plx
3207
        rts
3208
 
3209
;-------------------------------------------------
3210
; Compute number of characters in recieve buffer.
3211
; r4 = number of chars
3212
;-------------------------------------------------
3213
CharsInRxBuf:
3214
        ld              r4,Uart_rxhead
3215
        ldx             Uart_rxtail
3216
        sub             r4,r4,r2
3217
        bpl             cirxb1
3218
        ld              r4,#0x200
3219
        add             r4,r4,r2
3220
        ldx             Uart_rxhead
3221
        sub             r4,r4,r2
3222
cirxb1:
3223
        rts
3224
 
3225
;----------------------------------------------
3226
; Get character from rx fifo
3227
; If the fifo is empty enough then send an XON
3228
;----------------------------------------------
3229
;
3230
SerialGetChar:
3231
        phx
3232
        phy
3233
        push    r4
3234
 
3235
        ldy             Uart_rxhead
3236
        ldx             Uart_rxtail
3237
        cmp             r2,r3
3238
        beq             sgcfifo1                ; is there a char available ?
3239
        lda             Uart_rxfifo,x   ; get the char from the fifo into r1
3240
        inx                                             ; increment the fifo pointer
3241
        and             r2,r2,#$1ff
3242
        stx             Uart_rxtail
3243
        ldx             Uart_rxflow             ; using flow control ?
3244
        beq             sgcfifo2
3245
        ldy             Uart_fon                ; enough space in Rx buffer ?
3246
        jsr             CharsInRxBuf
3247
        cmp             r4,r3
3248
        bpl             sgcfifo2
3249
        stz             Uart_rxflow             ; flow off
3250
        ld              r4,Uart_rxrts
3251
        beq             sgcfifo3
3252
        ld              r4,UART_MC              ; set rts bit in MC
3253
        or              r4,r4,#2
3254
        st              r4,UART_MC
3255
sgcfifo3:
3256
        ld              r4,Uart_rxdtr
3257
        beq             sgcfifo4
3258
        ld              r4,UART_MC              ; set DTR
3259
        or              r4,r4,#1
3260
        st              r4,UART_MC
3261
sgcfifo4:
3262
        ld              r4,Uart_rxxon
3263
        beq             sgcfifo5
3264
        ld              r4,#XON
3265
        st              r4,UART
3266
sgcfifo5:
3267
sgcfifo2:                                       ; return with char in r1
3268
        pop             r4
3269
        ply
3270
        plx
3271
        rts
3272
sgcfifo1:
3273
        lda             #-1                             ; no char available
3274
        pop             r4
3275
        ply
3276
        plx
3277
        rts
3278
 
3279
 
3280
;-----------------------------------------
3281
; Serial port IRQ
3282
;-----------------------------------------
3283
;
3284
SerialIRQ:
3285
        pha
3286
        phx
3287
        phy
3288
        push    r4
3289
 
3290
        lda             UART_IS                 ; get interrupt status
3291
        bpl             sirq1                   ; no interrupt
3292
        and             #0x7f                   ; switch on interrupt type
3293
        cmp             #4
3294
        beq             srxirq
3295
        cmp             #$0C
3296
        beq             stxirq
3297
        cmp             #$10
3298
        beq             smsirq
3299
        ; unknown IRQ type
3300
sirq1:
3301
        pop             r4
3302
        ply
3303
        plx
3304
        pla
3305
        rti
3306
 
3307
 
3308
; Get the modem status and record it
3309
smsirq:
3310
        lda             UART_MS
3311
        sta             Uart_ms
3312
        bra             sirq1
3313
 
3314
stxirq:
3315
        bra             sirq1
3316
 
3317
; Get a character from the uart and store it in the rx fifo
3318
srxirq:
3319
srxirq1:
3320
        lda             UART                            ; get the char (clears interrupt)
3321
        ldx             Uart_txxon
3322
        beq             srxirq3
3323
        cmp             #XOFF
3324
        bne             srxirq2
3325
        lda             #1
3326
        sta             Uart_txxonoff
3327
        bra             srxirq5
3328
srxirq2:
3329
        cmp             #XON
3330
        bne             srxirq3
3331
        stz             Uart_txxonoff
3332
        bra             srxirq5
3333
srxirq3:
3334
        stz             Uart_txxonoff
3335
        ldx             Uart_rxhead
3336
        sta             Uart_rxfifo,x           ; store in buffer
3337
        inx
3338
        and             r2,r2,#$1ff
3339
        stx             Uart_rxhead
3340
srxirq5:
3341
        lda             UART_LS                         ; check for another ready character
3342
        and             #rxfull
3343
        bne             srxirq1
3344
        lda             Uart_rxflow                     ; are we using flow controls?
3345
        bne             srxirq8
3346
        jsr             CharsInRxBuf
3347
        lda             Uart_foff
3348
        cmp             r4,r1
3349
        bmi             srxirq8
3350
        lda             #1
3351
        sta             Uart_rxflow
3352
        lda             Uart_rxrts
3353
        beq             srxirq6
3354
        lda             UART_MC
3355
        and             #$FD                    ; turn off RTS
3356
        sta             UART_MC
3357
srxirq6:
3358
        lda             Uart_rxdtr
3359
        beq             srxirq7
3360
        lda             UART_MC
3361
        and             #$FE                    ; turn off DTR
3362
        sta             UART_MC
3363
srxirq7:
3364
        lda             Uart_rxxon
3365
        beq             srxirq8
3366
        lda             #XOFF
3367
        sta             UART
3368
srxirq8:
3369
        bra             sirq1
3370
 
3371
 
3372
;------------------------------------------------------------------------------
3373 11 robfinch
; Display nybble in r1
3374
;------------------------------------------------------------------------------
3375
;
3376
DisplayNybble:
3377
        pha
3378
        and             #$0F
3379
        add             #'0'
3380 15 robfinch
        cmp             #'9'+1
3381 11 robfinch
        bcc             dispnyb1
3382
        add             #7
3383
dispnyb1:
3384
        jsr             DisplayChar
3385
        pla
3386
        rts
3387
 
3388
;------------------------------------------------------------------------------
3389
; Display the byte in r1
3390
;------------------------------------------------------------------------------
3391
;
3392
DisplayByte:
3393
        pha
3394 18 robfinch
        lsr             r1,r1,#4
3395 11 robfinch
        jsr             DisplayNybble
3396
        pla
3397
        jmp             DisplayNybble   ; tail rts
3398 15 robfinch
message "785"
3399
;------------------------------------------------------------------------------
3400
; Display the half-word in r1
3401
;------------------------------------------------------------------------------
3402
;
3403
DisplayHalf:
3404
        pha
3405 18 robfinch
        lsr             r1,r1,#8
3406 15 robfinch
        jsr             DisplayByte
3407
        pla
3408
        jsr             DisplayByte
3409
        rts
3410 11 robfinch
 
3411 15 robfinch
message "797"
3412 11 robfinch
;------------------------------------------------------------------------------
3413 15 robfinch
; Display the half-word in r1
3414 11 robfinch
;------------------------------------------------------------------------------
3415 15 robfinch
;
3416
DisplayWord:
3417
        pha
3418 18 robfinch
        lsr             r1,r1,#16
3419 15 robfinch
        jsr             DisplayHalf
3420
        pla
3421
        jsr             DisplayHalf
3422
        rts
3423
message "810"
3424
;------------------------------------------------------------------------------
3425
; Display memory pointed to by r2.
3426
; destroys r1,r3
3427
;------------------------------------------------------------------------------
3428
;
3429
DisplayMemW:
3430
        pha
3431
        lda             #':'
3432
        jsr             DisplayChar
3433
        txa
3434
        jsr             DisplayWord
3435
        lda             #' '
3436
        jsr             DisplayChar
3437
        lda             (x)
3438
        jsr             DisplayWord
3439
        inx
3440
        lda             #' '
3441
        jsr             DisplayChar
3442
        lda             (x)
3443
        jsr             DisplayWord
3444
        inx
3445
        lda             #' '
3446
        jsr             DisplayChar
3447
        lda             (x)
3448
        jsr             DisplayWord
3449
        inx
3450
        lda             #' '
3451
        jsr             DisplayChar
3452
        lda             (x)
3453
        jsr             DisplayWord
3454
        inx
3455
        jsr             CRLF
3456
        pla
3457
        rts
3458 26 robfinch
 
3459
message "Monitor"
3460 15 robfinch
;==============================================================================
3461
; System Monitor Program
3462 26 robfinch
; The system monitor is task#0
3463 15 robfinch
;==============================================================================
3464
;
3465
Monitor:
3466 26 robfinch
        ldx             #BIOS_STACKS+0x03FF     ; setup stack pointer
3467 15 robfinch
        txs
3468 28 robfinch
        lda             #0                                      ; turn off keyboard echo
3469
        jsr             SetKeyboardEcho
3470
        jsr             RequestIOFocus
3471 15 robfinch
PromptLn:
3472
        jsr             CRLF
3473
        lda             #'$'
3474
        jsr             DisplayChar
3475
 
3476
; Get characters until a CR is keyed
3477
;
3478
Prompt3:
3479 28 robfinch
        jsr             RequestIOFocus
3480 15 robfinch
;       lw              r1,#2                   ; get keyboard character
3481
;       syscall #417
3482 26 robfinch
;       jsr             KeybdCheckForKeyDirect
3483
;       cmp             #0
3484
        jsr             KeybdGetChar
3485
        cmp             #-1
3486 15 robfinch
        beq             Prompt3
3487 26 robfinch
;       jsr             KeybdGetCharDirect
3488 15 robfinch
        cmp             #CR
3489
        beq             Prompt1
3490
        jsr             DisplayChar
3491
        bra             Prompt3
3492
 
3493
; Process the screen line that the CR was keyed on
3494
;
3495
Prompt1:
3496 31 robfinch
        lda             #80
3497
        sta             LEDS
3498 26 robfinch
        ldx             RunningTCB
3499 31 robfinch
        cpx             #MAX_TASKNO
3500 34 robfinch
        bhi             Prompt3
3501 31 robfinch
        lda             #81
3502
        sta             LEDS
3503 26 robfinch
        stz             TCB_CursorCol,x ; go back to the start of the line
3504 15 robfinch
        jsr             CalcScreenLoc   ; r1 = screen memory location
3505
        tay
3506 31 robfinch
        lda             #82
3507
        sta             LEDS
3508 34 robfinch
        jsr             MonGetch
3509 15 robfinch
        cmp             #'$'
3510
        bne             Prompt2                 ; skip over '$' prompt character
3511 31 robfinch
        lda             #83
3512
        sta             LEDS
3513 34 robfinch
        jsr             MonGetch
3514 15 robfinch
 
3515
; Dispatch based on command character
3516
;
3517
Prompt2:
3518
        cmp             #':'
3519
        beq             EditMem
3520
        cmp             #'D'
3521 18 robfinch
        bne             Prompt8
3522 34 robfinch
        jsr             MonGetch
3523 18 robfinch
        cmp             #'R'
3524
        beq             DumpReg
3525 31 robfinch
        cmp             #'I'
3526
        beq             DoDir
3527 18 robfinch
        dey
3528
        bra             DumpMem
3529
Prompt8:
3530 15 robfinch
        cmp             #'F'
3531 28 robfinch
        bne             Prompt7
3532 34 robfinch
        jsr             MonGetch
3533 28 robfinch
        cmp             #'L'
3534
        bne             Prompt8a
3535
        jsr             DumpIOFocusList
3536
        jmp             Monitor
3537
Prompt8a:
3538 34 robfinch
        cmp             #'I'
3539
        beq             DoFig
3540 31 robfinch
        cmp             #'M'
3541
        beq             DoFmt
3542 28 robfinch
        dey
3543
        bra             FillMem
3544 15 robfinch
Prompt7:
3545
        cmp             #'B'                    ; $B - start tiny basic
3546
        bne             Prompt4
3547 26 robfinch
        lda             #3
3548
        ldy             #CSTART
3549
        ldx             #0
3550
        jsr             StartTask
3551
;       jsr             CSTART
3552 15 robfinch
        bra             Monitor
3553
Prompt4:
3554
        cmp             #'b'
3555
        bne             Prompt5
3556 26 robfinch
        lda             #3                              ; priority level 3
3557
        ldy             #$C000                  ; start address $C000
3558 34 robfinch
        ldx             #$00000000              ; flags:
3559 26 robfinch
        jsr             StartTask
3560
        bra             Monitor
3561 15 robfinch
        emm
3562
        cpu             W65C02
3563
        jml             $0C000
3564
        cpu             rtf65002
3565
Prompt5:
3566
        cmp             #'J'                    ; $J - execute code
3567
        beq             ExecuteCode
3568 26 robfinch
        cmp             #'L'                    ; $L - load dector
3569
        beq             LoadSector
3570
        cmp             #'W'
3571
        beq             WriteSector
3572 15 robfinch
Prompt9:
3573
        cmp             #'?'                    ; $? - display help
3574
        bne             Prompt10
3575
        lda             #HelpMsg
3576
        jsr             DisplayStringB
3577
        jmp             Monitor
3578
Prompt10:
3579
        cmp             #'C'                    ; $C - clear screen
3580
        beq             TestCLS
3581 26 robfinch
        cmp             #'r'
3582 15 robfinch
        bne             Prompt12
3583 26 robfinch
        lda             #4                              ; priority level 4
3584
        ldx             #0                              ; zero all flags at startup
3585
        ldy             #RandomLines    ; task address
3586 34 robfinch
;       jsr             (y)
3587
        jsr             StartTask
3588 26 robfinch
        jmp             Monitor
3589
;       jmp             RandomLinesCall
3590 15 robfinch
Prompt12:
3591
Prompt13:
3592
        cmp             #'P'
3593
        bne             Prompt14
3594 31 robfinch
        lda             #2
3595
        ldx             #0
3596
        ldy             #Piano
3597
        jsr             StartTask
3598
        jmp             Monitor
3599 34 robfinch
 
3600 15 robfinch
Prompt14:
3601
        cmp             #'T'
3602
        bne             Prompt15
3603 34 robfinch
        jsr             MonGetch
3604
        cmp             #'O'
3605
        bne             Prompt14a
3606
        jsr             DumpTimeoutList
3607
        jmp             Monitor
3608
Prompt14a:
3609
        cmp             #'I'
3610
        bne             Prompt14b
3611
        jsr             DisplayDatetime
3612
        jmp             Monitor
3613
Prompt14b:
3614
        cmp             #'E'
3615
        bne             Prompt14c
3616
        jsr             ReadTemp
3617
        jmp             Monitor
3618
Prompt14c:
3619
        dey
3620 26 robfinch
        jsr             DumpTaskList
3621
        jmp             Monitor
3622 34 robfinch
 
3623 15 robfinch
Prompt15:
3624
        cmp             #'S'
3625
        bne             Prompt16
3626 34 robfinch
        jsr             MonGetch
3627 28 robfinch
        cmp             #'P'
3628
        bne             Prompt18
3629
        jsr             ignBlanks
3630
        jsr             GetHexNumber
3631
        sta             SPSave
3632
        jmp             Monitor
3633
Prompt18:
3634
        dey
3635 15 robfinch
        jsr             spi_init
3636
        cmp             #0
3637
        bne             Monitor
3638
        jsr             spi_read_part
3639
        cmp             #0
3640
        bne             Monitor
3641
        jsr             spi_read_boot
3642
        cmp             #0
3643
        bne             Monitor
3644
        jsr             loadBootFile
3645
        jmp             Monitor
3646
Prompt16:
3647 26 robfinch
        cmp             #'e'
3648
        bne             Prompt17
3649 34 robfinch
        lda             #1
3650
        ldx             #0
3651
        ldy             #eth_main
3652
        jsr             StartTask
3653
;       jsr             eth_main
3654
        jmp             Monitor
3655 26 robfinch
Prompt17:
3656
        cmp             #'R'
3657 34 robfinch
        bne             Prompt19
3658
        jsr             MonGetch
3659 26 robfinch
        cmp             #'S'
3660 28 robfinch
        beq             LoadSector
3661 26 robfinch
        dey
3662
        bra             SetRegValue
3663 15 robfinch
        jmp             Monitor
3664 34 robfinch
Prompt19:
3665
        cmp             #'K'
3666
        bne             Monitor
3667
Prompt19a:
3668
        jsr             MonGetch
3669
        cmp             #' '
3670
        bne             Prompt19a
3671
        jsr             ignBlanks
3672
        jsr             GetDecNumber
3673
        jsr             KillTask
3674
        jmp             Monitor
3675
 
3676 15 robfinch
message "Prompt16"
3677
RandomLinesCall:
3678 26 robfinch
;       jsr             RandomLines
3679 15 robfinch
        jmp             Monitor
3680
 
3681 34 robfinch
MonGetch:
3682
        lda             (y)
3683
        iny
3684
        jsr             ScreenToAscii
3685
        rts
3686
 
3687 31 robfinch
DoDir:
3688
        jsr             do_dir
3689
        jmp             Monitor
3690
DoFmt:
3691
        jsr             do_fmt
3692
        jmp             Monitor
3693 34 robfinch
DoFig:
3694
        lda             #3                              ; priority level 3
3695
        ldy             #$A000                  ; start address $A000
3696
        ldx             #$20000000              ; flags: emmulation mode set
3697
        jsr             StartTask
3698
        bra             Monitor
3699
 
3700 15 robfinch
TestCLS:
3701 34 robfinch
        jsr             MonGetch
3702 15 robfinch
        cmp             #'L'
3703
        bne             Monitor
3704 34 robfinch
        jsr             MonGetch
3705 15 robfinch
        cmp             #'S'
3706
        bne             Monitor
3707
        jsr     ClearScreen
3708 26 robfinch
        ldx             RunningTCB
3709
        stz             TCB_CursorCol,x
3710
        stz             TCB_CursorRow,x
3711 15 robfinch
        jsr             CalcScreenLoc
3712
        jmp             Monitor
3713 26 robfinch
message "HelpMsg"
3714 15 robfinch
HelpMsg:
3715
        db      "? = Display help",CR,LF
3716
        db      "CLS = clear screen",CR,LF
3717
        db      "S = Boot from SD Card",CR,LF
3718
        db      ": = Edit memory bytes",CR,LF
3719 26 robfinch
        db      "L = Load sector",CR,LF
3720
        db      "W = Write sector",CR,LF
3721 18 robfinch
        db  "DR = Dump registers",CR,LF
3722 15 robfinch
        db      "D = Dump memory",CR,LF
3723
        db      "F = Fill memory",CR,LF
3724 28 robfinch
        db  "FL = Dump I/O Focus List",CR,LF
3725 34 robfinch
;       db  "FIG = start FIG Forth",CR,LF
3726
        db      "KILL n = kill task #n",CR,LF
3727 15 robfinch
        db      "B = start tiny basic",CR,LF
3728
        db      "b = start EhBasic 6502",CR,LF
3729
        db      "J = Jump to code",CR,LF
3730 18 robfinch
        db      "R[n] = Set register value",CR,LF
3731 26 robfinch
        db      "r = random lines - test bitmap",CR,LF
3732
        db      "e = ethernet test",CR,LF
3733
        db      "T = Dump task list",CR,LF
3734 34 robfinch
        db      "TO = Dump timeout list",CR,LF
3735
        db      "TI = display date/time",CR,LF
3736
        db      "TEMP = display temperature",CR,LF
3737 15 robfinch
        db      "P = Piano",CR,LF,0
3738
 
3739
;------------------------------------------------------------------------------
3740
; Ignore blanks in the input
3741
; r3 = text pointer
3742
; r1 destroyed
3743
;------------------------------------------------------------------------------
3744
;
3745
ignBlanks:
3746
ignBlanks1:
3747 34 robfinch
        jsr             MonGetch
3748 15 robfinch
        cmp             #' '
3749
        beq             ignBlanks1
3750
        dey
3751
        rts
3752
 
3753
;------------------------------------------------------------------------------
3754
; Edit memory byte(s).
3755
;------------------------------------------------------------------------------
3756
;
3757
EditMem:
3758
        jsr             ignBlanks
3759
        jsr             GetHexNumber
3760
        or              r5,r1,r0
3761
        ld              r4,#3
3762
edtmem1:
3763
        jsr             ignBlanks
3764
        jsr             GetHexNumber
3765
        sta             (r5)
3766
        add             r5,r5,#1
3767
        dec             r4
3768
        bne             edtmem1
3769
        jmp             Monitor
3770
 
3771
;------------------------------------------------------------------------------
3772
; Execute code at the specified address.
3773
;------------------------------------------------------------------------------
3774
;
3775 26 robfinch
message "ExecuteCode"
3776 15 robfinch
ExecuteCode:
3777
        jsr             ignBlanks
3778
        jsr             GetHexNumber
3779 18 robfinch
        st              r1,JMPTMP
3780
        lda             #xcret                  ; push return address so we can do an indirect jump
3781
        pha
3782
        ld              r1,R1Save
3783
        ld              r2,R2Save
3784
        ld              r3,R3Save
3785
        ld              r4,R4Save
3786
        ld              r5,R5Save
3787
        ld              r6,R6Save
3788
        ld              r7,R7Save
3789
        ld              r8,R8Save
3790
        ld              r9,R9Save
3791
        ld              r10,R10Save
3792
        ld              r11,R11Save
3793
        ld              r12,R12Save
3794
        ld              r13,R13Save
3795
        ld              r14,R14Save
3796
        ld              r15,R15Save
3797
        jmp             (JMPTMP)
3798
xcret:
3799
        php
3800
        st              r1,R1Save
3801
        st              r2,R2Save
3802
        st              r3,R3Save
3803
        st              r4,R4Save
3804
        st              r5,R5Save
3805
        st              r6,R6Save
3806
        st              r7,R7Save
3807
        st              r8,R8Save
3808
        st              r9,R9Save
3809
        st              r10,R10Save
3810
        st              r11,R11Save
3811
        st              r12,R12Save
3812
        st              r13,R13Save
3813
        st              r14,R14Save
3814
        st              r15,R15Save
3815
        tsr             sp,r1
3816 28 robfinch
        st              r1,SPSave
3817 18 robfinch
        tsr             sp8,r1
3818 28 robfinch
        st              r1,SP8Save
3819 18 robfinch
        pla
3820
        sta             SRSave
3821 15 robfinch
        jmp     Monitor
3822
 
3823
LoadSector:
3824
        jsr             ignBlanks
3825 26 robfinch
        jsr             GetDecNumber
3826
        pha
3827
        jsr             ignBlanks
3828 15 robfinch
        jsr             GetHexNumber
3829 26 robfinch
        tax
3830
        phx
3831
;       ld              r2,#0x3800
3832
        jsr             spi_init
3833
        plx
3834
        pla
3835 15 robfinch
        jsr             spi_read_sector
3836
        jmp             Monitor
3837
 
3838 26 robfinch
WriteSector:
3839
        jsr             ignBlanks
3840
        jsr             GetDecNumber
3841
        pha
3842
        jsr             ignBlanks
3843
        jsr             GetHexNumber
3844
        tax
3845
        phx
3846
        jsr             spi_init
3847
        plx
3848
        pla
3849
        jsr             spi_write_sector
3850
        jmp             Monitor
3851
 
3852 15 robfinch
;------------------------------------------------------------------------------
3853 18 robfinch
; Dump the register set.
3854
;------------------------------------------------------------------------------
3855 26 robfinch
message "DumpReg"
3856 18 robfinch
DumpReg:
3857
        ldy             #0
3858
DumpReg1:
3859
        jsr             CRLF
3860
        lda             #':'
3861
        jsr             DisplayChar
3862
        lda             #'R'
3863
        jsr             DisplayChar
3864 26 robfinch
        ldx             #1
3865 18 robfinch
        tya
3866 26 robfinch
        ina
3867 18 robfinch
        jsr             PRTNUM
3868
        lda             #' '
3869
        jsr             DisplayChar
3870
        lda             R1Save,y
3871
        jsr             DisplayWord
3872
        iny
3873
        cpy             #15
3874
        bne             DumpReg1
3875
        jsr             CRLF
3876
        lda             #':'
3877
        jsr             DisplayChar
3878
        lda             #'S'
3879
        jsr             DisplayChar
3880
        lda             #'P'
3881
        jsr             DisplayChar
3882
        lda             #' '
3883
        jsr             DisplayChar
3884 26 robfinch
        lda             TCB_SPSave
3885 18 robfinch
        jsr             DisplayWord
3886
        jsr             CRLF
3887 26 robfinch
        jmp             Monitor
3888
;------------------------------------------------------------------------------
3889
;------------------------------------------------------------------------------
3890
SetRegValue:
3891
        jsr             GetDecNumber
3892
        cmp             #15
3893
        bpl             Monitor
3894
        pha
3895
        jsr             ignBlanks
3896
        jsr             GetHexNumber
3897
        ply
3898
        sta             R1Save,y
3899
        jmp             Monitor
3900 18 robfinch
 
3901
;------------------------------------------------------------------------------
3902 15 robfinch
; Do a memory dump of the requested location.
3903
;------------------------------------------------------------------------------
3904
;
3905
DumpMem:
3906
        jsr             ignBlanks
3907
        jsr             GetHexNumber    ; get start address of dump
3908
        tax
3909
        jsr             ignBlanks
3910
        jsr             GetHexNumber    ; get number of words to dump
3911
        lsr                                             ; 1/4 as many dump rows
3912
        lsr
3913
        bne             Dumpmem2
3914
        lda             #1                              ; dump at least one row
3915
Dumpmem2:
3916
        jsr             CRLF
3917
        bra             DumpmemW
3918
DumpmemW:
3919
        jsr             DisplayMemW
3920
        dea
3921
        bne             DumpmemW
3922
        jmp             Monitor
3923
 
3924
 
3925
        bra             Monitor
3926 26 robfinch
message "FillMem"
3927 15 robfinch
FillMem:
3928
        jsr             ignBlanks
3929
        jsr             GetHexNumber    ; get start address of dump
3930
        tax
3931
        jsr             ignBlanks
3932
        jsr             GetHexNumber    ; get number of bytes to fill
3933 26 robfinch
        ld              r5,r1
3934 15 robfinch
        jsr             ignBlanks
3935
        jsr             GetHexNumber    ; get the fill byte
3936
FillmemW:
3937
        sta             (x)
3938
        inx
3939
        dec             r5
3940
        bne             FillmemW
3941
        jmp             Monitor
3942
 
3943
;------------------------------------------------------------------------------
3944
; Get a hexidecimal number. Maximum of eight digits.
3945
; R3 = text pointer (updated)
3946
; R1 = hex number
3947
;------------------------------------------------------------------------------
3948
;
3949
GetHexNumber:
3950
        phx
3951
        push    r4
3952
        ldx             #0
3953
        ld              r4,#8
3954
gthxn2:
3955 34 robfinch
        jsr             MonGetch
3956 15 robfinch
        jsr             AsciiToHexNybble
3957
        cmp             #-1
3958
        beq             gthxn1
3959 18 robfinch
        asl             r2,r2,#4
3960 15 robfinch
        and             #$0f
3961
        or              r2,r2,r1
3962
        dec             r4
3963
        bne             gthxn2
3964
gthxn1:
3965
        txa
3966
        pop             r4
3967
        plx
3968
        rts
3969
 
3970 26 robfinch
GetDecNumber:
3971
        phx
3972
        push    r4
3973
        push    r5
3974
        ldx             #0
3975
        ld              r4,#10
3976
        ld              r5,#10
3977
gtdcn2:
3978 34 robfinch
        jsr             MonGetch
3979 26 robfinch
        jsr             AsciiToDecNybble
3980
        cmp             #-1
3981
        beq             gtdcn1
3982
        mul             r2,r2,r5
3983
        add             r2,r2,r1
3984
        dec             r4
3985
        bne             gtdcn2
3986
gtdcn1:
3987
        txa
3988
        pop             r5
3989
        pop             r4
3990
        plx
3991
        rts
3992
 
3993 15 robfinch
;------------------------------------------------------------------------------
3994
; Convert ASCII character in the range '0' to '9', 'a' to 'f' or 'A' to 'F'
3995
; to a hex nybble.
3996
;------------------------------------------------------------------------------
3997
;
3998
AsciiToHexNybble:
3999
        cmp             #'0'
4000
        bcc             gthx3
4001
        cmp             #'9'+1
4002
        bcs             gthx5
4003
        sub             #'0'
4004
        rts
4005
gthx5:
4006
        cmp             #'A'
4007
        bcc             gthx3
4008
        cmp             #'F'+1
4009
        bcs             gthx6
4010
        sub             #'A'
4011
        add             #10
4012
        rts
4013
gthx6:
4014
        cmp             #'a'
4015
        bcc             gthx3
4016
        cmp             #'z'+1
4017
        bcs             gthx3
4018
        sub             #'a'
4019
        add             #10
4020
        rts
4021
gthx3:
4022
        lda             #-1             ; not a hex number
4023
        rts
4024
 
4025 26 robfinch
AsciiToDecNybble:
4026
        cmp             #'0'
4027
        bcc             gtdc3
4028
        cmp             #'9'+1
4029
        bcs             gtdc3
4030
        sub             #'0'
4031
        rts
4032
gtdc3:
4033
        lda             #-1
4034
        rts
4035
 
4036
 
4037 15 robfinch
;------------------------------------------------------------------------------
4038
;------------------------------------------------------------------------------
4039 11 robfinch
ClearBmpScreen:
4040
        pha
4041
        phx
4042
        phy
4043 34 robfinch
        lda             #(1364*768)>>2          ; a = # words to clear
4044
        ldx             #0x29292929                     ; acc = color for four pixels
4045 11 robfinch
        ldy             #BITMAPSCR                      ; y = screen address
4046 34 robfinch
        stos
4047
;cbsj4
4048
;       sta             (y)                                     ; store pixel data
4049
;       iny                                                     ; advance screen address
4050
;       dex                                                     ; decrement pixel count and loop back
4051
;       bne             cbsj4
4052 11 robfinch
        ply
4053
        plx
4054
        pla
4055
        rts
4056
 
4057
;==============================================================================
4058
;==============================================================================
4059 28 robfinch
;--------------------------------------------------------------------------
4060
; Setup the AC97/LM4550 audio controller. Check keyboard for a CTRL-C
4061
; interrupt which may be necessary if the audio controller isn't
4062
; responding.
4063
;--------------------------------------------------------------------------
4064 11 robfinch
;
4065 28 robfinch
SetupAC97:
4066
        pha
4067
        phx
4068
        phy
4069
        push    r4
4070
        ld              r4,Milliseconds
4071
sac974:
4072
        stz             AC97+0x26               ; trigger a read of register 26 (status reg)
4073
sac971:                                         ; wait for status to register 0xF (all ready)
4074
        ld              r3,Milliseconds
4075
        sub             r3,r3,r4
4076
        cmp             r3,#1000
4077 34 robfinch
        bhi             sac97Abort
4078 28 robfinch
        jsr             KeybdGetChar    ; see if we needed to CTRL-C
4079
        cmp             #CTRLC
4080
        beq             sac973
4081
        lda             AC97+0x68               ; wait for dirty bit to clear
4082
        bne             sac971
4083
        lda             AC97+0x26               ; check status at reg h26, wait for
4084
        and             #0x0F                   ; analogue to be ready
4085
        cmp             #$0F
4086
        bne             sac974
4087
sac973:
4088
        stz             AC97+2                  ; master volume, 0db attenuation, mute off
4089
        stz             AC97+4                  ; headphone volume, 0db attenuation, mute off
4090
        stz             AC97+0x18               ; PCM gain (mixer) mute off, no attenuation
4091
        stz             AC97+0x0A               ; mute PC beep
4092
        lda             #0x8000                 ; bypass 3D sound
4093
        sta             AC97+0x20
4094
        ld              r4,Milliseconds
4095
sac972:
4096
        ld              r3,Milliseconds
4097
        sub             r3,r3,r4
4098
        cmp             r3,#1000
4099 34 robfinch
        bhi             sac97Abort
4100 28 robfinch
        jsr             KeybdGetChar
4101
        cmp             #CTRLC
4102
        beq             sac975
4103
        lda             AC97+0x68               ; wait for dirty bits to clear
4104
        bne             sac972                  ; wait a while for the settings to take effect
4105
sac975:
4106
        pop             r4
4107
        ply
4108
        plx
4109
        pla
4110
        rts
4111
sac97Abort:
4112
        lda             #msgAC97bad
4113
        jsr             DisplayStringCRLFB
4114
        pop             r4
4115
        ply
4116
        plx
4117
        pla
4118
        rts
4119
 
4120
msgAC97bad:
4121
        db      "The AC97 controller is not responding.",CR,LF,0
4122
 
4123
;--------------------------------------------------------------------------
4124
; Sound a 800 Hz beep
4125
;--------------------------------------------------------------------------
4126
;
4127
Beep:
4128
        lda             #15                             ; master volume to max
4129 34 robfinch
        sta             PSG+64
4130 28 robfinch
        lda             #13422                  ; 800Hz
4131
        sta             PSGFREQ0
4132
        ; decay  (16.384 ms)2
4133
        ; attack (8.192 ms)1
4134
        ; release (1.024 s)A
4135
        ; sustain level C
4136
        lda             #0xCA12
4137
        sta             PSGADSR0
4138
        lda             #0x1104                 ; gate, output enable, triangle waveform
4139
        sta             PSGCTRL0
4140 31 robfinch
        lda             #100                    ; delay about 1s
4141
        jsr             Sleep
4142 28 robfinch
        lda             #0x0104                 ; gate off, output enable, triangle waveform
4143
        sta             PSGCTRL0
4144 31 robfinch
        lda             #100                    ; delay about 1s
4145
        jsr             Sleep
4146 34 robfinch
        lda             #83
4147
        sta             LEDS
4148 28 robfinch
        lda             #0x0000                 ; gate off, output enable off, no waveform
4149
        sta             PSGCTRL0
4150
        rts
4151
 
4152
;--------------------------------------------------------------------------
4153
;--------------------------------------------------------------------------
4154
;
4155
Piano:
4156 31 robfinch
        jsr             RequestIOFocus
4157 28 robfinch
        lda             #15                             ; master volume to max
4158 34 robfinch
        sta             PSG+64
4159 28 robfinch
playnt:
4160
        jsr             KeybdGetChar
4161
        cmp             #CTRLC
4162 31 robfinch
        beq             PianoX
4163 28 robfinch
        cmp             #'a'
4164
        beq             playnt1a
4165
        cmp             #'b'
4166
        beq             playnt1b
4167
        cmp             #'c'
4168
        beq             playnt1c
4169
        cmp             #'d'
4170
        beq             playnt1d
4171
        cmp             #'e'
4172
        beq             playnt1e
4173
        cmp             #'f'
4174
        beq             playnt1f
4175
        cmp             #'g'
4176
        beq             playnt1g
4177
        bra             playnt
4178 31 robfinch
PianoX:
4179
        jsr             ReleaseIOFocus
4180
        rts
4181 28 robfinch
 
4182
playnt1a:
4183
        lda             #7217
4184
        jsr             Tone
4185
        bra             playnt
4186
playnt1b:
4187
        lda             #8101
4188
        jsr             Tone
4189
        bra             playnt
4190
playnt1c:
4191
        lda             #4291
4192
        jsr             Tone
4193
        bra             playnt
4194
playnt1d:
4195
        lda             #4817
4196
        jsr             Tone
4197
        bra             playnt
4198
playnt1e:
4199
        lda             #5407
4200
        jsr             Tone
4201
        bra             playnt
4202
playnt1f:
4203
        lda             #5728
4204
        jsr             Tone
4205
        bra             playnt
4206
playnt1g:
4207
        lda             #6430
4208
        jsr             Tone
4209
        bra             playnt
4210
 
4211
Tone:
4212
        pha
4213
        sta             PSGFREQ0
4214
        ; decay  (16.384 ms)2
4215
        ; attack (8.192 ms)1
4216
        ; release (1.024 s)A
4217
        ; sustain level C
4218
        lda             #0xCA12
4219
        sta             PSGADSR0
4220
        lda             #0x1104                 ; gate, output enable, triangle waveform
4221
        sta             PSGCTRL0
4222
        lda             #1                              ; delay about 10ms
4223
        jsr             Sleep
4224
        lda             #0x0104                 ; gate off, output enable, triangle waveform
4225
        sta             PSGCTRL0
4226
        lda             #1                              ; delay about 10ms
4227
        jsr             Sleep
4228
        lda             #0x0000                 ; gate off, output enable off, no waveform
4229
        sta             PSGCTRL0
4230
        pla
4231
        rts
4232
 
4233
;==============================================================================
4234
;==============================================================================
4235
;
4236 11 robfinch
; Initialize the SD card
4237
; Returns
4238
; acc = 0 if successful, 1 otherwise
4239 26 robfinch
; Z=1 if successful, otherwise Z=0
4240 11 robfinch
;
4241 26 robfinch
message "spi_init"
4242 11 robfinch
spi_init
4243
        lda             #SPI_INIT_SD
4244
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
4245
        lda             #SPI_TRANS_START
4246
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
4247
        nop
4248
spi_init1
4249
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
4250
        nop
4251
        nop
4252
        cmp             #SPI_TRANS_BUSY
4253
        beq             spi_init1
4254
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
4255
        and             #3
4256
        cmp             #SPI_INIT_NO_ERROR
4257
        bne             spi_error
4258 31 robfinch
;       lda             #spi_init_ok_msg
4259
;       jsr             DisplayStringB
4260 11 robfinch
        lda             #0
4261 26 robfinch
        rts
4262 11 robfinch
spi_error
4263
        jsr             DisplayByte
4264 15 robfinch
        lda             #spi_init_error_msg
4265 11 robfinch
        jsr             DisplayStringB
4266
        lda             SPIMASTER+SPI_RESP_BYTE1
4267
        jsr             DisplayByte
4268
        lda             SPIMASTER+SPI_RESP_BYTE2
4269
        jsr             DisplayByte
4270
        lda             SPIMASTER+SPI_RESP_BYTE3
4271
        jsr             DisplayByte
4272
        lda             SPIMASTER+SPI_RESP_BYTE4
4273
        jsr             DisplayByte
4274
        lda             #1
4275
        rts
4276
 
4277 26 robfinch
spi_delay:
4278
        nop
4279
        nop
4280
        rts
4281 11 robfinch
 
4282
 
4283
; SPI read sector
4284
;
4285
; r1= sector number to read
4286
; r2= address to place read data
4287
; Returns:
4288
; r1 = 0 if successful
4289
;
4290
spi_read_sector:
4291
        phx
4292
        phy
4293
        push    r4
4294
 
4295
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
4296 18 robfinch
        lsr             r1,r1,#8
4297 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
4298 18 robfinch
        lsr             r1,r1,#8
4299 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
4300 18 robfinch
        lsr             r1,r1,#8
4301 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
4302
 
4303
        ld              r4,#20  ; retry count
4304
 
4305
spi_read_retry:
4306
        ; Force the reciever fifo to be empty, in case a prior error leaves it
4307
        ; in an unknown state.
4308
        lda             #1
4309
        sta             SPIMASTER+SPI_RX_FIFO_CTRL_REG
4310
 
4311
        lda             #RW_READ_SD_BLOCK
4312
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
4313
        lda             #SPI_TRANS_START
4314
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
4315
        nop
4316
spi_read_sect1:
4317
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
4318 26 robfinch
        jsr             spi_delay                       ; just a delay between consecutive status reg reads
4319 11 robfinch
        cmp             #SPI_TRANS_BUSY
4320
        beq             spi_read_sect1
4321
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
4322
        lsr
4323
        lsr
4324
        and             #3
4325
        cmp             #SPI_READ_NO_ERROR
4326
        bne             spi_read_error
4327
        ldy             #512            ; read 512 bytes from fifo
4328
spi_read_sect2:
4329
        lda             SPIMASTER+SPI_RX_FIFO_DATA_REG
4330 15 robfinch
        sb              r1,0,x
4331 11 robfinch
        inx
4332
        dey
4333
        bne             spi_read_sect2
4334
        lda             #0
4335
        bra             spi_read_ret
4336
spi_read_error:
4337 15 robfinch
        dec             r4
4338 11 robfinch
        bne             spi_read_retry
4339
        jsr             DisplayByte
4340 15 robfinch
        lda             #spi_read_error_msg
4341 11 robfinch
        jsr             DisplayStringB
4342
        lda             #1
4343
spi_read_ret:
4344
        pop             r4
4345
        ply
4346
        plx
4347
        rts
4348
 
4349
; SPI write sector
4350
;
4351
; r1= sector number to write
4352
; r2= address to get data from
4353
; Returns:
4354
; r1 = 0 if successful
4355
;
4356
spi_write_sector:
4357
        phx
4358
        phy
4359
        pha
4360
        ; Force the transmitter fifo to be empty, in case a prior error leaves it
4361
        ; in an unknown state.
4362
        lda             #1
4363
        sta             SPIMASTER+SPI_TX_FIFO_CTRL_REG
4364
        nop                     ; give I/O time to respond
4365
        nop
4366
 
4367
        ; now fill up the transmitter fifo
4368
        ldy             #512
4369
spi_write_sect1:
4370 15 robfinch
        lb              r1,0,x
4371 11 robfinch
        sta             SPIMASTER+SPI_TX_FIFO_DATA_REG
4372
        nop                     ; give the I/O time to respond
4373
        nop
4374
        inx
4375
        dey
4376
        bne             spi_write_sect1
4377
 
4378
        ; set the sector number in the spi master address registers
4379
        pla
4380
        sta             SPIMASTER+SPI_SD_SECT_7_0_REG
4381 18 robfinch
        lsr             r1,r1,#8
4382 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_15_8_REG
4383 18 robfinch
        lsr             r1,r1,#8
4384 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_23_16_REG
4385 18 robfinch
        lsr             r1,r1,#8
4386 11 robfinch
        sta             SPIMASTER+SPI_SD_SECT_31_24_REG
4387
 
4388
        ; issue the write command
4389
        lda             #RW_WRITE_SD_BLOCK
4390
        sta             SPIMASTER+SPI_TRANS_TYPE_REG
4391
        lda             #SPI_TRANS_START
4392
        sta             SPIMASTER+SPI_TRANS_CTRL_REG
4393
        nop
4394
spi_write_sect2:
4395
        lda             SPIMASTER+SPI_TRANS_STATUS_REG
4396
        nop                                                     ; just a delay between consecutive status reg reads
4397
        nop
4398
        cmp             #SPI_TRANS_BUSY
4399
        beq             spi_write_sect2
4400
        lda             SPIMASTER+SPI_TRANS_ERROR_REG
4401 18 robfinch
        lsr             r1,r1,#4
4402 11 robfinch
        and             #3
4403
        cmp             #SPI_WRITE_NO_ERROR
4404
        bne             spi_write_error
4405
        lda             #0
4406
        bra             spi_write_ret
4407
spi_write_error:
4408
        jsr             DisplayByte
4409 15 robfinch
        lda             #spi_write_error_msg
4410 11 robfinch
        jsr             DisplayStringB
4411
        lda             #1
4412
 
4413
spi_write_ret:
4414
        ply
4415
        plx
4416
        rts
4417
 
4418 31 robfinch
; SPI read multiple sector
4419
;
4420
; r1= sector number to read
4421
; r2= address to write data
4422
; r3= number of sectors to read
4423
;
4424
; Returns:
4425
; r1 = 0 if successful
4426
;
4427
spi_read_multiple:
4428
        push    r4
4429
        ld              r4,#0
4430
spi_rm1:
4431
        pha
4432
        jsr             spi_read_sector
4433
        add             r4,r4,r1
4434
        add             r2,r2,#512
4435
        pla
4436
        ina
4437
        dey
4438
        bne             spi_rm1
4439
        ld              r1,r4
4440
        pop             r4
4441
        rts
4442
 
4443 28 robfinch
; SPI write multiple sector
4444
;
4445
; r1= sector number to write
4446
; r2= address to get data from
4447
; r3= number of sectors to write
4448
;
4449
; Returns:
4450
; r1 = 0 if successful
4451
;
4452
spi_write_multiple:
4453
        push    r4
4454 31 robfinch
        ld              r4,#0
4455 28 robfinch
spi_wm1:
4456
        pha
4457
        jsr             spi_write_sector
4458
        add             r4,r4,r1                ; accumulate an error count
4459
        add             r2,r2,#512              ; 512 bytes per sector
4460
        pla
4461
        ina
4462
        dey
4463
        bne             spi_wm1
4464
        ld              r1,r4
4465
        pop             r4
4466
        rts
4467
 
4468 15 robfinch
; read the partition table to find out where the boot sector is.
4469 26 robfinch
; Returns
4470
; r1 = 0 everything okay, 1=read error
4471
; also Z=1=everything okay, Z=0=read error
4472 15 robfinch
;
4473
spi_read_part:
4474
        phx
4475
        stz             startSector                                             ; default starting sector
4476
        lda             #0                                                              ; r1 = sector number (#0)
4477 26 robfinch
        ldx             #BYTE_SECTOR_BUF                                ; r2 = target address (word to byte address)
4478 15 robfinch
        jsr             spi_read_sector
4479 18 robfinch
        cmp             #0
4480
        bne             spi_rp1
4481 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1C9
4482 18 robfinch
        asl             r1,r1,#8
4483 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C8
4484 18 robfinch
        asl             r1,r1,#8
4485 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C7
4486 18 robfinch
        asl             r1,r1,#8
4487 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$1C6
4488
        sta             startSector                                             ; r1 = 0, for okay status
4489 18 robfinch
        plx
4490 15 robfinch
        lda             #0
4491 18 robfinch
        rts
4492
spi_rp1:
4493 15 robfinch
        plx
4494 18 robfinch
        lda             #1
4495 15 robfinch
        rts
4496
 
4497
; Read the boot sector from the disk.
4498
; Make sure it's the boot sector by looking for the signature bytes 'EB' and '55AA'.
4499 26 robfinch
; Returns:
4500
; r1 = 0 means this card is bootable
4501
; r1 = 1 means a read error occurred
4502
; r1 = 2 means the card is not bootable
4503 15 robfinch
;
4504
spi_read_boot:
4505
        phx
4506
        phy
4507
        push    r5
4508
        lda             startSector                                     ; r1 = sector number
4509
        ldx             #BYTE_SECTOR_BUF                        ; r2 = target address
4510
        jsr             spi_read_sector
4511 26 robfinch
        cmp             #0
4512
        bne             spi_read_boot_err
4513 15 robfinch
        lb              r1,BYTE_SECTOR_BUF
4514
        cmp             #$EB
4515 26 robfinch
        bne             spi_eb_err
4516 15 robfinch
spi_read_boot2:
4517
        lda             #msgFoundEB
4518
        jsr             DisplayStringB
4519
        lb              r1,BYTE_SECTOR_BUF+$1FE         ; check for 0x55AA signature
4520
        cmp             #$55
4521 26 robfinch
        bne             spi_eb_err
4522 15 robfinch
        lb              r1,BYTE_SECTOR_BUF+$1FF         ; check for 0x55AA signature
4523
        cmp             #$AA
4524 26 robfinch
        bne             spi_eb_err
4525
        pop             r5
4526
        ply
4527
        plx
4528 15 robfinch
        lda             #0                                              ; r1 = 0, for okay status
4529 26 robfinch
        rts
4530
spi_read_boot_err:
4531 15 robfinch
        pop             r5
4532
        ply
4533
        plx
4534 26 robfinch
        lda             #1
4535 15 robfinch
        rts
4536 26 robfinch
spi_eb_err:
4537
        lda             #msgNotFoundEB
4538
        jsr             DisplayStringB
4539
        pop             r5
4540
        ply
4541
        plx
4542
        lda             #2
4543
        rts
4544 15 robfinch
 
4545
msgFoundEB:
4546
        db      "Found EB code.",CR,LF,0
4547 26 robfinch
msgNotFoundEB:
4548
        db      "EB/55AA Code missing.",CR,LF,0
4549 15 robfinch
 
4550
; Load the root directory from disk
4551
; r2 = where to place root directory in memory
4552
;
4553
loadBootFile:
4554 31 robfinch
        lb              r1,BYTE_SECTOR_BUF+BSI_SecPerFAT+1                      ; sectors per FAT
4555 18 robfinch
        asl             r1,r1,#8
4556 31 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+BSI_SecPerFAT
4557 15 robfinch
        bne             loadBootFile7
4558
        lb              r1,BYTE_SECTOR_BUF+$27                  ; sectors per FAT, FAT32
4559 18 robfinch
        asl             r1,r1,#8
4560 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$26
4561 18 robfinch
        asl             r1,r1,#8
4562 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$25
4563 18 robfinch
        asl             r1,r1,#8
4564 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$24
4565
loadBootFile7:
4566
        lb              r4,BYTE_SECTOR_BUF+$10                  ; number of FATs
4567
        mul             r3,r1,r4                                                ; offset
4568
        lb              r1,BYTE_SECTOR_BUF+$F                   ; r1 = # reserved sectors before FAT
4569 18 robfinch
        asl             r1,r1,#8
4570 15 robfinch
        orb             r1,r1,BYTE_SECTOR_BUF+$E
4571
        add             r3,r3,r1                                                ; r3 = root directory sector number
4572
        ld              r6,startSector
4573
        add             r5,r3,r6                                                ; r5 = root directory sector number
4574
        lb              r1,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
4575
        add             r3,r1,r5                                                ; r3 = first cluster after first cluster of directory
4576
        bra             loadBootFile6
4577
 
4578
loadBootFile6:
4579
        ; For now we cheat and just go directly to sector 512.
4580
        bra             loadBootFileTmp
4581
 
4582
loadBootFileTmp:
4583
        ; We load the number of sectors per cluster, then load a single cluster of the file.
4584
        ; This is 16kib
4585
        ld              r5,r3                                                   ; r5 = start sector of data area
4586
        ld              r2,#PROG_LOAD_AREA                              ; where to place file in memory
4587
        lb              r3,BYTE_SECTOR_BUF+$D                   ; sectors per cluster
4588
loadBootFile1:
4589
        ld              r1,r5                                                   ; r1=sector to read
4590
        jsr             spi_read_sector
4591
        inc             r5                                              ; r5 = next sector
4592
        add             r2,r2,#512
4593
        dec             r3
4594
        bne             loadBootFile1
4595 26 robfinch
        lda             PROG_LOAD_AREA>>2               ; make sure it's bootable
4596 15 robfinch
        cmp             #$544F4F42
4597
        bne             loadBootFile2
4598
        lda             #msgJumpingToBoot
4599
        jsr             DisplayStringB
4600 26 robfinch
        lda             (PROG_LOAD_AREA>>2)+$1
4601 15 robfinch
        jsr             (r1)
4602
        jmp             Monitor
4603
loadBootFile2:
4604
        lda             #msgNotBootable
4605
        jsr             DisplayStringB
4606
        ldx             #PROG_LOAD_AREA>>2
4607
        jsr             DisplayMemW
4608
        jsr             DisplayMemW
4609
        jsr             DisplayMemW
4610
        jsr             DisplayMemW
4611
        jmp             Monitor
4612
 
4613 11 robfinch
msgJumpingToBoot:
4614
        db      "Jumping to boot",0
4615
msgNotBootable:
4616
        db      "SD card not bootable.",0
4617
spi_init_ok_msg:
4618
        db "SD card initialized okay.",0
4619
spi_init_error_msg:
4620
        db      ": error occurred initializing the SD card.",0
4621
spi_boot_error_msg:
4622 26 robfinch
        db      "SD card boot error",CR,LF,0
4623 11 robfinch
spi_read_error_msg:
4624 26 robfinch
        db      "SD card read error",CR,LF,0
4625 11 robfinch
spi_write_error_msg:
4626
        db      "SD card write error",0
4627
 
4628 31 robfinch
do_fmt:
4629
        jsr             spi_init
4630
        cmp             #0
4631
        bne             fmt_abrt
4632
        ldx             #DIRBUF
4633
        ldy             #65536
4634
        ; clear out the directory buffer
4635
dfmt1:
4636
        stz             (x)
4637
        inx
4638
        dey
4639
        bne             dfmt1
4640
        jsr             store_dir
4641
fmt_abrt:
4642
        rts
4643
 
4644
do_dir:
4645
        jsr             CRLF
4646
        jsr             spi_init
4647
        cmp             #0
4648
        bne             dirabrt
4649
        jsr             load_dir
4650
        ld              r4,#0                   ; r4 = entry counter
4651
ddir3:
4652
        asl             r3,r4,#6                ; y = start of entry, 64 bytes per entry
4653
        ldx             #32                             ; 32 chars in filename
4654
ddir4:
4655
        lb              r1,DIRBUF<<2,y
4656
        beq             ddir2                   ; move to next dir entry if null is found
4657
        cmp             #$20                    ; don't display control chars
4658
        bmi             ddir1
4659
        jsr             DisplayChar
4660
        bra             ddir5
4661
ddir1:
4662
        lda             #' '
4663
        jsr             DisplayChar
4664
ddir5:
4665
        iny
4666
        dex
4667
        bne             ddir4
4668
        lda             #' '
4669
        jsr             DisplayChar
4670
        asl             r3,r4,#4                ; y = start of entry, 16 words per entry
4671
        lda             DIRBUF+$D,y
4672
        ldx             #5
4673
        jsr             PRTNUM
4674
        jsr             CRLF
4675
ddir2:
4676
        jsr             KeybdGetChar
4677
        cmp             #CTRLC
4678
        beq             ddir6
4679
        inc             r4
4680
        cmp             r4,#512         ; max 512 dir entries
4681
        bne             ddir3
4682
ddir6:
4683
 
4684
dirabrt:
4685
        rts
4686
 
4687
load_dir:
4688
        pha
4689
        phx
4690
        phy
4691
        lda             #4000
4692
        ldx             #DIRBUF<<2
4693
        ldy             #64
4694
        jsr             spi_read_multiple
4695
        ply
4696
        plx
4697
        pla
4698
        rts
4699
store_dir:
4700
        pha
4701
        phx
4702
        phy
4703
        lda             #4000
4704
        ldx             #DIRBUF<<2
4705
        ldy             #64
4706
        jsr             spi_write_multiple
4707
        ply
4708
        plx
4709
        pla
4710
        rts
4711
 
4712
; r1 = pointer to file name
4713
; r2 = pointer to buffer to save
4714
; r3 = length of buffer
4715
;
4716
do_save:
4717
        pha
4718
        jsr             spi_init
4719
        cmp             #0
4720
        bne             dsavErr
4721
        pla
4722
        jsr             load_dir
4723
        ld              r4,#0
4724
dsav4:
4725
        asl             r5,r4,#6
4726
        ld              r7,#0
4727
        ld              r10,r1
4728
dsav2:
4729
        lb              r6,DIRBUF<<2,r5
4730
        lb              r8,0,r10
4731
        cmp             r6,r8
4732
        bne             dsav1
4733
        inc             r5
4734
        inc             r7
4735
        inc             r10
4736
        cmp             r7,#32
4737
        bne             dsav2
4738
        ; here the filename matched
4739
dsav8:
4740
        asl             r7,r4,#7        ; compute file address  64k * entry #
4741
        add             r7,r7,#5000     ; start at sector 5,000
4742
        ld              r1,r7           ; r1 = sector number
4743
        lsr             r3,r3,#9        ; r3/512
4744
        iny                                     ; +1
4745
        jsr             spi_write_multiple
4746
dsav3:
4747
        rts
4748
        ; Here the filename didn't match
4749
dsav1:
4750
        inc             r4
4751
        cmp             r4,#512
4752
        bne             dsav4
4753
        ; Here none of the filenames in the directory matched
4754
        ; Find an empty entry.
4755
        ld              r4,#0
4756
dsav6:
4757
        asl             r5,r4,#6
4758
        lb              r6,DIRBUF<<2,r5
4759
        beq             dsav5
4760
        inc             r4
4761
        cmp             r4,#512
4762
        bne             dsav6
4763
        ; Here there were no empty entries
4764
        lda             #msgDiskFull
4765
        jsr             DisplayStringB
4766
        rts
4767
dsav5:
4768
        ld              r7,#32
4769
        ld              r10,r1
4770
dsav7:
4771
        lb              r6,0,r10        ; copy the filename into the directory entry
4772
        sb              r6,DIRBUF<<2,r5
4773
        inc             r5
4774
        inc             r10
4775
        dec             r7
4776
        bne             dsav7
4777
                                                ; copy the file size into the directory entry
4778
        asl             r5,r4,#4        ; 16 words per dir entry
4779
        sty             DIRBUF+$D,r5
4780
        jsr             store_dir
4781
        bra             dsav8
4782
dsavErr:
4783
        pla
4784
        rts
4785
 
4786
msgDiskFull
4787
        db      CR,LF,"The disk is full, unable to save file.",CR,LF,0
4788
 
4789
do_load:
4790
        pha
4791
        jsr             spi_init
4792
        cmp             #0
4793
        bne             dsavErr
4794
        pla
4795
        jsr             load_dir
4796
        ld              r4,#0
4797
dlod4:
4798
        asl             r5,r4,#6
4799
        ld              r7,#0
4800
        ld              r10,r1
4801
dlod2:
4802
        lb              r6,DIRBUF<<2,r5
4803
        lb              r8,0,r10
4804
        cmp             r6,r8
4805
        bne             dlod1
4806
        inc             r5
4807
        inc             r7
4808
        inc             r10
4809
        cmp             r7,#32
4810
        bne             dlod2
4811
        ; here the filename matched
4812
dlod8:
4813
        asl             r5,r4,#4                                ; 16 words
4814
        ld              r3,DIRBUF+$d,r5                 ; get file size into y register
4815
        asl             r7,r4,#7        ; compute file address  64k * entry #
4816
        add             r7,r7,#5000     ; start at sector 5,000
4817
        ld              r1,r7           ; r1 = sector number
4818
        lsr             r3,r3,#9        ; r3/512
4819
        iny                                     ; +1
4820
        jsr             spi_read_multiple
4821
dlod3:
4822
        rts
4823
        ; Here the filename didn't match
4824
dlod1:
4825
        inc             r4
4826
        cmp             r4,#512
4827
        bne             dlod4
4828
        ; Here none of the filenames in the directory matched
4829
        ;
4830
        lda             #msgFileNotFound
4831
        jsr             DisplayStringB
4832
        rts
4833
 
4834
msgFileNotFound:
4835
        db      CR,LF,"File not found.",CR,LF
4836
 
4837 26 robfinch
;==============================================================================
4838
; Ethernet
4839
;==============================================================================
4840
my_MAC1 EQU     0x00
4841
my_MAC2 EQU     0xFF
4842
my_MAC3 EQU     0xEE
4843
my_MAC4 EQU     0xF0
4844
my_MAC5 EQU     0xDA
4845
my_MAC6 EQU     0x42
4846
 
4847 34 robfinch
; r1 = PHY
4848
; r2 = regnum
4849
; r3 = data
4850
;
4851
eth_mii_write:
4852
        pha
4853
        phx
4854
        push    r4
4855
        ld              r4,#ETHMAC
4856
        asl             r2,r2,#8
4857
        or              r1,r1,r2
4858
        sta             ETH_MIIADDRESS,r4
4859
        sty             ETH_MIITX_DATA,r4
4860
        lda             #ETH_WCTRLDATA
4861
        sta             ETH_MIICOMMAND,r4
4862
        stz             ETH_MIICOMMAND,r4
4863
emiw1:
4864
        lda             ETH_MIISTATUS,r4
4865
        bit             #ETH_MIISTATUS_BUSY
4866
        bne             emiw1
4867
        pop             r4
4868
        plx
4869
        pla
4870
        rts
4871
 
4872
; r1 = PHY
4873
; r2 = reg
4874
 
4875
eth_mii_read:
4876
        phx
4877
        phy
4878
        ldy             #ETHMAC
4879
        asl             r2,r2,#8
4880
        or              r1,r1,r2
4881
        sta             ETH_MIIADDRESS,y
4882
        lda             #ETH_MIICOMMAND_RSTAT
4883
        sta             ETH_MIICOMMAND,y
4884
        stz             ETH_MIICOMMAND,y
4885
emir1:
4886
        lda             ETH_MIISTATUS,y
4887
        bit             #ETH_MIISTATUS_BUSY
4888
        bne             emir1
4889
        lda             ETH_MIIRX_DATA,y
4890
        ply
4891
        plx
4892
        rts
4893
 
4894
ethmac_setup:
4895
        ld              r4,#ETHMAC
4896
        lda             #ETH_MIIMODER_RST
4897
        sta             ETH_MIIMODER,r4
4898
        lda             ETH_MIIMODER,r4
4899
        and             #~ETH_MIIMODER_RST
4900
        sta             ETH_MIIMODER,r4
4901
        lda             #$10                            ; /16=1.25MHz
4902
        sta             ETH_MIIMODER,r4         ; Clock divider for MII Management interface
4903
        lda             #ETH_MODER_RST
4904
        sta             ETH_MODER,r4
4905
        lda             ETH_MODER,r4
4906
        and             #~ETH_MODER_RST
4907
        sta             ETH_MODER,r4
4908
 
4909
        stz             ETH_MIITX_DATA,r4
4910
        stz             ETH_MIIADDRESS,r4
4911
        stz             ETH_MIICOMMAND,r4
4912
 
4913
        lda             #0xEEF0DA42
4914
        sta             ETH_MAC_ADDR0,r4                ; MAC0
4915
        lda             #0x00FF
4916
        sta             ETH_MAC_ADDR1,r4                ; MAC1
4917
 
4918
        lda             #-1
4919
        sta             ETH_INT_SOURCE,r4
4920
 
4921
        ; Advertise support for 10/100 FD/HD
4922
        lda             #ETH_PHY
4923
        ldx             #ETH_MII_ADVERTISE
4924
        jsr             eth_mii_read
4925
        or              r3,r1,#ETH_ADVERTISE_ALL
4926
        lda             #ETH_PHY
4927
        ldx             #ETH_MII_ADVERTISE
4928
        jsr             eth_mii_write
4929
 
4930
        ; Do NOT advertise support for 1000BT
4931
        lda             #ETH_PHY
4932
        ldx             #ETH_MII_CTRL1000
4933
        jsr             eth_mii_read
4934
        and             r3,r1,#~(ETH_ADVERTISE_1000FULL|ETH_ADVERTISE_1000HALF)
4935
        lda             #ETH_PHY
4936
        ldx             #ETH_MII_CTRL1000
4937
        jsr             eth_mii_write
4938
 
4939
        ; Disable 1000BT
4940
        lda             #ETH_PHY
4941
        ldx             #ETH_MII_EXPANSION
4942
        jsr             eth_mii_read
4943
        and             r3,r1,#~(ETH_ESTATUS_1000_THALF|ETH_ESTATUS_1000_TFULL)
4944
        ldx             #ETH_MII_EXPANSION
4945
        jsr             eth_mii_write
4946
 
4947
        ; Restart autonegotiation
4948
        lda             #0
4949
        ldx             #ETH_MII_BMCR
4950
        jsr             eth_mii_read
4951
        and             r3,r1,#~(ETH_BMCR_ANRESTART|ETH_BMCR_ANENABLE)
4952
        lda             #7
4953
        jsr             eth_mii_write
4954
 
4955
        ; Enable BOTH the transmiter and receiver
4956
        lda             #$A003
4957
        sta             ETH_MODER,r4
4958
        rts
4959
 
4960 26 robfinch
; Initialize the ethmac controller.
4961
; Supply a MAC address, set MD clock
4962
;
4963
message "eth_init"
4964
eth_init:
4965
        pha
4966
        phy
4967
        ldy             #ETHMAC
4968 34 robfinch
        lda             #$A003
4969
        sta             ETH_MODER,y
4970
;       lda             #0x64                           ; 100
4971
;       sta             ETH_MIIMODER,y
4972
;       lda             #7                                      ; PHY address
4973
;       sta             ETH_MIIADDRESS,y
4974 26 robfinch
        lda             #0xEEF0DA42
4975
        sta             ETH_MAC_ADDR0,y         ; MAC0
4976
        lda             #0x00FF
4977
        sta             ETH_MAC_ADDR1,y         ; MAC1
4978
        ply
4979
        pla
4980
        rts
4981
 
4982
; Request a packet and display on screen
4983
; r1 = address where to put packet
4984
;
4985
message "eth_request_packet"
4986
eth_request_packet:
4987
        phx
4988
        phy
4989
        push    r4
4990
        push    r5
4991
        ldy             #ETHMAC
4992
        ldx             #4                                      ; clear rx interrupt
4993
        stx             ETH_INT_SOURCE,y
4994
        sta             0x181,y                         ; storage address
4995
        ldx             #0xe000                         ; enable interrupt
4996
        stx             0x180,y
4997
eth1:
4998
        nop
4999
        ldx             ETH_INT_SOURCE,y
5000 34 robfinch
        bit             r2,#4                           ; get bit #2
5001 26 robfinch
        beq             eth1
5002
        ldx             0x180,y                         ; get from descriptor
5003
        lsr             r2,r2,#16
5004
        ldy             #0
5005 34 robfinch
        pha
5006
        jsr             GetScreenLocation
5007
        add             r4,r1,3780                      ; second last line of screen
5008
        pla
5009 26 robfinch
eth20:
5010
        add             r5,r1,r3
5011 34 robfinch
        lb              r2,0,r5                         ; get byte
5012 26 robfinch
        add             r5,r4,r3
5013
        stx             (r5)                            ; store to screen
5014
        iny
5015
        cpy             #83
5016
        bne             eth20
5017
        pop             r5
5018
        pop             r4
5019
        ply
5020
        plx
5021
        rts
5022
 
5023
; r1 = packet address
5024
;
5025
message "eth_interpret_packet"
5026
eth_interpret_packet:
5027
        phx
5028
        phy
5029
        lb              r2,12,r1
5030
        lb              r3,13,r1
5031
        cpx             #8                                      ; 0x806 ?
5032
        bne             eth2
5033
        cpy             #6
5034
        bne             eth2
5035
        lda             #2                                      ; return r1 = 2 for ARP
5036
eth5:
5037
        ply
5038
        plx
5039
        rts
5040
eth2:
5041
        cpx             #8
5042
        bne             eth3                            ; 0x800 ?
5043
        cpy             #0
5044
        bne             eth3
5045
        lb              r2,23,r1
5046
        cpx             #1
5047
        bne             eth4
5048
        lda             #1
5049
        bra             eth5                            ; return 1 ICMP
5050
eth4:
5051
        cpx             #$11
5052
        bne             eth6
5053
        lda             #3                                      ; return 3 for UDP
5054
        bra             eth5
5055
eth6:
5056
        cpx             #6
5057
        bne             eth7
5058
        lda             #4                                      ; return 4 for TCP
5059
        bra             eth5
5060
eth7:
5061
eth3:
5062
        eor             r1,r1,r1                        ; return zero for unknown
5063
        ply
5064
        plx
5065
        rts
5066
 
5067
; r1 = address of packet to send
5068
; r2 = packet length
5069
;
5070
message "eth_send_packet"
5071
eth_send_packet:
5072
        phx
5073
        phy
5074
        push    r4
5075
        ldy             #ETHMAC
5076
        ; wait for tx buffer to be clear
5077
eth8:
5078
        ld              r4,0x100,y
5079 34 robfinch
        bit             r4,#$8000
5080 26 robfinch
        bne             eth8
5081
        ld              r4,#1                   ; clear tx interrupt
5082
        st              r4,ETH_INT_SOURCE,y
5083
        ; set address
5084
        sta             0x101,y
5085
        ; set the packet length field and enable interrupts
5086
        asl             r2,r2,#16
5087
        or              r2,r2,#0xF000
5088
        stx             0x100,y
5089
        pop             r4
5090
        ply
5091
        plx
5092
        rts
5093
 
5094
; Only for IP type packets (not ARP)
5095
; r1 = rx buffer address
5096
; r2 = swap flag
5097
; Returns:
5098
; r1 = data start index
5099
;
5100
message "eth_build_packet"
5101
eth_build_packet:
5102
        phy
5103
        push    r4
5104
        push    r5
5105
        push    r6
5106
        push    r7
5107
        push    r8
5108
        push    r9
5109
        push    r10
5110
 
5111
        lb              r3,6,r1
5112
        lb              r4,7,r1
5113
        lb              r5,8,r1
5114
        lb              r6,9,r1
5115
        lb              r7,10,r1
5116
        lb              r8,11,r1
5117
        ; write to destination header
5118
        sb              r3,0,r1
5119
        sb              r4,1,r1
5120
        sb              r5,2,r1
5121
        sb              r6,3,r1
5122
        sb              r7,4,r1
5123
        sb              r8,5,r1
5124
        ; write to source header
5125
        ld              r3,#my_MAC1
5126
        sb              r3,6,r1
5127
        ld              r3,#my_MAC2
5128
        sb              r3,7,r1
5129
        ld              r3,#my_MAC3
5130
        sb              r3,8,r1
5131
        ld              r3,#my_MAC4
5132
        sb              r3,9,r1
5133
        ld              r3,#my_MAC5
5134
        sb              r3,10,r1
5135
        ld              r3,#my_MAC6
5136
        sb              r3,11,r1
5137
        cmp             r2,#1
5138
        bne             eth16                   ; if (swap)
5139
        lb              r3,26,r1
5140
        lb              r4,27,r1
5141
        lb              r5,28,r1
5142
        lb              r6,29,r1
5143
        ; read destination
5144
        lb              r7,30,r1
5145
        lb              r8,31,r1
5146
        lb              r9,32,r1
5147
        lb              r10,33,r1
5148
        ; write to sender
5149
        sb              r7,26,r1
5150
        sb              r8,27,r1
5151
        sb              r9,28,r1
5152
        sb              r10,29,r1
5153
        ; write destination
5154
        sb              r3,30,r1
5155
        sb              r4,31,r1
5156
        sb              r5,32,r1
5157
        sb              r6,33,r1
5158
eth16:
5159
        ldy             eth_unique_id
5160
        iny
5161
        sty             eth_unique_id
5162
        sb              r3,19,r1
5163
        lsr             r3,r3,#8
5164
        sb              r3,18,r1
5165
        lb              r3,14,r1
5166
        and             r3,r3,#0xF
5167
        asl             r3,r3,#2                ; *4
5168
        add             r1,r3,#14               ; return datastart in r1
5169
        pop             r10
5170
        pop             r9
5171
        pop             r8
5172
        pop             r7
5173
        pop             r6
5174
        pop             r5
5175
        pop             r4
5176
        ply
5177
        rts
5178
 
5179
; Compute IPv4 checksum of header
5180
; r1 = packet address
5181
; r2 = data start
5182
;
5183
message "eth_checksum"
5184
eth_checksum:
5185
        phy
5186
        push    r4
5187
        push    r5
5188
        push    r6
5189
        ; set checksum to zero
5190
        stz             24,r1
5191
        stz             25,r1
5192
        eor             r3,r3,r3                ; r3 = sum = zero
5193
        ld              r4,#14
5194
eth15:
5195
        ld              r5,r2
5196
        dec             r5                              ; r5 = datastart - 1
5197
        cmp             r4,r5
5198
        bpl             eth14
5199
        add             r6,r1,r4
5200
        lb              r5,0,r6                 ; shi = [rx_addr+i]
5201
        lb              r6,1,r6             ; slo = [rx_addr+i+1]
5202
        asl     r5,r5,#8
5203
        or              r5,r5,r6                ; shilo
5204
        add             r3,r3,r5                ; sum = sum + shilo
5205
        add             r4,r4,#2                ; i = i + 2
5206
        bra             eth15
5207
eth14:
5208
        ld              r5,r3                   ; r5 = sum
5209
        and             r3,r3,#0xffff
5210
        lsr             r5,r5,#16
5211
        add             r3,r3,r5
5212
        eor             r3,r3,#-1
5213
        sb              r3,25,r1                ; low byte
5214
        lsr             r3,r3,#8
5215
        sb              r3,24,r1                ; high byte
5216
        pop             r6
5217
        pop             r5
5218
        pop             r4
5219
        ply
5220
        rts
5221
 
5222
; r1 = packet address
5223
; returns r1 = 1 if this IP
5224
;
5225
message "eth_verifyIP"
5226
eth_verifyIP:
5227
        phx
5228
        phy
5229
        push    r4
5230
        push    r5
5231
        lb              r2,30,r1
5232
        lb              r3,31,r1
5233
        lb              r4,32,r1
5234
        lb              r5,33,r1
5235
        ; Check for general broadcast
5236
        cmp             r2,#$FF
5237
        bne             eth11
5238
        cmp             r3,#$FF
5239
        bne             eth11
5240
        cmp             r4,#$FF
5241
        bne             eth11
5242
        cmp             r5,#$FF
5243
        bne             eth11
5244
eth12:
5245
        lda             #1
5246
eth13:
5247
        pop             r5
5248
        pop             r4
5249
        ply
5250
        plx
5251
        rts
5252
eth11:
5253
        ld              r1,r2
5254
        asl             r1,r1,#8
5255
        or              r1,r1,r3
5256
        asl             r1,r1,#8
5257
        or              r1,r1,r4
5258
        asl             r1,r1,#8
5259
        or              r1,r1,r5
5260
        cmp             #$C0A8012A              ; 192.168.1.42
5261
        beq             eth12
5262
        eor             r1,r1,r1
5263
        bra             eth13
5264
 
5265 34 robfinch
msgEthTest
5266
        db              CR,LF,"Ethernet test - press CTRL-C to exit.",CR,LF,0
5267
 
5268 26 robfinch
message "eth_main"
5269
eth_main:
5270 34 robfinch
        jsr             RequestIOFocus
5271
        jsr             ClearScreen
5272
        jsr             HomeCursor
5273
        lda             #msgEthTest
5274
        jsr             DisplayStringB
5275
;       jsr             eth_init
5276
        jsr             ethmac_setup
5277 26 robfinch
eth_loop:
5278
        jsr             KeybdGetChar
5279
        cmp             #-1
5280
        beq             eth17
5281
        cmp             #CTRLC
5282
        bne             eth17
5283 34 robfinch
        lda             #$A000                                  ; tunr off transmit/recieve
5284
        sta             ETH_MODER+ETHMAC
5285
        jsr             ReleaseIOFocus
5286 26 robfinch
        rts
5287
eth17
5288
        lda             #eth_rx_buffer<<2               ; memory address zero
5289
        jsr             eth_request_packet
5290
        jsr             eth_interpret_packet    ; r1 = packet type
5291
 
5292
        cmp             #1
5293
        bne             eth10
5294
        ld              r2,r1                                   ; save off r1, r2 = packet type
5295
        lda             #eth_rx_buffer<<2               ; memory address zero
5296
        jsr             eth_verifyIP
5297
        tay
5298
        txa                                                             ; r1 = packet type again
5299
        cpy             #1
5300
        bne             eth10
5301
 
5302
        lda             #eth_rx_buffer<<2               ; memory address zero
5303
        ldx             #1
5304
        jsr             eth_build_packet
5305
        tay                                                             ; y = icmpstart
5306
        lda             #eth_rx_buffer<<2               ; memory address zero
5307
        add             r4,r1,r3
5308
        sb              r0,0,r4                                 ; [rx_addr+icmpstart] = 0
5309
        lb              r2,17,r1
5310
        add             r2,r2,#14                               ; r2 = len
5311
        ld              r6,r2                                   ; r6 = len
5312
        add             r15,r1,r3
5313
        lb              r4,2,r15                                ; shi
5314
        lb              r5,3,r15                                ; slo
5315
        asl             r4,r4,#8
5316
        or              r4,r4,r5                                ; sum = {shi,slo};
5317
        eor             r4,r4,#-1                               ; sum = ~sum
5318
        sub             r4,r4,#0x800                    ; sum = sum - 0x800
5319
        eor             r4,r4,#-1                               ; sum = ~sum
5320
        add             r15,r1,r3
5321
        sb              r4,3,r15
5322
        lsr             r4,r4,#8
5323
        sb              r4,2,r15
5324
        tyx
5325
        jsr             eth_checksum
5326
        lda             #eth_rx_buffer<<2               ; memory address zero
5327
        ld              r2,r6
5328
        jsr             eth_send_packet
5329
        jmp             eth_loop
5330
eth10:
5331
        ; r2 = rx_addr
5332
        cmp             #2
5333
        bne             eth_loop                ; Do we have ARP ?
5334
;       xor             r2,r2,r2                        ; memory address zero
5335
        ldx             #eth_rx_buffer<<2
5336
        ; get the opcode
5337
        lb              r13,21,x
5338
        cmp             r13,#1
5339
        bne             eth_loop                ; ARP request
5340
        ; get destination IP address
5341
        lb              r9,38,x
5342
        lb              r10,39,x
5343
        lb              r11,40,x
5344
        lb              r12,41,x
5345
        ; set r15 = destination IP
5346
        ld              r15,r9
5347
        asl             r15,r15,#8
5348
        or              r15,r15,r10
5349
        asl             r15,r15,#8
5350
        or              r15,r15,r11
5351
        asl             r15,r15,#8
5352
        or              r15,r15,r12
5353
        ; Is it our IP ?
5354
        cmp             r15,#$C0A8012A  ; //192.168.1.42
5355
        bne             eth_loop
5356
        ; get source IP address
5357
        lb              r5,28,x
5358
        lb              r6,29,x
5359
        lb              r7,30,x
5360
        lb              r8,31,x
5361
        ; set r14 = source IP
5362
        ld              r14,r5
5363
        asl             r14,r14,#8
5364
        or              r14,r14,r6
5365
        asl             r14,r14,#8
5366
        or              r14,r14,r7
5367
        asl             r14,r14,#8
5368
        or              r14,r14,r8
5369
        ; Get the source MAC address
5370
        push    r6
5371
        push    r7
5372
        push    r8
5373
        push    r9
5374
        push    r10
5375
        push    r11
5376
        lb              r6,22,x
5377
        lb              r7,23,x
5378
        lb              r8,24,x
5379
        lb              r9,25,x
5380
        lb              r10,26,x
5381
        lb              r11,27,x
5382
        ; write to destination header
5383
        sb              r6,0,x
5384
        sb              r7,1,x
5385
        sb              r8,2,x
5386
        sb              r9,3,x
5387
        sb              r10,4,x
5388
        sb              r11,5,x
5389
        ; and write to ARP destination
5390
        sb              r6,32,x
5391
        sb              r7,33,x
5392
        sb              r8,34,x
5393
        sb              r9,35,x
5394
        sb              r10,36,x
5395
        sb              r11,37,x
5396
        pop             r11
5397
        pop             r10
5398
        pop             r9
5399
        pop             r8
5400
        pop             r7
5401
        pop             r6
5402
        ; write to source header
5403
;       stbc    #0x00,6[r2]
5404
;       stbc    #0xFF,7[r2]
5405
;       stbc    #0xEE,8[r2]
5406
;       stbc    #0xF0,9[r2]
5407
;       stbc    #0xDA,10[r2]
5408
;       stbc    #0x42,11[r2]
5409
        sb              r0,6,x
5410
        lda             #0xFF
5411
        sb              r1,7,x
5412
        lda             #0xEE
5413
        sb              r1,8,x
5414
        lda             #0xF0
5415
        sb              r1,9,x
5416
        lda             #0xDA
5417
        sb              r1,10,x
5418
        lda             #0x42
5419
        sb              r1,11,x
5420
        ; write to ARP source
5421
;       stbc    #0x00,22[r2]
5422
;       stbc    #0xFF,23[r2]
5423
;       stbc    #0xEE,24[r2]
5424
;       stbc    #0xF0,25[r2]
5425
;       stbc    #0xDA,26[r2]
5426
;       stbc    #0x42,27[r2]
5427
        sb              r0,22,x
5428
        lda             #0xFF
5429
        sb              r1,23,x
5430
        lda             #0xEE
5431
        sb              r1,24,x
5432
        lda             #0xF0
5433
        sb              r1,25,x
5434
        lda             #0xDA
5435
        sb              r1,26,x
5436
        lda             #0x42
5437
        sb              r1,27,x
5438
        ; swap sender / destination IP
5439
        ; write sender
5440
        sb              r9,28,x
5441
        sb              r10,29,x
5442
        sb              r11,30,x
5443
        sb              r12,31,x
5444
        ; write destination
5445
        sb              r5,38,x
5446
        sb              r6,39,x
5447
        sb              r7,40,x
5448
        sb              r8,41,x
5449
        ; change request to reply
5450
;       stbc    #2,21[r2]
5451
        lda             #2
5452
        sb              r1,21,x
5453
        txa                                             ; r1 = packet address
5454
        ldx             #0x2A                   ; r2 = packet length
5455
        jsr             eth_send_packet
5456
        jmp             eth_loop
5457
 
5458
;--------------------------------------------------------------------------
5459
; Initialize sprite image caches with random data.
5460
;--------------------------------------------------------------------------
5461 34 robfinch
message "RandomizeSprram"
5462 26 robfinch
RandomizeSprram:
5463
        ldx             #SPRRAM
5464
        ld              r4,#14336               ; number of chars to initialize
5465
rsr1:
5466
        tsr             LFSR,r1
5467
        sta             (x)
5468
        inx
5469
        dec             r4
5470
        bne             rsr1
5471
        rts
5472
 
5473
;--------------------------------------------------------------------------
5474
; Draw random lines on the bitmap screen.
5475
;--------------------------------------------------------------------------
5476
;
5477 34 robfinch
message "RandomLines"
5478 26 robfinch
RandomLines:
5479
        pha
5480
        phx
5481
        phy
5482
        push    r4
5483
        push    r5
5484
        jsr             RequestIOFocus
5485 34 robfinch
        jsr             ClearScreen
5486
        jsr             HomeCursor
5487
        lda             #msgRandomLines
5488
        jsr             DisplayStringB
5489 26 robfinch
rl5:
5490
        tsr             LFSR,r1
5491
        tsr             LFSR,r2
5492 34 robfinch
        tsr             LFSR,r3
5493
        mod             r1,r1,#1364
5494
        mod             r2,r2,#768
5495 26 robfinch
        jsr             DrawPixel
5496
        tsr             LFSR,r1
5497
        sta             LineColor               ; select a random color
5498
rl1:                                            ; random X0
5499
        tsr             LFSR,r1
5500 34 robfinch
        mod             r1,r1,#1364
5501 26 robfinch
rl2:                                            ; random X1
5502
        tsr             LFSR,r3
5503 34 robfinch
        mod             r3,r3,#1364
5504 26 robfinch
rl3:                                            ; random Y0
5505
        tsr             LFSR,r2
5506 34 robfinch
        mod             r2,r2,#768
5507 26 robfinch
rl4:                                            ; random Y1
5508
        tsr             LFSR,r4
5509 34 robfinch
        mod             r4,r4,#768
5510 26 robfinch
rl8:
5511 34 robfinch
        ld              r5,GA_STATE             ; make sure state is IDLE
5512
        bne             rl8
5513 26 robfinch
        jsr             DrawLine
5514
        jsr             KeybdGetChar
5515
        cmp             #CTRLC
5516
        beq             rl7
5517
        bra             rl5
5518
rl7:
5519
        jsr             ReleaseIOFocus
5520
        pop             r5
5521
        pop             r4
5522
        ply
5523
        plx
5524
        pla
5525
        rts
5526
 
5527 34 robfinch
msgRandomLines:
5528
        db              CR,LF,"Random lines running - press CTRL-C to exit.",CR,LF,0
5529
 
5530 28 robfinch
;--------------------------------------------------------------------------
5531
; Draw a pixel on the bitmap screen.
5532
; r1 = x coordinate
5533
; r2 = y coordinate
5534
; r3 = color
5535
;--------------------------------------------------------------------------
5536 34 robfinch
message "DrawPixel"
5537 26 robfinch
DrawPixel:
5538
        pha
5539 34 robfinch
        sta             GA_X0
5540
        stx             GA_Y0
5541
        sty             GA_PEN
5542
        lda             #1
5543
        sta             GA_CMD
5544
        pla
5545
        rts
5546
 
5547
comment ~
5548
        pha
5549 26 robfinch
        phx
5550
        push    r4
5551 34 robfinch
        mod             r2,r2,#768
5552
        mod             r1,r1,#1364
5553
        mul             r2,r2,#1364     ; y * 1364
5554 26 robfinch
        add             r1,r1,r2        ; + x
5555
        sb              r3,BITMAPSCR<<2,r1
5556
        pop             r4
5557
        plx
5558
        pla
5559
        rts
5560 34 robfinch
~
5561 28 robfinch
 
5562
;--------------------------------------------------------------------------
5563
; Draw a line on the bitmap screen.
5564
;--------------------------------------------------------------------------
5565 26 robfinch
;50 REM DRAWLINE
5566
;100 dx = ABS(xb-xa)
5567
;110 dy = ABS(yb-ya)
5568
;120 sx = SGN(xb-xa)
5569
;130 sy = SGN(yb-ya)
5570
;140 er = dx-dy
5571
;150 PLOT xa,ya
5572
;160 if xa<>xb goto 200
5573
;170 if ya=yb goto 300
5574
;200 ee = er * 2
5575
;210 if ee <= -dy goto 240
5576
;220 er = er - dy
5577
;230 xa = xa + sx
5578
;240 if ee >= dx goto 270
5579
;250 er = er + dx
5580
;260 ya = ya + sy
5581
;270 GOTO 150
5582
;300 RETURN
5583
 
5584 34 robfinch
message "DrawLine"
5585 26 robfinch
DrawLine:
5586
        pha
5587 34 robfinch
        sta             GA_X0
5588
        stx             GA_Y0
5589
        sty             GA_X1
5590
        st              r4,GA_Y1
5591
        lda             LineColor
5592
        sta             GA_PEN
5593
        lda             #2
5594
        sta             GA_CMD
5595
        pla
5596
        rts
5597
 
5598
comment ~
5599
        pha
5600 26 robfinch
        phx
5601
        phy
5602
        push    r4
5603
        push    r5
5604
        push    r6
5605
        push    r7
5606
        push    r8
5607
        push    r9
5608
        push    r10
5609
        push    r11
5610
 
5611
        sub             r5,r3,r1        ; dx = abs(x2-x1)
5612
        bpl             dln1
5613
        sub             r5,r0,r5
5614
dln1:
5615
        sub             r6,r4,r2        ; dy = abs(y2-y1)
5616
        bpl             dln2
5617
        sub             r6,r0,r6
5618
dln2:
5619
 
5620
        sub             r7,r3,r1        ; sx = sgn(x2-x1)
5621
        beq             dln5
5622
        bpl             dln4
5623
        ld              r7,#-1
5624
        bra             dln5
5625
dln4:
5626
        ld              r7,#1
5627
dln5:
5628
 
5629
        sub             r8,r4,r2        ; sy = sgn(y2-y1)
5630
        beq             dln8
5631
        bpl             dln7
5632
        ld              r8,#-1
5633
        bra             dln8
5634
dln7:
5635
        ld              r8,#1
5636
 
5637
dln8:
5638
        sub             r9,r5,r6        ; er = dx-dy
5639
dln150:
5640 28 robfinch
        phy
5641
        ldy             LineColor
5642 26 robfinch
        jsr             DrawPixel
5643 28 robfinch
        ply
5644 26 robfinch
        cmp             r1,r3           ; if (xa <> xb)
5645
        bne             dln200          ;    goto 200
5646
        cmp             r2,r4           ; if (ya==yb)
5647
        beq             dln300          ;    goto 300
5648
dln200:
5649
        asl             r10,r9          ; ee = er * 2
5650
        sub             r11,r0,r6       ; r11 = -dy
5651
        cmp             r10,r11         ; if (ee <= -dy)
5652
        bmi             dln240          ;     goto 240
5653
        beq             dln240
5654
        sub             r9,r9,r6        ; er = er - dy
5655
        add             r1,r1,r7        ; xa = xa + sx
5656
dln240:
5657
        cmp             r10,r5          ; if (ee >= dx)
5658
        bpl             dln150          ;    goto 150
5659
        add             r9,r9,r5        ; er = er + dx
5660
        add             r2,r2,r8        ; ya = ya + sy
5661
        bra             dln150          ; goto 150
5662
 
5663
dln300:
5664
        pop             r11
5665
        pop             r10
5666
        pop             r9
5667
        pop             r8
5668
        pop             r7
5669
        pop             r6
5670
        pop             r5
5671
        pop             r4
5672
        ply
5673
        plx
5674
        pla
5675
        rts
5676 34 robfinch
~
5677 26 robfinch
 
5678
;include "float.asm"
5679
 
5680 34 robfinch
;--------------------------------------------------------------------------
5681
; RTF65002 code to display the date and time from the date/time device.
5682
;--------------------------------------------------------------------------
5683
DisplayDatetime
5684
        pha
5685
        phx
5686
        lda             #' '
5687
        jsr             DisplayChar
5688
        stz             DATETIME_SNAPSHOT       ; take a snapshot of the running date/time
5689
        lda             DATETIME_DATE
5690
        tax
5691
        lsr             r1,r1,#16
5692
        jsr             DisplayHalf             ; display the year
5693
        lda             #'/'
5694
        jsr             DisplayChar
5695
        txa
5696
        lsr             r1,r1,#8
5697
        and             #$FF
5698
        jsr             DisplayByte             ; display the month
5699
        lda             #'/'
5700
        jsr             DisplayChar
5701
        txa
5702
        and             #$FF
5703
        jsr             DisplayByte             ; display the day
5704
        lda             #' '
5705
        jsr             DisplayChar
5706
        lda             #' '
5707
        jsr             DisplayChar
5708
        lda             DATETIME_TIME
5709
        tax
5710
        lsr             r1,r1,#24
5711
        jsr             DisplayByte             ; display hours
5712
        lda             #':'
5713
        jsr             DisplayChar
5714
        txa
5715
        lsr             r1,r1,#16
5716
        jsr             DisplayByte             ; display minutes
5717
        lda             #':'
5718
        jsr             DisplayChar
5719
        txa
5720
        lsr             r1,r1,#8
5721
        jsr             DisplayByte             ; display seconds
5722
        lda             #'.'
5723
        jsr             DisplayChar
5724
        txa
5725
        jsr             DisplayByte             ; display 100ths seconds
5726
        jsr             CRLF
5727
        plx
5728
        pla
5729
        rts
5730 31 robfinch
 
5731 34 robfinch
;--------------------------------------------------------------------------
5732
; ReadTemp
5733
;    Read and display the temperature from a DS1626 temperature sensor
5734
; device. RTF65002 source code.
5735
;--------------------------------------------------------------------------
5736
DS1626_CMD      =$FFDC0300
5737
DS1626_DAT      =$FFDC0301
5738
; Commands
5739
START_CNV = $51;
5740
STOP_CNV = $22;
5741
READ_TEMP = $AA;
5742
READ_CONFIG = $AC;
5743
READ_TH = $A1;
5744
READ_TL = $A2;
5745
WRITE_TH = $01;
5746
WRITE_TL = $02;
5747
WRITE_CONFIG = $0C;
5748
POR = $54;
5749
 
5750
ReadTemp:
5751
        lda             CONFIGREC       ; Do we even have a temperature sensor ?
5752
        bit             #$10
5753
        beq             rdtmp3          ; If not, output '0.000'
5754
rdtmp1:
5755
        ; On power up the DS1626 interface circuit sends a power on reset (POR)
5756
        ; command to the DS1626. Waiting here makes sure this command has been
5757
        ; completed.
5758
        jsr             rdt_busy_wait
5759
        lda             #$0F                    ; 12 bits resolution, cpu mode, one-shot mode
5760
        sta             DS1626_DAT
5761
        lda             #WRITE_CONFIG   ; write the desired config to the device
5762
        sta             DS1626_CMD
5763
        jsr             rdt_busy_wait
5764
        lda             #10
5765
        jsr             tSleep
5766
        lda             #0
5767
        sta             DS1626_DAT
5768
        lda             #START_CNV              ; issue a start conversion command
5769
        sta             DS1626_CMD
5770
        jsr             rdt_busy_wait
5771
        lda             #10
5772
        jsr             tSleep
5773
        ; Now poll the config register to determine when the conversion has completed.
5774
rdtmp2:
5775
        lda             #READ_CONFIG    ; issue the READ_CONFIG command
5776
        sta             DS1626_CMD
5777
        jsr             rdt_busy_wait
5778
        pha
5779
        lda             #10                             ; Wait a bit before checking again. The conversion
5780
        jsr             tSleep                  ; can take up to 1s to complete.
5781
        pla
5782
        bit             #$80                    ; test done bit
5783
        beq             rdtmp2                  ; loop back if not done conversion
5784
        lda             #0
5785
        sta             DS1626_DAT              ; issue a stop conversion command
5786
        lda             #STOP_CNV
5787
        sta             DS1626_CMD
5788
        jsr             rdt_busy_wait
5789
        lda             #10
5790
        jsr             tSleep
5791
        lda             #READ_TEMP              ; issue the READ_TEMP command
5792
        sta             DS1626_CMD
5793
        jsr             rdt_busy_wait
5794
        pha
5795
        lda             #10
5796
        jsr             tSleep
5797
        pla
5798
rdtmp4:
5799
        jsr             CRLF
5800
        and             #$FFF
5801
        bit             #$800           ; check for negative temperature
5802
        beq             rdtmp7
5803
        sub             r1,r0,r1        ; negate the number
5804
        and             #$FFF
5805
        pha
5806
        lda             #'-'            ; output a minus sign
5807
        jsr             DisplayChar
5808
        pla
5809
rdtmp7:
5810
        pha                                     ; save off value
5811
        lsr             r1,r1,#4        ; get rid of fractional portion
5812
        and             #$7F            ; strip off sign bit
5813
        ldx             #3                      ; output the whole number part
5814
        jsr             PRTNUM
5815
        lda             #'.'            ; followed by a decimal point
5816
        jsr             DisplayChar
5817
        pla                                     ; get back temp value
5818
        and             #$0F
5819
        mul             r1,r1,#625      ; 1/16th's per degree
5820
        pha                                     ; save off fraction bits
5821
        div             r1,r1,#100      ; calculate the first digit
5822
        add             #'0'
5823
        jsr             DisplayChar     ; output digit
5824
        pla                                     ; get back fractions bits
5825
        pha                                     ; and save again
5826
        div             r1,r1,#10       ; shift over to second digit
5827
        mod             r1,r1,#10       ; ignore high order bits
5828
        add             #'0'
5829
        jsr             DisplayChar     ; display the digit
5830
        pla                                     ; get back fraction
5831
        mod             r1,r1,#10       ; compute low order digit
5832
        add             #'0'
5833
        jsr             DisplayChar     ; display low order digit
5834
        jsr             CRLF
5835
        rts
5836
rdtmp3:
5837
        lda             #0
5838
        bra             rdtmp4
5839
 
5840
; Returns:
5841
;       acc = value from data register
5842
;
5843
rdt_busy_wait:
5844
        jsr             KeybdGetChar
5845
        cmp             #CTRLC
5846
        beq             Monitor
5847
        lda             DS1626_DAT
5848
        bit             #$8000
5849
        bne             rdt_busy_wait
5850
        rts
5851
 
5852
tSleep:
5853
        ldx             Milliseconds
5854
        txa
5855
tSleep1:
5856
        ldx             Milliseconds
5857
        sub             r2,r2,r1
5858
        cpx             #100
5859
        blo             tSleep1
5860
        rts
5861
 
5862 31 robfinch
;==============================================================================
5863
; Memory Management routines follow.
5864
;==============================================================================
5865
MemInit:
5866
        lda             #1                                      ; initialize memory semaphore
5867
        sta             MEM_SEMA
5868
        lda             #$4D454D20
5869
        sta             HeapStart+MEM_CHK
5870
        sta             HeapStart+MEM_FLAG
5871
        sta             HeapEnd-2
5872
        sta             HeapEnd-3
5873
        lda             #0
5874
        sta             HeapStart+MEM_PREV      ; prev of first MEMHDR
5875
        sta             HeapEnd                 ; next of last MEMHDR
5876
        lda             #HeapEnd
5877
        ina
5878
        sub             #$4
5879
        sta             HeapStart+MEM_NEXT      ; next of first MEMHDR
5880
        lda             #HeapStart
5881
        sta             HeapEnd-1               ; prev of last MEMHDR
5882
        rts
5883
 
5884
ReportMemFree:
5885
        jsr             CRLF
5886
        lda             #HeapEnd
5887
        ina
5888
        sub             #HeapStart
5889
        ldx             #5
5890
        jsr             PRTNUM
5891
        lda             #msgMemFree
5892
        jsr             DisplayStringB
5893
        rts
5894
 
5895
msgMemFree:
5896
        db      " words free",CR,LF,0
5897
 
5898 15 robfinch
;------------------------------------------------------------------------------
5899 31 robfinch
; Allocate memory from the heap.
5900
;------------------------------------------------------------------------------
5901
MemAlloc:
5902
        phx
5903
        phy
5904
        push    r4
5905
memaSpin:
5906
        ldx             MEM_SEMA+1
5907
        beq             memaSpin
5908
        ldx             #HeapStart
5909
mema4:
5910
        ldy             MEM_FLAG,x              ; Check the flag word to see if this block is available
5911
        cpy             #$4D454D20
5912
        bne             mema1                   ; block not available, go to next block
5913
        ld              r4,MEM_NEXT,x   ; compute the size of this block
5914
        sub             r4,r4,r2
5915
        sub             r4,r4,#4                ; minus size of block header
5916
        cmp             r1,r4                   ; is the block large enough ?
5917
        bmi             mema2                   ; if yes, go allocate
5918
mema1:
5919
        ldx             MEM_NEXT,x              ; go to the next block
5920
        beq             mema3                   ; if no more blocks, out of memory error
5921
        bra             mema4
5922
mema2:
5923
        ldy             #$6D656D20
5924
        sty             MEM_FLAG,x
5925
        sub             r4,r4,r1
5926
        cmp             r4,#4                   ; is the block large enough to split
5927
        bpl             memaSplit
5928
        stz             MEM_SEMA+1
5929
        txa
5930
        pop             r4
5931
        ply
5932
        plx
5933
        rts
5934
mema3:                                          ; insufficient memory
5935
        stz             MEM_SEMA+1
5936
        pop             r4
5937
        ply
5938
        plx
5939
        lda             #0
5940
        rts
5941
memaSplit:
5942
        add             r4,r1,r2
5943
        add             r4,r4,#4
5944
        ldy             #$4D454D20
5945
        sty             (r4)
5946
        sty             MEM_FLAG,r4
5947
        stx             MEM_PREV,r4
5948
        ldy             MEM_NEXT,x
5949
        sty             MEM_NEXT,r4
5950
        st              r4,MEM_PREV,y
5951
        ld              r1,r4
5952
        stz             MEM_SEMA+1
5953
        pop             r4
5954
        ply
5955
        plx
5956
        rts
5957
 
5958
;------------------------------------------------------------------------------
5959
; Free previously allocated memory. Recombine with next and previous blocks
5960
; if they are free as well.
5961
;------------------------------------------------------------------------------
5962
MemFree:
5963
        cmp             #0                      ; null pointer ?
5964
        beq             memf2
5965
        phx
5966
        phy
5967
memfSpin:
5968
        ldx             MEM_SEMA+1
5969
        beq             memfSpin
5970
        ldx             MEM_FLAG,r1
5971
        cpx             #$6D656D20      ; is the block allocated ?
5972
        bne             memf1
5973
        ldx             #$4D454D20
5974
        stx             MEM_FLAG,r1     ; mark block as free
5975
        ldx             MEM_PREV,r1     ; is the previous block free ?
5976
        beq             memf3           ; no previous block
5977
        ldy             MEM_FLAG,x
5978
        cpy             #$4D454D20
5979
        bne             memf3           ; the previous block is not free
5980
        ldy             MEM_NEXT,r1
5981
        sty             MEM_NEXT,x
5982
        beq             memf1           ; no next block
5983
        stx             MEM_PREV,y
5984
memf3:
5985
        ldy             MEM_NEXT,r1
5986
        ldx             MEM_FLAG,y
5987
        cpx             #$4D454D20
5988
        bne             memf1           ; next block not free
5989
        ldx             MEM_PREV,r1
5990
        stx             MEM_PREV,y
5991
        beq             memf1           ; no previous block
5992
        sty             MEM_NEXT,x
5993
memf1:
5994
        stz             MEM_SEMA+1
5995
        ply
5996
        plx
5997
memf2:
5998
        rts
5999
 
6000
;------------------------------------------------------------------------------
6001 26 robfinch
; Bus Error Routine
6002
; This routine display a message then restarts the BIOS.
6003
;------------------------------------------------------------------------------
6004
;
6005
message "bus_err_rout"
6006
bus_err_rout:
6007
        cld
6008 34 robfinch
        ldx             #87
6009
        stx             LEDS
6010 26 robfinch
        pla                                                     ; get rid of the stacked flags
6011
        ply                                                     ; get the error PC
6012
        ldx             #$05FFFFF8                      ; setup stack pointer top of memory
6013
        txs
6014 34 robfinch
        ldx             #88
6015
        stx             LEDS
6016 26 robfinch
        jsr             CRLF
6017 34 robfinch
        stz             RunningTCB
6018
        stz             IOFocusNdx
6019 26 robfinch
        lda             #msgBusErr
6020
        jsr             DisplayStringB
6021
        tya
6022
        jsr             DisplayWord                     ; display the originating PC address
6023
        lda             #msgDataAddr
6024
        jsr             DisplayStringB
6025
        tsr             #9,r1
6026
        jsr             DisplayWord
6027 34 robfinch
        ldx             #89
6028
        stx             LEDS
6029
        ldx             #128
6030
ber2:
6031
        lda             #' '
6032
        jsr             DisplayChar
6033
        tsr             hist,r1
6034
        jsr             DisplayWord
6035
        dex
6036
        bne             ber2
6037
        jsr             CRLF
6038
ber3:
6039
        nop
6040
        jmp             ber3
6041
        ;cli                                                    ; enable interrupts so we can get a char
6042 28 robfinch
ber1:
6043 34 robfinch
        jsr             KeybdGetCharDirect      ; Don't use the keyboard buffer
6044 28 robfinch
        cmp             #-1
6045
        beq             ber1
6046 34 robfinch
        lda             RunningTCB
6047
        jsr             KillTask
6048
        jmp             SelectTaskToRun
6049 26 robfinch
 
6050
msgBusErr:
6051
        db              "Bus error at: ",0
6052
msgDataAddr:
6053
        db              " data address: ",0
6054
 
6055 34 robfinch
 
6056
;------------------------------------------------------------------------------
6057
; Reschedule tasks to run without affecting the timeout list timing.
6058
;------------------------------------------------------------------------------
6059
;
6060
reschedule:
6061
        cld             ; clear extended precision mode
6062
 
6063
        pusha   ; save off regs on the stack
6064
 
6065
        ldx             RunningTCB
6066
        tsa                                             ; save off the stack pointer
6067
        sta             TCB_SPSave,x
6068
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
6069
        sta             TCB_SP8Save,x
6070
        tsr             abs8,r1
6071
        sta             TCB_ABS8Save,x  ; 8 bit emulation base register
6072
        jmp             SelectTaskToRun
6073
 
6074 26 robfinch
strStartQue:
6075 34 robfinch
        db              1,0,0,0,2,0,0,0,3,0,1,0,4,0,0,0
6076 31 robfinch
;       db              0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
6077 26 robfinch
 
6078
;------------------------------------------------------------------------------
6079 15 robfinch
; 100 Hz interrupt
6080
; - takes care of "flashing" the cursor
6081 34 robfinch
; - decrements timeouts for tasks on timeout list
6082 26 robfinch
; - switching tasks
6083 15 robfinch
;------------------------------------------------------------------------------
6084
;
6085
p100Hz:
6086 26 robfinch
        ; Handle every other interrupt because 100Hz interrupts may be too fast.
6087
        pha
6088 31 robfinch
        lda             #3                              ; reset the edge sense circuit
6089
        sta             PIC_RSTE
6090 26 robfinch
        lda             IRQFlag
6091
        ina
6092
        sta             IRQFlag
6093
        ror
6094 34 robfinch
        pla
6095 26 robfinch
        bcc             p100Hz11
6096
        rti
6097
 
6098
p100Hz11:
6099
 
6100
        cld             ; clear extended precision mode
6101
 
6102 34 robfinch
        pusha   ; save off regs on the stack
6103
 
6104 26 robfinch
        ldx             RunningTCB
6105
        tsa                                             ; save off the stack pointer
6106
        sta             TCB_SPSave,x
6107
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
6108
        sta             TCB_SP8Save,x
6109 31 robfinch
        tsr             abs8,r1
6110
        sta             TCB_ABS8Save,x  ; 8 bit emulation base register
6111 34 robfinch
        lda             #TS_READY
6112 28 robfinch
        sta             TCB_Status,x
6113 31 robfinch
p100Hz4:
6114 26 robfinch
 
6115
        ; support EhBASIC's IRQ functionality
6116
        ; code derived from minimon.asm
6117
        lda             #3                              ; Timer is IRQ #3
6118
        sta             IrqSource               ; stuff a byte indicating the IRQ source for PEEK()
6119
        lb              r1,IrqBase              ; get the IRQ flag byte
6120 31 robfinch
        lsr             r4,r1
6121
        or              r1,r1,r4
6122 26 robfinch
        and             #$E0
6123
        sb              r1,IrqBase
6124
 
6125 34 robfinch
        inc             TEXTSCR+55              ; update IRQ live indicator on screen
6126 26 robfinch
 
6127
        ; flash the cursor
6128 34 robfinch
        cpx             IOFocusNdx              ; only bother to flash the cursor for the task with the IO focus.
6129 31 robfinch
        bne             p100Hz1a
6130 26 robfinch
        lda             CursorFlash             ; test if we want a flashing cursor
6131
        beq             p100Hz1a
6132
        jsr             CalcScreenLoc   ; compute cursor location in memory
6133
        tay
6134
        lda             $10000,y                ; get color code $10000 higher in memory
6135 31 robfinch
        ld              r4,IRQFlag              ; get counter
6136
        lsr             r4,r4
6137
        and             r4,r4,#$0F              ; limit to low order nybble
6138 26 robfinch
        and             #$F0                    ; prepare to or in new value, mask off foreground color
6139 31 robfinch
        or              r1,r1,r4                ; set new foreground color for cursor
6140 26 robfinch
        sta             $10000,y                ; store the color code back to memory
6141
p100Hz1a
6142
 
6143
        ; Check the timeout list to see if there are items ready to be removed from
6144
        ; the list. Also decrement the timeout of the item at the head of the list.
6145
 
6146
p100Hz15:
6147
        ldx             TimeoutList
6148
        bmi             p100Hz12                                ; are there any entries in the timeout list ?
6149
        lda             TCB_Timeout,x
6150
        bne             p100Hz14                                ; has this entry timed out ?
6151
        txa
6152
        jsr             RemoveFromTimeoutList
6153
        jsr             AddTaskToReadyList
6154
        bra             p100Hz15                                ; go back and see if there's another task to be removed
6155 34 robfinch
                                                                        ; there could be a string of tasks to make ready.
6156 26 robfinch
p100Hz14:
6157 31 robfinch
        dea                                                             ; decrement the entry's timeout
6158 26 robfinch
        sta             TCB_Timeout,x
6159
 
6160
p100Hz12:
6161 34 robfinch
        ; Falls through into selecting a task to run
6162
 
6163
;------------------------------------------------------------------------------
6164
; Search the ready queues for a ready task.
6165
; The search is occasionally started at a lower priority queue in order
6166
; to prevent starvation of lower priority tasks. This is managed by
6167
; using a tick count as an index to a string containing the start que.
6168
;------------------------------------------------------------------------------
6169
;
6170 26 robfinch
SelectTaskToRun:
6171
        ld              r6,#5                   ; number of queues to search
6172
        ldy             IRQFlag                 ; use the IRQFlag as a buffer index
6173
        lsr             r3,r3,#1                ; the LSB is always the same
6174
        and             r3,r3,#$0F              ; counts from 0 to 15
6175
        lb              r3,strStartQue,y        ; get the queue to start search at
6176 34 robfinch
sttr2:
6177
        lda             QNdx0,y
6178
        bmi             sttr1
6179
        lda             TCB_NxtRdy,r1           ; Advance the queue index
6180
        sta             QNdx0,y
6181
        ; This is the only place the RunningTCB is set (except for initialization).
6182 26 robfinch
        sta             RunningTCB
6183 34 robfinch
        ldx             #TS_RUNNING                     ; flag the task as the running task
6184 26 robfinch
        stx             TCB_Status,r1
6185 34 robfinch
        ; The mmu map better have the task control block area mapped
6186
        ; properly.
6187
        tax
6188
        lda             CONFIGREC
6189
        bit             #4096
6190
        beq             sttr4
6191
        lda             TCB_mmu_map,x
6192
        sta             MMU_OKEY                        ; select the mmu map for the task
6193
        lda             #2
6194
        sta             MMU_FUSE                        ; set fuse to 2 clocks before mapping starts
6195
sttr4:
6196 31 robfinch
        lda             TCB_ABS8Save,x          ; 8 bit emulation base register
6197 34 robfinch
        trs             r0,abs8
6198 26 robfinch
        lda             TCB_SP8Save,x           ; get back eight bit stack pointer
6199
        trs             r1,sp8
6200
        ldx             TCB_SPSave,x            ; get back stack pointer
6201
        txs
6202 34 robfinch
        popa                                            ; restore registers
6203 15 robfinch
        rti
6204
 
6205 34 robfinch
        ; Set index to check the next ready list for a task to run
6206
sttr1:
6207
        iny
6208
        cpy             #5
6209
        bne             sttr5
6210
        ldy             #0
6211
sttr5
6212
        dec             r6
6213
        bne             sttr2
6214 26 robfinch
 
6215 34 robfinch
        ; Here there were no tasks ready
6216
        ; This should not be able to happen, so hang the machine.
6217
sttr3:
6218
        ldx             #94
6219
        stx             LEDS
6220
        bra             sttr3
6221
 
6222 15 robfinch
;------------------------------------------------------------------------------
6223
; 1000 Hz interrupt
6224
; This IRQ must be fast.
6225 26 robfinch
; Increments the millisecond counter
6226 15 robfinch
;------------------------------------------------------------------------------
6227
;
6228
p1000Hz:
6229 31 robfinch
        pha
6230
        lda             #2                                              ; reset edge sense circuit
6231
        sta             PIC_RSTE
6232 15 robfinch
        inc             Milliseconds                    ; increment milliseconds count
6233 31 robfinch
        pla
6234 15 robfinch
        rti
6235
 
6236 31 robfinch
;------------------------------------------------------------------------------
6237
; Sleep interrupt
6238
; This interrupt just selects another task to run. The current task is
6239
; stuck in an infinite loop.
6240
;------------------------------------------------------------------------------
6241 15 robfinch
slp_rout:
6242 31 robfinch
        cld             ; clear extended precision mode
6243 34 robfinch
        pusha
6244
        lda             RunningTCB
6245
        cmp             #MAX_TASKNO
6246
        bhi             slp1
6247
        jsr             RemoveTaskFromReadyList
6248
        tax
6249 31 robfinch
        tsa                                             ; save off the stack pointer
6250
        sta             TCB_SPSave,x
6251
        tsr             sp8,r1                  ; and the eight bit mode stack pointer
6252
        sta             TCB_SP8Save,x
6253 34 robfinch
        tsr             abs8,r1
6254
        sta             TCB_ABS8Save,x
6255
        lda             #TS_SLEEP               ; set the task status to SLEEP
6256 31 robfinch
        sta             TCB_Status,x
6257
slp1:
6258
        jmp             SelectTaskToRun
6259
 
6260
;------------------------------------------------------------------------------
6261
; Check for and emulate unsupoorted instructions.
6262
;------------------------------------------------------------------------------
6263
InvalidOpIRQ:
6264
        pha
6265
        phx
6266
        phy
6267
        tsx
6268
        lda             4,x             ; get the address of the invalid op off the stack
6269
        lb              r3,0,r1 ; get the opcode byte
6270
        cpy             #$44    ; is it MVP ?
6271
        beq             EmuMVP
6272
        cpy             #$54    ; is it MVN ?
6273
        beq             EmuMVN
6274
        ; We don't know what the op is. Treat it like a NOP
6275
        ; Increment the address and return.
6276
        pha
6277
        lda             #msgUnimp
6278
        jsr             DisplayStringB
6279
        pla
6280
        jsr             DisplayWord
6281
        jsr             CRLF
6282
        ina
6283
        sta             4,x             ; save incremented return address back to stack
6284
        ldx             #64
6285
ioi1:
6286 34 robfinch
        tsr             hist,r1
6287 31 robfinch
        jsr             DisplayWord
6288
        lda             #' '
6289
        jsr             DisplayChar
6290
        dex
6291
        bne             ioi1
6292
        jsr             CRLF
6293
        ply
6294
        plx
6295
        pla
6296 15 robfinch
        rti
6297 31 robfinch
 
6298
EmuMVP:
6299
        push    r4
6300
        push    r5
6301
        tsr             sp,r4
6302
        lda             4,r4
6303
        ldx             3,r4
6304
        ldy             2,r4
6305
EmuMVP1:
6306
        ld              r5,(x)
6307
        st              r5,(y)
6308
        dex
6309
        dey
6310
        dea
6311
        cmp             #$FFFFFFFF
6312
        bne             EmuMVP1
6313
        sta             4,r4
6314
        stx             3,r4
6315
        sty             2,r4
6316
        inc             6,r4            ; increment the return address by one.
6317
        pop             r5
6318
        pop             r4
6319
        ply
6320
        plx
6321
        pla
6322
        rti
6323
 
6324
EmuMVN:
6325
        push    r4
6326
        push    r5
6327
        tsr             sp,r4
6328
        lda             4,r4
6329
        ldx             3,r4
6330
        ldy             2,r4
6331
EmuMVN1:
6332
        ld              r5,(x)
6333
        st              r5,(y)
6334
        inx
6335
        iny
6336
        dea
6337
        cmp             #$FFFFFFFF
6338
        bne             EmuMVN1
6339
        sta             4,r4
6340
        stx             3,r4
6341
        sty             2,r4
6342
        inc             6,r4            ; increment the return address by one.
6343
        pop             r5
6344
        pop             r4
6345
        ply
6346
        plx
6347
        pla
6348
        rti
6349
 
6350
msgUnimp:
6351
        db      "Unimplemented at: ",0
6352
 
6353 15 robfinch
brk_rout:
6354
        rti
6355 31 robfinch
nmirout:
6356
        pha
6357
        phx
6358
        lda             #msgPerr
6359
        jsr             DisplayStringB
6360
        tsx
6361
        lda             4,x
6362
        jsr             DisplayWord
6363
        jsr             CRLF
6364
        plx
6365
        pla
6366 11 robfinch
        rti
6367 31 robfinch
 
6368
msgPerr:
6369
        db      "Parity error at: ",0
6370
 
6371 15 robfinch
message "1298"
6372
include "TinyBasic65002.asm"
6373 18 robfinch
message "1640"
6374 11 robfinch
        org $0FFFFFFF4          ; NMI vector
6375
        dw      nmirout
6376
 
6377
        org     $0FFFFFFF8              ; reset vector, native mode
6378
        dw      start
6379
 
6380
        end
6381
 

powered by: WebSVN 2.1.0

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