-
Notifications
You must be signed in to change notification settings - Fork 1
/
shell.s
179 lines (169 loc) · 6.62 KB
/
shell.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
.export ShellMain
.importzp R0, R1, R2, R3
.import UartInit, UartRxBufRead, UartTxBufWrite, UartTxStr
.import TermNewline
.import LifeMain
.import BLINKEN, BLINKSRC
.import StrEq
.import SidPlay, SidPause
.segment "bss"
cmdbuf: .res 256
cmdbuf_pos: .res 1
.segment "os"
welcome: .byte "Welcome to pda6502v2", $0D, $0A, $00
prompt: .byte "> ", $00
helpmsg: .byte "Available commands:", $0D, $0A
.byte " hello: just being friendly", $0D, $0A
.byte " help: this message", $0D, $0A
.byte " life: conway's game of life (ctrl-c to interrupt)", $0D, $0A
.byte " spi: send a greeting over SPI", $0D, $0A
.byte " tunes: SID tunes", $0D, $0A
.byte " pause: stop SID tunes", $0D, $0A
.byte $00
e_notfound: .byte "command not found", $0D, $0A, $00
cmdhelp: .byte "help", $00
cmdhello: .byte "hello", $00
cmdlife: .byte "life", $00
cmdspi: .byte "spi", $00
cmdtunes: .byte "tunes", $00
cmdpause: .byte "pause", $00
.proc ShellMain
JSR UartInit
JSR ShellHello
JSR ShellPrompt
RTS
.endproc
.proc ShellHello
JSR TermNewline
LDX #<welcome
LDY #>welcome
JSR UartTxStr
RTS
.endproc
.proc ShellPrompt
LDA #$AA
STA BLINKEN
;LDA #0
;STA BLINKSRC
LDA #0
STA cmdbuf_pos ; init cmdbuf position
showprompt: LDX #<prompt
LDY #>prompt
JSR UartTxStr
eachchar: LDA cmdbuf_pos
;STA BLINKEN
SEC ; UartRxBufRead blocking mode
JSR UartRxBufRead ; A <- rxbuf after waiting
TAY ; Y <- A (spare copy)
CMP #$08 ; ASCII backspace
BEQ backspace
CMP #$0D ; ASCII carriage return (CR, \r)
BEQ newline
CMP #$0A ; ASCII new line (LF, \n)
BEQ newline
default: LDX cmdbuf_pos
STA cmdbuf,X ; append received byte onto cmdbuf
INC cmdbuf_pos ; TODO: check overflow
JSR UartTxBufWrite
JMP chardone
backspace: LDX cmdbuf_pos ; check position in cmdbuf...
BEQ chardone ; if it's zero, don't backspace.
DEC cmdbuf_pos ; shorten cmdbuf by one
JSR UartTxBufWrite ; print the backspace to move cursor back
LDA #' '
JSR UartTxBufWrite ; then a space to overwrite the char being backspaced
TYA
JSR UartTxBufWrite ; then another backspace
JMP chardone
newline: LDA #$0D ; CR
JSR UartTxBufWrite
LDA #$0A ; LF
JSR UartTxBufWrite
LDX cmdbuf_pos ; check if cmdbuf is empty..
BEQ showprompt ; then jump back to show a fresh prompt.
LDA #0 ; else null-terminate cmdbuf..
LDX cmdbuf_pos
STA cmdbuf,X
JSR ShellCmd ; .. and evaluate command
LDX #0 ;
STX cmdbuf_pos ; reset position in cmdbuf to empty
JMP showprompt ; and then jump back to show a fresh prompt.
chardone: JMP eachchar ; again, forever
return: RTS ; this never happens
.endproc
.proc ShellCmd
LDX #<cmdbuf ; R0,R1 pointer to cmdbuf...
STX R0
LDX #>cmdbuf
STX R1
LDX #<cmdhelp ; R2,R3 pointer to cmdhelp...
STX R2
LDX #>cmdhelp
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ help
LDX #<cmdhello ; R2,R3 pointer to cmdhello...
STX R2
LDX #>cmdhello
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ hello
LDX #<cmdlife ; R2,R3 pointer to cmdlife...
STX R2
LDX #>cmdlife
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ life
LDX #<cmdspi ; R2,R3 pointer to cmdspi...
STX R2
LDX #>cmdspi
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ spi
LDX #<cmdtunes ; R2,R3 pointer to cmdtunes...
STX R2
LDX #>cmdtunes
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ tunes
LDX #<cmdpause ; R2,R3 pointer to cmdpause...
STX R2
LDX #>cmdpause
STX R3
JSR StrEq ; compare (R0) and (R2)
BEQ pause
JMP default ; cmdbuf didn't match any commands
help: LDX #<helpmsg
LDY #>helpmsg
JSR UartTxStr
JMP return
hello: LDX #<welcome
LDY #>welcome
JSR UartTxStr
JMP return
life: JSR LifeMain
JMP return
spi: JSR ShellSPI
JMP return
tunes: JSR SidPlay
JMP return
pause: JSR SidPause
JMP return
default: LDX #<e_notfound
LDY #>e_notfound
JSR UartTxStr
return: RTS
.endproc
.proc ShellSPI
LDA #1<<0
TRB $DE10 ; SPI CS[0] active low
LDX #0
eachchar: LDA welcome,X ; 4 cycles ] Total:
BEQ done ; 2 cycles ] 15 cycles
STA $DE11 ; SPI data 4 cycles ] 3.75 µs per byte @ 4 MHz
INX ; 2 cycles ] 260 KiB/sec @ 4 MHz
JMP eachchar ; 3 cycles ] (bottleneck: 6502, not SPI clock)
done: LDA #1<<0
TSB $DE10 ; release SPI CS[0]
RTS
.endproc