From e591dc84eae3522466f67ed9f8f6488e145eb26d Mon Sep 17 00:00:00 2001 From: Vince Weaver Date: Tue, 6 Feb 2018 01:30:20 -0500 Subject: [PATCH] mockingboard: add interrupt test code --- mockingboard/Makefile | 16 ++- mockingboard/interrupt_test.s | 129 +++++++++++++++++++++++ mockingboard/ksp_theme_interrupt.s | 159 ++++++++++++++++------------- mockingboard/mock_test.dsk | Bin 143360 -> 143360 bytes 4 files changed, 231 insertions(+), 73 deletions(-) create mode 100644 mockingboard/interrupt_test.s diff --git a/mockingboard/Makefile b/mockingboard/Makefile index 0b952057..720e7b16 100644 --- a/mockingboard/Makefile +++ b/mockingboard/Makefile @@ -6,10 +6,11 @@ PNG2GR = ../gr-utils/png2gr all: dump_ed mock.dsk lzss_compress mock.dsk: KSP_THEME_UNCOMPRESSED KSP_THEME_COMPRESSED \ - KSP_THEME_INTERRUPT + KSP_THEME_INTERRUPT INTERRUPT_TEST $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 KSP_THEME_UNCOMPRESSED $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 KSP_THEME_COMPRESSED $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 KSP_THEME_INTERRUPT + $(DOS33) -y mock_test.dsk BSAVE -a 0x1000 INTERRUPT_TEST KSP_THEME_COMPRESSED: ksp_theme_compressed.o ld65 -o KSP_THEME_COMPRESSED ksp_theme_compressed.o -C ./apple2_1000.inc @@ -35,6 +36,16 @@ ksp_theme_uncompressed.o: ksp_theme_uncompressed.s \ ../asm_routines/mockingboard.s ca65 -o ksp_theme_uncompressed.o ksp_theme_uncompressed.s -l ksp_theme_uncompressed.lst + +INTERRUPT_TEST: interrupt_test.o + ld65 -o INTERRUPT_TEST interrupt_test.o -C ./apple2_1000.inc + +interrupt_test.o: interrupt_test.s \ + ../asm_routines/mockingboard.s + ca65 -o interrupt_test.o interrupt_test.s -l interrupt_test.lst + + + ED: duet.o ld65 -o ED duet.o -C ./apple2_900.inc @@ -58,5 +69,6 @@ lzss_compress: lzss_compress.o $(CC) $(LFLAGS) -o lzss_compress lzss_compress.o clean: - rm -f *~ TITLE.GR *.o *.lst ED KSP_THEME_UNCOMPRESSED dump_ed + rm -f *~ TITLE.GR *.o *.lst ED KSP_THEME_UNCOMPRESSED \ + KSP_THEME_COMPRESSED KSP_THEME_INTERRUPT INTERRUPT_TEST dump_ed diff --git a/mockingboard/interrupt_test.s b/mockingboard/interrupt_test.s new file mode 100644 index 00000000..4da80d55 --- /dev/null +++ b/mockingboard/interrupt_test.s @@ -0,0 +1,129 @@ +; Test the 6522 on a Mockingboard running in interrupt mode +; Trying to set it to 50Hz + +.include "zp.inc" + + ;============================= + ; Print message + ;============================= + jsr HOME + jsr TEXT + + lda #0 + sta DRAW_PAGE + sta CH + sta CV + lda #mocking_message + sta OUTH + jsr move_and_print + + jsr mockingboard_detect_slot4 + cpx #$1 + beq mockingboard_found + + lda #not_message + sta OUTH + inc CV + jsr move_and_print + + jmp forever_loop + +mockingboard_found: + lda #found_message + sta OUTH + inc CV + jsr move_and_print + + ;========================= + ; Setup Interrupt Handler + ;========================= + ; Vector address goes to 0x3fe/0x3ff + ; FIXME: should chain any existing handler + + lda #interrupt_handler + sta $03ff + + ;============================ + ; Enable 50Hz clock on 6522 + ;============================ + + lda #$40 ; Generate continuous interrupts, don't touch PB7 + sta $C40B ; ACR register + lda #$7F ; clear all interrupt flags + sta $C40E ; IER register (interrupt enable) + + lda #$C0 + sta $C40D ; IFR: 1100, enable interrupt on timer one oflow + sta $C40E ; IER: 1100, enable timer one interrupt + + lda #$E7 + sta $C404 ; write into low-order latch + lda #$4f + sta $C405 ; write into high-order latch, + ; load both values into counter + ; clear interrupt and start counting + + ; 4fe7 / 1e6 = .020s, 50Hz + + ;============================ + ; Enable 6502 interrupts + ;============================ + ; + cli ; clear interrupt mask + + + ;============================ + ; Loop forever + ;============================ + lda #64 +forever_loop: +; clc +; adc #1 + sta $0401 + jmp forever_loop + + + + ;============================= + ; simple interrupt handler + ;============================= +interrupt_handler: + lda $45 ; the Apple II firmware messes with A when + ; detecting BRK, so the value in $45 is the real one? + ; also DISK II support uses this so you should disable + ; interrupts if messing with the disk? + + pha ; save A (hardware saved Pflags for us) + + bit $C404 ; can clear interrupt by reading T1C-L + + + inc $0410 ; increment text char on screen + + pla ; restore A + rti + + + +;========= +;routines +;========= +.include "../asm_routines/gr_offsets.s" +.include "../asm_routines/text_print.s" +.include "../asm_routines/mockingboard.s" + +;========= +; strings +;========= +mocking_message: .asciiz "LOOKING FOR MOCKINGBOARD IN SLOT #4" +not_message: .byte "NOT " +found_message: .asciiz "FOUND" +done_message: .asciiz "DONE PLAYING" diff --git a/mockingboard/ksp_theme_interrupt.s b/mockingboard/ksp_theme_interrupt.s index 68d3c8ea..c040eb66 100644 --- a/mockingboard/ksp_theme_interrupt.s +++ b/mockingboard/ksp_theme_interrupt.s @@ -34,14 +34,12 @@ jmp forever_loop mockingboard_found: - - lda #found_message - sta OUTH - inc CV - jsr move_and_print - + lda #found_message + sta OUTH + inc CV + jsr move_and_print ;============================ ; Init the Mockingboard @@ -63,8 +61,8 @@ mockingboard_found: lda #>ksptheme sta INH - ldy #0 new_frame: + ldy #0 lda (INL),Y ; read in frame delay cmp #$ff ; see if end beq done_play ; if so, done @@ -72,90 +70,96 @@ new_frame: tax old_frame: dex ; decrement the frame diff - bpl delay_a_bit ; if not there yet, delay + beq bottom_regs ; if not there yet, delay + jsr delay_50Hz + jmp old_frame -top_regs: +bottom_regs: iny - lda (INL),Y ; load low reg bitmask - ldx #$ff -top_regs_loop: - inx - cmp #$8 - beq bottom_regs - ror - bcc top_regs_loop + lda (INL),Y ; load low reg bitmask + sta MASK + ldx #$ff ; init to -1 +bottom_regs_loop: + inx ; increment X + cpx #$8 ; if we reach 8, done + beq top_regs ; move on to top - stx XX - sty YY + ror MASK + bcc bottom_regs_loop ; if bit not set in mask, skip reg - iny - lda (INL),Y ; read in value - tax + stx XX ; save X - ldy XX + iny ; get next output value + lda (INL),Y ; read in value + + sty YY ; save Y + + tax ; value in X + ldy XX ; register# in Y ; reg in Y, value in X - jsr write_ay_left ; assume 3 channel (not six) - jsr write_ay_right ; so write same to both left/write + jsr write_ay_left ; assume 3 channel (not six) + jsr write_ay_right ; so write same to both left/write + + ldx XX ; restore X + ldy YY ; restore Y + + jmp bottom_regs_loop ; loop + +top_regs: + iny ; point to next value + lda (INL),Y ; load top reg bitmask + sta MASK + ldx #$7 ; load X as 7 (we increment first) +top_regs_loop: + inx ; increment + cpx #$16 + beq done_with_masks ; exit if done + + ror MASK + bcc top_regs_loop ; loop if not set + + stx XX ; save X value + + iny ; point to value + lda (INL),Y ; read in output value + + sty YY ; save Y value + + tax ; value in X + ldy XX ; register in Y + + ; reg in Y, value in X + jsr write_ay_left ; assume 3 channel (not six) + jsr write_ay_right ; so write same to both left/write ldx XX ldy YY jmp top_regs_loop -bottom_regs: +done_with_masks: iny - lda (INL),Y ; load low reg bitmask - ldx #$ff -bottom_regs_loop: - inx - cmp #$8 - beq delay_a_bit - ror - bcc bottom_regs_loop + clc + tya + adc INL + sta INL + lda #0 + adc INH + sta INH + jsr delay_50Hz - stx XX - sty YY + jmp new_frame - iny - lda (INL),Y ; read in value - tax - - ldy XX - - ; reg in Y, value in X - jsr write_ay_left ; assume 3 channel (not six) - jsr write_ay_right ; so write same to both left/write - - ldx XX - ldy YY - - jmp bottom_regs_loop - - ; reg in Y, value in X - jsr write_ay_left ; assume 3 channel (not six) - jsr write_ay_right ; so write same to both left/write - -delay_a_bit: - - lda #86 - jsr WAIT ; delay 1/2(26+27A+5A^2) us - ; 50Hz = 20ms = 20000us - ; 40000 = 26+27A+5A^2 - ; 5a^2+27a-39974 = 0 - ; A = 86.75 - - jmp old_frame done_play: jsr clear_ay_left jsr clear_ay_right - lda #0 sta CH - lda #2 + lda #3 sta CV lda #_PMMQkGB3L=(y}O|Ot;Yj zfMakN+%A&a7_jQYG1w0#d#^{JN$!~xqCwAHS(*FFKG+qJx7kcWM4pWqXH9-ri={NPV}l(|LjTur$EOFassAca*N zic{ef*X$`$+=^hOmUQnHN_RIaT^y_DZRtj5B#URHo0ya99e*cX%^!>lA&N}*2E8Y; z(w)pocPk@Z+?FnGOII~3T~0>2)_KwejCK$NdI_%y15iE(G#~P_ugmL&ptrN223C7) z(2*H11J}1;{rQ|+KloRmR@=N+#bRVbEaf0ydn>%1S9p>+MTindY^ z)E9Nrk`e8L3RfHvi*1P734Lf>+)0sQK?_Mxk|uc&Bh7}ylBclvVlbPocXzh6CiF@0 zLGm(p?%~Y6hjYH~H~l%(pF?M*c1P-f^^gPePz;GdnN1~XGHr=(L~G;>#KgO)H8~CU zGOS)!Wm#5auZ(0L)AqF>kKh51=3M3;uDuVl@9x;c51&=NL2pPA6i`H_J$oBJZ#<3V z8v1mBcCFchxnee&P4<|1)owJ4G)(9c$w405D{kaU6OSb(vHklEd-^D$`v`rW&@Tu* zOKfBo>?(8pq%cw#FXs0TPvE^{BZa}@@;J)tFMqiD&f>rl4-5}2(&L04=_Ow-4lN~8 z_<9oEoaE-bhs$3OyO*9WBo5%pg@V~=i@faB>t*v2+1nkRRns_{YBZbA&EV9E8BbD? zSm!T6BMK8+GFNDrCHqp^aq=$yGkG#ND9|J9Qr~vCU>%)?hO7jd!UpGBN=@p-k&R87 zuiVy3=$hLkfk&FmB5zVFN#w9Cv9A3?pl0Tt+m0M~0RVp`_5yaqhqwkD=;F`p5|27C z%U{_OyTh5*?rdO_BBY=Y1g0&tpa2T^0&2j|w7HLXSEaLUXsu!W(g4kl*bP?$ z*)|YG_T+0L?5BR@eES$Y-oifHSr(lGZ-GCIBXUHEcq1s{i>MKQM6C0B|9NdoTggU4b>$s9<;8P~5@$w(0FZ(KJs&#q> S%5+KN|AV@F@qeW51^-{erv8rr