-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboot.asm
319 lines (299 loc) · 6.83 KB
/
boot.asm
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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
* = $8000
#define clk_count $00
#define spi_in $01
#define spi_out $02
#define out_buf $03
#define in_buf $04
#define out_count $05
#define txt_buffer $0200
#define incoming_ch $06
#define cmd_count $07
#define str_base $08
#define cmp_base $0A
#define temp_addr $0C
#define inbuf_count $0E
#define inbuf_ptr $0F
#define inbuf $0300
#define cmd_count $10
#define cmd_buffer $0400
#define in_reg $4000
#define out_reg $FFFF
#define clock_pin_mask $01
#define din_pin_mask $02
#define dout_pin_mask $01
START CLV ;Clear overflow, disable emulation mode
CLC
XCE
LDA #$01 ;Set stack pointer to $01FF (grows downward)
XBA
LDA #$FF
TCS
JMP @MAINL ;go to the main application
PROMT .asc "-->"
.byte $0
HLMSG .asc "Hello to you too!"
.byte $A, $0
LDMSG .asc "LOAD not implemented yet."
.byte $A, $0
EXMSG .asc "."
.byte $A, $0
#define command_count $03
cmd_str_table .word hello_string
.word load_string
cmd_ptr_table .word HLOCM
.word LODCM
.word EXACM
hello_string .asc "hello"
.byte $0
load_string .asc "load"
.byte $0
ex_string .asc "x"
.byte $0
int_str .asc "INTERRUPT"
.byte $0A, $00
DOSPI PHX
LDA #$00 ;reset byte counter
STA clk_count
WFLO LDA in_reg ;check clock pin
AND #clock_pin_mask
BNE WFLO ;if clock was not low, check it again
SETOB LDA out_buf ;set spi out pin from spi_out buffer
AND #$FE
STA out_buf
LDA spi_out
AND #dout_pin_mask
ORA out_buf ;A = (out_buf & 0xFE) | (spi_out & 0x01)
STA out_buf ;Save computed out reg value
STA out_reg ;Output computed out reg value
LSR spi_out ;shift spi_out to the right
WFHI LDA in_reg ;check clock pin
STA in_buf ;save the value in case we need to get the data line value
AND #clock_pin_mask
BEQ WFHI ;if it wasn't high check it again
LDA in_buf ;if it was high, check what the value of the data pin was
AND #din_pin_mask
BEQ CLRB ;if it was low, jump to clear the buffer lsb
LDA spi_in ;otherwise, set the buffer lsb
ORA #$01
CLV
BVC CHKDN
CLRB LDA spi_in ;clear the buffer lsb
AND #$FE
CHKDN STA spi_in ;write the modified spi_in buffer back to memory
LDY clk_count ;load and increment the clock counter
INY
TYA ;store updated counter
STA clk_count
CMP #$08 ;check to see if we've read eight bits yet
BEQ SPIDN ;if so, jump to return section
ASL spi_in ;otherwise, shift the input spi buffer and get the next bit
CLV
BVC WFLO
SPIDN PLX
RTL ;full byte has been transfered, return to the caller
OUTCH PHX
LDX out_count
CPX #$FF
BEQ OCHDN ;if the out buffer is full, bail out
STA txt_buffer,X
INX
STX out_count
OCHDN PLX
RTL
PRNTS PHY
STA str_base
XBA
STA str_base + 1
LDY #$00
CLV
PRTOP LDA (str_base),Y
BEQ PRDN
JSR @OUTCH
INY ;Cleverly, this should force us to also exit if and when Y wraps
BVC PRTOP
PRDN PLY
RTL
HLOCM PHA
PHX
LDA #HLMSG/256
XBA
LDA #HLMSG&255
JSR @PRNTS
PLX
PLA
RTS
LODCM PHA
PHX
LDA #LDMSG/256
XBA
LDA #LDMSG&255
JSR @PRNTS
PLX
PLA
RTS
EXACM PHA
PHX
LDA #EXMSG/256
XBA
LDA #EXMSG&255
JSR @PRNTS
PLX
PLA
RTS
STCMP PHY
STA str_base
XBA
STA str_base + 1
STY cmp_base
STX cmp_base + 1
LDY #$00
CLV
SEC
SCTOP LDA (str_base),Y
CMP (cmp_base),Y
BNE CBLK ;If they don't match, double-check for end-of-string vs space
CMP #$00
BEQ SCDN ;If both are zero, exit success
INY ;Cleverly, this should force us to also exit if and when Y wraps
BVC SCTOP
CBLK CMP #00 ;Compare base string to null character
BNE CSWP ;Not null, go check the other way around
CPY #$20 ;base = 0 && cmp = ' '?
BNE SCFL ; no, fail
BVC SCDN ; yes, success
CSWP CPY #00 ;Switch the comparison (check blank in cmp string)
BNE SCFL ; neither is null, fail
CMP #$20 ;cmp = 0 && base = ' '?
BEQ SCDN ; yes, success
; no, fail through
SCFL CLC
SCDN PLY
RTL
RDCHR PHX
LDX inbuf_ptr
CPX inbuf_count
BNE DORD
LDA #$00
CLV
BVC RDEXT
DORD LDA inbuf,X
INX
STX inbuf_ptr
RDEXT PLX
RTL
PARSE PHX
PHY
LDX cmd_count
CPX #$FF
BEQ CHECK
CMP #$0A
BEQ CHECK
STA cmd_buffer,X
INX
STX cmd_count
CLV
BVC PRSDN
CHECK PHA
LDA #$00
STA cmd_buffer,X ;We'll parse this some day
LDX #>cmd_buffer
LDY #$00
STY cmd_count
CMPLP
LDY cmd_count
CPY #command_count*2
BEQ PRPMT
LDA cmd_str_table,Y
XBA
INY
LDA cmd_str_table,Y
INY
XBA
STY cmd_count
LDY #<cmd_buffer
JSR @STCMP
BCC CMPLP
LDA cmd_count
SBC #$02
TAX
JSR (cmd_ptr_table,X)
PRPMT LDA #PROMT/256
XBA
LDA #PROMT&255
JSR @PRNTS
LDY #$00
STY cmd_buffer
STY cmd_count
PLA
PRSDN PLY
PLX
RTL
MAINL
LDA #$AA
STA out_buf
STA out_reg ;Set display
LDA #$00
STA out_count ;init output buffer
STA cmd_count
STA inbuf_count
STA inbuf_ptr
PHP ;Clear IRQ Disable bit
PLA
AND #$FB
PHA
PLP
LDA #PROMT/256
XBA
LDA #PROMT&255
JSR @PRNTS ;print command prompt
CKCHR JSR @RDCHR ;Get the next character from the incoming ring buffer
CMP #$00
BEQ CKCHR ;If the character was zero, try reading again
JSR @PARSE
SKPAD CLV
BVC CKCHR
INTST ;We should test to make sure our interrupt is actually coming from the debug port
PHP ;Check to make sure it wasn't a BRK interrupt
PLA
AND #$10
BEQ IEXIT
TXL LDA out_count
STA spi_out
JSR @DOSPI
LDA spi_in
STA incoming_ch
LDX #$00
FLSHL CPX out_count
BEQ ENDFL
LDA txt_buffer,X
STA spi_out
JSR @DOSPI
INX
CLV
BVC FLSHL
ENDFL LDX #$00
STX out_count
LDA incoming_ch ;Add incoming character to the input buffer
BEQ IEXIT
LDX inbuf_count
INX
CPX inbuf_ptr ;If the 'count' pointer is one cell behind the read pointer then the ring buf is full
BEQ IEXIT
DEX
STA inbuf,X
INX
STX inbuf_count
JSR @OUTCH
IEXIT RTI
CDEND
.dsb $FFEE - *,$00
.word INTST ;FFEE,EF
.word 0 ;FFF0,F1
.word 0 ;FFF2,F3
.word 0 ;FFF4,F5
.word 0 ;FFF6,F7
.word 0 ;FFF8,F9
.word 0 ;FFFA,FB
.word START ;FFFC,FD
.byte $00
.byte $AA