-
Notifications
You must be signed in to change notification settings - Fork 3
/
Interrupt_Handler.asm
673 lines (571 loc) · 20 KB
/
Interrupt_Handler.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
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
;////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////
; Interrupt Handler
;////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////
;////////////////////////////////////////////////////////////////////////////
check_irq_bit .macro
LDA \1
AND #\2
CMP #\2
BNE END_CHECK
STA \1
JSR \3
END_CHECK
.endm
IRQ_HANDLER
; First Block of 8 Interrupts
setdp 0
setas
LDA #0 ; set the data bank register to 0
PHA
PLB
LDA INT_PENDING_REG0
BEQ CHECK_PENDING_REG1
; Start of Frame
;check_irq_bit INT_PENDING_REG0, FNX0_INT00_SOF, SOF_INTERRUPT
; Timer 0
check_irq_bit INT_PENDING_REG0, FNX0_INT02_TMR0, TIMER0_INTERRUPT
; FDC Interrupt
check_irq_bit INT_PENDING_REG0, FNX0_INT06_FDC, FDC_INTERRUPT
; Mouse IRQ
check_irq_bit INT_PENDING_REG0, FNX0_INT07_MOUSE, MOUSE_INTERRUPT
; Second Block of 8 Interrupts
CHECK_PENDING_REG1
setas
LDA INT_PENDING_REG1
BEQ CHECK_PENDING_REG2 ; BEQ EXIT_IRQ_HANDLE
; Keyboard Interrupt
check_irq_bit INT_PENDING_REG1, FNX1_INT00_KBD, KEYBOARD_INTERRUPT
; COM2 Interrupt
check_irq_bit INT_PENDING_REG1, FNX1_INT03_COM2, COM2_INTERRUPT
; COM1 Interrupt
check_irq_bit INT_PENDING_REG1, FNX1_INT04_COM1, COM1_INTERRUPT
; MPU401 - MIDI Interrupt
check_irq_bit INT_PENDING_REG1, FNX1_INT05_MPU401, MPU401_INTERRUPT
; LPT Interrupt
check_irq_bit INT_PENDING_REG1, FNX1_INT06_LPT, LPT1_INTERRUPT
; Third Block of 8 Interrupts
CHECK_PENDING_REG2
setas
LDA INT_PENDING_REG2
BEQ EXIT_IRQ_HANDLE
; OPL2 Right Interrupt
;check_irq_bit INT_PENDING_REG2, FNX2_INT00_OPL2R, OPL2R_INTERRUPT
; OPL2 Left Interrupt
;check_irq_bit INT_PENDING_REG2, FNX2_INT01_OPL2L, OPL2L_INTERRUPT
EXIT_IRQ_HANDLE
; Exit Interrupt Handler
setaxl
RTL
; ****************************************************************
; ****************************************************************
;
; KEYBOARD_INTERRUPT
;
; ****************************************************************
; ****************************************************************
; * Todo: Rewrite this to use indirect or indexed jumps.
; * This is otherwise impossible to read.
KEYBOARD_INTERRUPT
.as
ldx #$0000
IRQ_HANDLER_FETCH
LDA KBD_INPT_BUF ; Get Scan Code from KeyBoard
STA KEYBOARD_SC_TMP ; Save Code Immediately
setxl
LDY #70
JSR WRITE_HEX ; print the HEX key code at column 70 on the top line
CMP #1 ; ESC
BNE NOT_ESCAPE
LDA STATE_MACHINE
CMP #2
BNE NOT_ESCAPE
JSL EXIT_FILE
JMP KB_WR_2_SCREEN
NOT_ESCAPE
CMP #$1A ; left bracket
BNE NOT_LEFT_BRACKET
DEC INSTR_NUMBER
JSR LOAD_INSTRUMENT ; X is already set to 0
JMP KB_WR_2_SCREEN
NOT_LEFT_BRACKET
CMP #$1B ; right bracket
BNE NOT_RIGHT_BRACKET
INC INSTR_NUMBER
JSR LOAD_INSTRUMENT ; X is already set to 0
JMP KB_WR_2_SCREEN
NOT_RIGHT_BRACKET
CMP #$0C ; minus
BNE NOT_MINUS
LDA STATE_MACHINE ; only allow for this in edit mode
AND #$F
BNE MINUS_DONE
; if the pattern is 1, then stay here otherwise, decrement
LDA PATTERN_NUM
CMP #1
BEQ MINUS_DONE
SED ; switch to decimal
SEC
SBC #1
STA PATTERN_NUM
CLD ; switch out of decimal
JSR DISPLAY_PATTERN
MINUS_DONE
JMP KB_WR_2_SCREEN
NOT_MINUS
CMP #$0D ; plus
BNE BPM_KEYS
LDA STATE_MACHINE ; only allow for this in edit mode
AND #$F
BNE PLUS_DONE
; if the pattern is 30, then stay here otherwise, increment
LDA PATTERN_NUM
CMP #$30
BEQ PLUS_DONE
SED ; switch to decimal
CLC
ADC #1
STA PATTERN_NUM
CLD ; switch out of decimal
JSR DISPLAY_PATTERN
PLUS_DONE
JMP KB_WR_2_SCREEN
BPM_KEYS
CMP #$27 ; semi-colon
BNE NOT_SEMI_COLON
; reduce the BPM by 1 beat
LDA BPM
CMP #4
BEQ PLUS_DONE
DEC A
BRA SETUP_TIMER
NOT_SEMI_COLON
CMP #$28 ; quote
BNE TRY_GRAVE
; increase the BPM by 1 beat
LDA BPM
CMP #240
BEQ PLUS_DONE
INC A
SETUP_TIMER
STA BPM
JSR DISPLAY_BPM
JSR INIT_TIMER0_BPM
JMP KB_WR_2_SCREEN
TRY_GRAVE
CMP #$29
BNE SPECIAL_KEYS
LDA #0
XBA
LDA STATE_MACHINE
PHA
AND #$30
LSR
LSR
TAX
PLA
EOR HL_CLR_TABLE+3,X
STA STATE_MACHINE
JSR HIGHLIGHT_MODE
JMP KB_WR_2_SCREEN
SPECIAL_KEYS
; Check for Shift Press or Unpressed
CMP #$2A ; Left Shift Pressed
BNE NOT_KB_SET_SHIFT
BRL KB_SET_SHIFT
NOT_KB_SET_SHIFT
CMP #$AA ; Left Shift Unpressed
BNE NOT_KB_CLR_SHIFT
BRL KB_CLR_SHIFT
NOT_KB_CLR_SHIFT
; Check for CTRL Press or Unpressed
CMP #$1D ; Left CTRL pressed
BNE NOT_KB_SET_CTRL
BRL KB_SET_CTRL
NOT_KB_SET_CTRL
CMP #$9D ; Left CTRL Unpressed
BNE NOT_KB_CLR_CTRL
BRL KB_CLR_CTRL
NOT_KB_CLR_CTRL
CMP #$38 ; Left ALT Pressed
BNE NOT_KB_SET_ALT
BRL KB_SET_ALT
NOT_KB_SET_ALT
CMP #$B8 ; Left ALT Unpressed
BNE NOT_SPECIAL
BRL KB_CLR_ALT
NOT_SPECIAL
CMP #$48 ; UP arrow
BNE NOT_UP
PHA
LDA STATE_MACHINE
AND #$F
BNE UP_WRONG_STATE
JSR DECR_LINE
UP_WRONG_STATE
CMP #2
BNE UP_WRG_DONE
JSL SELECT_PREVIOUS_FILE
UP_WRG_DONE
PLA
JMP KB_WR_2_SCREEN
NOT_UP
CMP #$50 ; DOWN arrow
BNE NOT_DOWN
PHA
LDA STATE_MACHINE
AND #$F
BNE DOWN_WRONG_STATE
JSR INCR_LINE
DOWN_WRONG_STATE
CMP #2
BNE DOWN_WRG_DONE
JSL SELECT_NEXT_FILE
DOWN_WRG_DONE
PLA
JMP KB_WR_2_SCREEN
NOT_DOWN
KB_UNPRESSED
AND #$80 ; See if the Scan Code is press or Depressed
CMP #$80 ; Depress Status - We will not do anything at this point
BNE KB_NORM_SC
; send note off signal
LDA #$00
STA OPL2_PARAMETER0 ; Set Keyon False
JSR OPL2_SET_KEYON
BRL KB_CHECK_B_DONE
KB_NORM_SC
LDA KEYBOARD_SC_TMP
setxs
TAX
LDA KEYBOARD_SC_FLG ; Check to See if the SHIFT Key is being Pushed
AND #$10
CMP #$10
BEQ SHIFT_KEY_ON
LDA KEYBOARD_SC_FLG ; Check to See if the CTRL Key is being Pushed
AND #$20
CMP #$20
BEQ CTRL_KEY_ON
LDA KEYBOARD_SC_FLG ; Check to See if the ALT Key is being Pushed
AND #$40
CMP #$40
BEQ ALT_KEY_ON
setxl
LDA KEYBOARD_SC_TMP
JSR PLAY_TRACKER_NOTE
setxs
LDX KEYBOARD_SC_TMP
; Pick and Choose the Right Bank of Character depending if the Shift/Ctrl/Alt or none are chosen
LDA @lScanCode_Press_Set1, x
BRL KB_WR_2_SCREEN
SHIFT_KEY_ON LDA @lScanCode_Shift_Set1, x
BRL KB_WR_2_SCREEN
CTRL_KEY_ON LDA @lScanCode_Ctrl_Set1, x
BEQ KB_WR_2_SCREEN
CMP #2
BNE CONTINUE_KEY
; load a file
LDA STATE_MACHINE ; check if the load file screen is already opened
AND #$F
CMP #2
BEQ CONTINUE_KEY
JSL LOAD_FILE_DISPLAY
CONTINUE_KEY
BRA KB_WR_2_SCREEN
ALT_KEY_ON LDA @lScanCode_Alt_Set1, x
BEQ KB_WR_2_SCREEN
; turn channels on / off
AND #$F
JSR TOGGLE_CHANNEL
setxl
JSR DISPLAY_ACTIVE_CHANNELS
setxs
RTS ; early exit
KB_WR_2_SCREEN
setxl
LDY #74
JSR WRITE_HEX
CMP #$0D ; Enter Key Pressed
BNE KB_CHECK_B_DONE_R
PHA
; start or stop scrolling
LDA STATE_MACHINE
BEQ START_SOF ; if zero then start playing
CMP #2
BEQ GO_LOAD_FILE
STOP_SOF
LDA @lINT_MASK_REG0 ; stop the timer interrupts
ORA #FNX0_INT02_TMR0
STA @lINT_MASK_REG0
LDA #0 ; record mode
STA STATE_MACHINE
JSR RAD_ALL_NOTES_OFF
PLA
KB_CHECK_B_DONE_R
JMP KB_CHECK_B_DONE
START_SOF
LDA KEYBOARD_SC_FLG
BNE CONTINUE_FROM_CURRENT_LOCATION
JSR RESET_STATE_MACHINE
JSR DISPLAY_PATTERN
CONTINUE_FROM_CURRENT_LOCATION
LDA #1
STA STATE_MACHINE
JSR RAD_PLAYNOTES
LDA @lINT_MASK_REG0
AND #~(FNX0_INT02_TMR0)
STA @lINT_MASK_REG0
PLA
JMP KB_CHECK_B_DONE
GO_LOAD_FILE
.xl
PLA
JSL READ_FILE
JMP KB_CHECK_B_DONE
KB_SET_SHIFT LDA KEYBOARD_SC_FLG
ORA #$10
STA KEYBOARD_SC_FLG
JMP KB_CHECK_B_DONE
KB_CLR_SHIFT LDA KEYBOARD_SC_FLG
AND #$EF
STA KEYBOARD_SC_FLG
JMP KB_CHECK_B_DONE
KB_SET_CTRL LDA KEYBOARD_SC_FLG
ORA #$20
STA KEYBOARD_SC_FLG
JMP KB_CHECK_B_DONE
KB_CLR_CTRL LDA KEYBOARD_SC_FLG
AND #$DF
STA KEYBOARD_SC_FLG
JMP KB_CHECK_B_DONE
KB_SET_ALT LDA KEYBOARD_SC_FLG
ORA #$40
STA KEYBOARD_SC_FLG
JMP KB_CHECK_B_DONE
KB_CLR_ALT LDA KEYBOARD_SC_FLG
AND #$BF
STA KEYBOARD_SC_FLG
KB_CHECK_B_DONE .as
LDA STATUS_PORT ; the address should have $AF
AND #OUT_BUF_FULL ; Test bit $01 (if 1, Full)
CMP #OUT_BUF_FULL ; if Still Byte in the Buffer, fetch it out
BNE KB_DONE
JMP IRQ_HANDLER_FETCH
KB_DONE
RTS
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Start of Frame Interrupt
; /// 60Hz, 16ms Cyclical Interrupt
; ///
; ///////////////////////////////////////////////////////////////////
SOF_INTERRUPT
TIMER0_INTERRUPT
.as
LDA STATE_MACHINE ; the SOF is still called even when the interrupt is masked.
AND #1
BEQ EDIT_MODE
LDA @lTICK
INC A
CMP @lTuneInfo.InitialSpeed
BNE TICK_DONE
; we now have to increment the line count
INCR_LINE
LDA LINE_NUM_HEX
BIT #3
BNE NO_LED
TURN_ON_SD_LED
NO_LED
CLC
SED
INC LINE_NUM_HEX
LDA @lLINE_NUM_DEC
ADC #1
CMP #$65 ; this is the maximum number of lines
BNE INCR_DONE
LDA #1
STZ LINE_NUM_HEX
; read the next pattern from the order list
JSR INCREMENT_ORDER
INCR_DONE
CLD
STA @lLINE_NUM_DEC
JSR DISPLAY_PATTERN
; if the state is PLAY then play the notes
LDA STATE_MACHINE
AND #1
BEQ EDIT_MODE
JSR RAD_PLAYNOTES
EDIT_MODE
LDA #0 ; reset the tick to 0
TICK_DONE
STA @lTICK
TURN_OFF_SD_LED
; TODO deal with effects
;JSR APPLY_EFFECTS
RTS
; ///////////////////////////////////////////////////////////////////
; ///
; /// This is called when the up arrow is pressed on the keyboard
; ///
; ///////////////////////////////////////////////////////////////////
DECR_LINE
SEC
SED
DEC LINE_NUM_HEX
LDA @lLINE_NUM_DEC
SBC #1
BNE DECR_DONE
LDA #63
STA LINE_NUM_HEX
LDA #$64
DECR_DONE
CLD
STA @lLINE_NUM_DEC
JSR DISPLAY_PATTERN
LDA #0 ; reset the tick to 0
STA @lTICK
RTS
; ///////////////////////////////////////////////////////////////////
; ///
; /// MPU-401 (MIDI)
; /// Desc: Interrupt for Data Rx/Tx
; /// We get a single interrupt per byte
; /// MIDI command have a command byte then one or two data bytes
; ///
; ///////////////////////////////////////////////////////////////////
MPU401_INTERRUPT .as
PHA
setxl
MORE_MIDI_DATA LDA @lMIDI_STATUS_REG ; if bit D7 is low, there is more data to read
STA MIDI_REG
AND #$80
CMP #$80
BEQ MIDI_DONE
LDA @lMIDI_DATA_REG
JSR RECEIVE_MIDI_DATA
LDA MIDI_REG
CMP #$80
BNE MORE_MIDI_DATA
MIDI_DONE
PLA
RTS
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Mouse Interrupt
; /// Desc: Basically Assigning the 3Bytes Packet to Vicky's Registers
; /// Vicky does the rest
; ///////////////////////////////////////////////////////////////////
MOUSE_INTERRUPT
.as
LDA KBD_INPT_BUF
PHA
LDX #$0000
setxs
LDX MOUSE_PTR
BNE MOUSE_BYTE_GT1
; copy the buttons to another address
AND #%0111
STA MOUSE_BUTTONS_REG
MOUSE_BYTE_GT1
PLA
STA @lMOUSE_PTR_BYTE0, X
INX
CPX #$03
BNE EXIT_FOR_NEXT_VALUE
; Create Absolute Count from Relative Input
LDA @lMOUSE_PTR_X_POS_L
STA MOUSE_POS_X_LO
LDA @lMOUSE_PTR_X_POS_H
STA MOUSE_POS_X_HI
LDA @lMOUSE_PTR_Y_POS_L
STA MOUSE_POS_Y_LO
LDA @lMOUSE_PTR_Y_POS_H
STA MOUSE_POS_Y_HI
; print the character on the upper-right of the screen
; this is temporary
CLC
LDA MOUSE_BUTTONS_REG
setxl
LDY #60
JSR WRITE_HEX
setxs
JSR MOUSE_BUTTON_HANDLER
LDX #$00
EXIT_FOR_NEXT_VALUE
STX MOUSE_PTR
setxl
RTS
MOUSE_BUTTON_HANDLER
setas
LDA @lMOUSE_BUTTONS_REG
BEQ MOUSE_CLICK_DONE
; set the cursor position ( X/8 and Y/8 ) and enable blinking
setal
CLC
LDA @lMOUSE_PTR_X_POS_L
LSR
LSR
LSR
STA CURSORX
STA @lVKY_TXT_CURSOR_X_REG_L
CLC
LDA @lMOUSE_PTR_Y_POS_L
LSR
LSR
LSR
STA CURSORY
STA @lVKY_TXT_CURSOR_Y_REG_L
setas
LDA #$03 ;Set Cursor Enabled And Flash Rate @1Hz
STA @lVKY_TXT_CURSOR_CTRL_REG
MOUSE_CLICK_DONE
RTS
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Floppy Controller
; /// Desc: Interrupt for Data Rx/Tx or Process Commencement or Termination
; ///
; ///////////////////////////////////////////////////////////////////
FDC_INTERRUPT .as
;; PUT YOUR CODE HERE
RTS
;
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Serial Port COM2
; /// Desc: Interrupt for Data Rx/Tx or Process Commencement or Termination
; ///
; ///////////////////////////////////////////////////////////////////
COM2_INTERRUPT .as
;; PUT YOUR CODE HERE
RTS
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Serial Port COM1
; /// Desc: Interrupt for Data Rx/Tx or Process Commencement or Termination
; ///
; ///////////////////////////////////////////////////////////////////
COM1_INTERRUPT .as
;; PUT YOUR CODE HERE
RTS
;
;
; ///////////////////////////////////////////////////////////////////
; ///
; /// Parallel Port LPT1
; /// Desc: Interrupt for Data Rx/Tx or Process Commencement or Termination
; ///
; ///////////////////////////////////////////////////////////////////
LPT1_INTERRUPT .as
;; PUT YOUR CODE HERE
RTS
NMI_HANDLER
RTL