VIA usage + ISR + "asm blobs" BASLOAD example
Posted: Tue Oct 31, 2023 4:07 am
Here is an example that makes use of VIA#2, and then responding to that interrupt using an ISR.
It's a working baseline reference for those interested. Done in a text file intended to be loaded by BASLOAD, but the PRG is tokenized BASIC also.
In the emulator you'll need to run it with the -via2 command line argument.
The online emulator seems to default to the 512K and only VIA#1 configuration, so TryItNow won't work on this for now. In the command startup of the emulator you can add "-via2" to model the second VIA.
REM V* 2023 - PUBLIC DOMAIN REM PURPOSE OF EXAMPLE: REM SET VIA#2 COUNTER (THAT COUNTS DOWN) TO TRIGGER AN ISR THAT COUNTS UP REM (NOTE FOR PC EMULATOR REMEMBER TO USE -VIA2 COMMAND LINE ARGUMENT) REM ADDRESSES USED: REM $4000 MAIN PROGRAM TO SETUP VIA AND ISR STARTS HERE REM $2000 USER-DEFINED ISR PROGRAMMED HERE REM $1000 LOCATION OF ISR DATA COUNTER (16-BIT) REM $1002 USED TO STORE PRIOR ISR ADDR (16-BIT) REM THIS PROGRAM "EXITS" TO THE SYSTEM MONITOR TO HELP VIEW REM MEMORY STATE CHANGES CAUSED BY THE ISR (USE "M 1000" COMMAND) REM (IT COULD EXIT BACK TO BASIC... THERE IS A KERNAL CALL FOR THAT) PRINT "RUN ONCE TO INIT COUNTER ISR." PRINT "THIS PROGRAM WILL ACTIVATE THE MONITOR." PRINT "USE 'M 1000' COMMAND (THEN PRESS" PRINT "ENTER-ENTER-ENTER) TO OBSERVE" PRINT "COUNTER VAUES TO VERIFY ISR IS" PRINT "ACTIVE. MUST [RESET] TO CLEAR THE ISR." PRINT REM ************************************************ REM LOAD UP THE "MAIN PROGRAM"... AD=$4000 RESTORE BLOB4000 GOSUB LOADBLOB REM LOAD UP THE USER-DEFINED ISR... AD=$2000 RESTORE BLOB2000 GOSUB LOADBLOB REM HAND OFF EXECUTION TO THE "MAIN PROGRAM"... SYS $4000 END:REM NOT REALLY NECESSARY, UNLIKELY THE MAIN-PROGRAM WILL COME BACK HERE. REM ************************************************ REM ************************************************ REM RE-USABLE "FUNCTION" TO LOAD DATA VALUES AS MACHINE CODE SEQUENCES LOADBLOB: PRINT "LOADING ";HEX$(AD); LOADBLOBNEXT: READ DV REM USING 999 INSTEAD OF -1 DUE TO BUG IN BASLOAD 0.2.3 RELATED TO INITIAL PARSING OF DATA-1 IF DV = 999 THEN PRINT" DONE":RETURN POKE AD,DV AD=AD+1 GOTO LOADBLOBNEXT REM ************************************************ REM ************************************************ REM MAIN PROGRAM... BLOB4000:REM EXPECTED TO BE LOADED INTO $4000 REM CLEAR/INIT TIMER_COUNT TO 0 (NOT REALLY NECESSARY, BUT JUST A "CLEAN START" IS GOOD PRACTICE) REM THIS IS THE COUNTER THAT WILL BE USED IN THE ISR DATA $A9,$00 :REM LDA #$00 DATA $8D,$00,$10:REM STA $1000 ; CAN USE STZ FOR 65C02 DATA $8D,$01,$10:REM STA $1001 REM PERFORM VIA#2 SETUP DATA $A9,$C0 :REM LDA #$C0 ; SET BIT 7 SETS INTERRUPTS, BIT 6 ENABLE TIMER 1 (%11000000) DATA $8D,$1E,$9F:REM STA $9F1E STA VIA_IER DATA $A9,$40 :REM LDA #$40 ; CONTINUOUS INTERRUPTS, NO TOGGLE OF PORT B/A DATA $8D,$1B,$9F:REM STA $9F1B STA VIA_ACL DATA $A9,$34 :REM LDA #$34 ; LOAD LOW BYTE OF THE INITIAL 16-BIT VALUE DATA $8D,$14,$9F:REM STA $9F14 STA VIA_T1CL (L FOR LOW) DATA $A9,$12 :REM LDA #$12 ; LOAD HIGH BYTE OF THE INITIAL 16-BIT VALUE DATA $8D,$15,$9F:REM STA $9F15 ; STA VIA_T1CH (H FOR HIGH) [STARTS TIMER RUNNING] REM ABOVE EXAMPLE USES TIMER VALUE OF $1234, THIS IMPACTS HOW OFTEN REM THE INTERRUPT WILL FIRE. CAN TRY OUT DIFFERENT VALUES AS DESIRED. :REM ; SAVE ADDRESS OF THE CURRENT INTERRUPT HANDLER (WILL THEN BE REFERRED TO AS "THE PRIOR" ISR) DATA $AD,$14,$03:REM LDA $0314 LDA IRQVECTOR DATA $8D,$02,$10:REM STA $1002 STA PRIOR_IRQ DATA $AD,$15,$03:REM LDA $0315 LDA IRQVECTOR+1 DATA $8D,$03,$10:REM STA $1003 STA PRIOR_IRQ+1 :REM ; INSERT "MY_ISR" AS NEW INTERRUPT HANDLER DATA $78 :REM SEI ; DISABLE INTERRUPTS DATA $A9,$00 :REM LDA #$00 ; WRITE LO ADDRESS OF CUSTOM INTERRUPT MY_ISR DATA $8D,$14,$03:REM STA $0314 STA IRQVECTOR DATA $A9,$20 :REM LDA #$20 ; Write HI ADDRESS OF CUSTOM INTERRUPT MY_ISR DATA $8D,$15,$03:REM STA $0315 STA IRQVECTOR+1 DATA $58 :REM CLI ; ENABLE INTERRUPTS :REM ; PROCEED WITH APPLICATION... (ISR IS NOW ACTIVE) DATA $4C,$CC,$FE:REM JMP $FECC ; JUMP TO MONITOR DATA 999 :REM END OF THIS BLOB OF CODE REM ************************************************ REM ************************************************ REM USER ISR (AKA "MY_ISR"): INTERRUPT SERVICE ROUTINE REM (THE FOLLOWING REGISTER-PUSH IS NOT NECESSARY, THIS IS DONE VIA ENTRY INTO IRQ) REM DATA $48 :REM PHA ; PUSH A REGISTER TO STACK REM DATA $DA :REM PHX ; PUSH X REGISTER TO STACK REM DATA $5A :REM PHY ; PUSH Y REGISTER TO STACK BLOB2000:REM EXPECTED TO BE LOADED INTO $2000 DATA $2C,$1D,$9F:REM BIT $9F1D ; BIT 6 COPIED TO OVERFLOW FLAG DATA $50,$0F :REM BVC ISR_PRIOR ; OVERFLOW CLEAR, SO ISR NOT INVOKED DUE TO THIS INTERRUPT... DATA $AD,$14,$9F:REM LDA $9F14 ; CLEARS THE INTERRUPT DATA $EE,$00,$10:REM INC $1000 ; INCREMET LOW BYTE DATA $D0,$03 :REM BNE ISR_END ; LOW BYTE DIDN'T ROLL OVER = DONE DATA $EE,$01,$10:REM INC $1001 ; PREVIOUS BYTE ROLLED OVER --> INCREMENT THE HIGH BYTE REM ISR_END: DATA $7A :REM PLY ; PULL Y FROM STACK DATA $FA :REM PLX ; PULL X FROM STACK DATA $68 :REM PLA ; PULL A FROM STACK DATA $40 :REM RTI:REM RETURN FROM THIS INTERRUPT REM ISR_PRIOR: DATA $6C,$02,$10:REM JMP ($1002) JUMP TO PRIOR ISR THAT WAS STORED AT $1002 EARLIER (PRIOR_IRQ) DATA 999 :REM END OF THIS BLOB OF CODE REM ************************************************
It's a working baseline reference for those interested. Done in a text file intended to be loaded by BASLOAD, but the PRG is tokenized BASIC also.
In the emulator you'll need to run it with the -via2 command line argument.
The online emulator seems to default to the 512K and only VIA#1 configuration, so TryItNow won't work on this for now. In the command startup of the emulator you can add "-via2" to model the second VIA.
REM V* 2023 - PUBLIC DOMAIN REM PURPOSE OF EXAMPLE: REM SET VIA#2 COUNTER (THAT COUNTS DOWN) TO TRIGGER AN ISR THAT COUNTS UP REM (NOTE FOR PC EMULATOR REMEMBER TO USE -VIA2 COMMAND LINE ARGUMENT) REM ADDRESSES USED: REM $4000 MAIN PROGRAM TO SETUP VIA AND ISR STARTS HERE REM $2000 USER-DEFINED ISR PROGRAMMED HERE REM $1000 LOCATION OF ISR DATA COUNTER (16-BIT) REM $1002 USED TO STORE PRIOR ISR ADDR (16-BIT) REM THIS PROGRAM "EXITS" TO THE SYSTEM MONITOR TO HELP VIEW REM MEMORY STATE CHANGES CAUSED BY THE ISR (USE "M 1000" COMMAND) REM (IT COULD EXIT BACK TO BASIC... THERE IS A KERNAL CALL FOR THAT) PRINT "RUN ONCE TO INIT COUNTER ISR." PRINT "THIS PROGRAM WILL ACTIVATE THE MONITOR." PRINT "USE 'M 1000' COMMAND (THEN PRESS" PRINT "ENTER-ENTER-ENTER) TO OBSERVE" PRINT "COUNTER VAUES TO VERIFY ISR IS" PRINT "ACTIVE. MUST [RESET] TO CLEAR THE ISR." PRINT REM ************************************************ REM LOAD UP THE "MAIN PROGRAM"... AD=$4000 RESTORE BLOB4000 GOSUB LOADBLOB REM LOAD UP THE USER-DEFINED ISR... AD=$2000 RESTORE BLOB2000 GOSUB LOADBLOB REM HAND OFF EXECUTION TO THE "MAIN PROGRAM"... SYS $4000 END:REM NOT REALLY NECESSARY, UNLIKELY THE MAIN-PROGRAM WILL COME BACK HERE. REM ************************************************ REM ************************************************ REM RE-USABLE "FUNCTION" TO LOAD DATA VALUES AS MACHINE CODE SEQUENCES LOADBLOB: PRINT "LOADING ";HEX$(AD); LOADBLOBNEXT: READ DV REM USING 999 INSTEAD OF -1 DUE TO BUG IN BASLOAD 0.2.3 RELATED TO INITIAL PARSING OF DATA-1 IF DV = 999 THEN PRINT" DONE":RETURN POKE AD,DV AD=AD+1 GOTO LOADBLOBNEXT REM ************************************************ REM ************************************************ REM MAIN PROGRAM... BLOB4000:REM EXPECTED TO BE LOADED INTO $4000 REM CLEAR/INIT TIMER_COUNT TO 0 (NOT REALLY NECESSARY, BUT JUST A "CLEAN START" IS GOOD PRACTICE) REM THIS IS THE COUNTER THAT WILL BE USED IN THE ISR DATA $A9,$00 :REM LDA #$00 DATA $8D,$00,$10:REM STA $1000 ; CAN USE STZ FOR 65C02 DATA $8D,$01,$10:REM STA $1001 REM PERFORM VIA#2 SETUP DATA $A9,$C0 :REM LDA #$C0 ; SET BIT 7 SETS INTERRUPTS, BIT 6 ENABLE TIMER 1 (%11000000) DATA $8D,$1E,$9F:REM STA $9F1E STA VIA_IER DATA $A9,$40 :REM LDA #$40 ; CONTINUOUS INTERRUPTS, NO TOGGLE OF PORT B/A DATA $8D,$1B,$9F:REM STA $9F1B STA VIA_ACL DATA $A9,$34 :REM LDA #$34 ; LOAD LOW BYTE OF THE INITIAL 16-BIT VALUE DATA $8D,$14,$9F:REM STA $9F14 STA VIA_T1CL (L FOR LOW) DATA $A9,$12 :REM LDA #$12 ; LOAD HIGH BYTE OF THE INITIAL 16-BIT VALUE DATA $8D,$15,$9F:REM STA $9F15 ; STA VIA_T1CH (H FOR HIGH) [STARTS TIMER RUNNING] REM ABOVE EXAMPLE USES TIMER VALUE OF $1234, THIS IMPACTS HOW OFTEN REM THE INTERRUPT WILL FIRE. CAN TRY OUT DIFFERENT VALUES AS DESIRED. :REM ; SAVE ADDRESS OF THE CURRENT INTERRUPT HANDLER (WILL THEN BE REFERRED TO AS "THE PRIOR" ISR) DATA $AD,$14,$03:REM LDA $0314 LDA IRQVECTOR DATA $8D,$02,$10:REM STA $1002 STA PRIOR_IRQ DATA $AD,$15,$03:REM LDA $0315 LDA IRQVECTOR+1 DATA $8D,$03,$10:REM STA $1003 STA PRIOR_IRQ+1 :REM ; INSERT "MY_ISR" AS NEW INTERRUPT HANDLER DATA $78 :REM SEI ; DISABLE INTERRUPTS DATA $A9,$00 :REM LDA #$00 ; WRITE LO ADDRESS OF CUSTOM INTERRUPT MY_ISR DATA $8D,$14,$03:REM STA $0314 STA IRQVECTOR DATA $A9,$20 :REM LDA #$20 ; Write HI ADDRESS OF CUSTOM INTERRUPT MY_ISR DATA $8D,$15,$03:REM STA $0315 STA IRQVECTOR+1 DATA $58 :REM CLI ; ENABLE INTERRUPTS :REM ; PROCEED WITH APPLICATION... (ISR IS NOW ACTIVE) DATA $4C,$CC,$FE:REM JMP $FECC ; JUMP TO MONITOR DATA 999 :REM END OF THIS BLOB OF CODE REM ************************************************ REM ************************************************ REM USER ISR (AKA "MY_ISR"): INTERRUPT SERVICE ROUTINE REM (THE FOLLOWING REGISTER-PUSH IS NOT NECESSARY, THIS IS DONE VIA ENTRY INTO IRQ) REM DATA $48 :REM PHA ; PUSH A REGISTER TO STACK REM DATA $DA :REM PHX ; PUSH X REGISTER TO STACK REM DATA $5A :REM PHY ; PUSH Y REGISTER TO STACK BLOB2000:REM EXPECTED TO BE LOADED INTO $2000 DATA $2C,$1D,$9F:REM BIT $9F1D ; BIT 6 COPIED TO OVERFLOW FLAG DATA $50,$0F :REM BVC ISR_PRIOR ; OVERFLOW CLEAR, SO ISR NOT INVOKED DUE TO THIS INTERRUPT... DATA $AD,$14,$9F:REM LDA $9F14 ; CLEARS THE INTERRUPT DATA $EE,$00,$10:REM INC $1000 ; INCREMET LOW BYTE DATA $D0,$03 :REM BNE ISR_END ; LOW BYTE DIDN'T ROLL OVER = DONE DATA $EE,$01,$10:REM INC $1001 ; PREVIOUS BYTE ROLLED OVER --> INCREMENT THE HIGH BYTE REM ISR_END: DATA $7A :REM PLY ; PULL Y FROM STACK DATA $FA :REM PLX ; PULL X FROM STACK DATA $68 :REM PLA ; PULL A FROM STACK DATA $40 :REM RTI:REM RETURN FROM THIS INTERRUPT REM ISR_PRIOR: DATA $6C,$02,$10:REM JMP ($1002) JUMP TO PRIOR ISR THAT WAS STORED AT $1002 EARLIER (PRIOR_IRQ) DATA 999 :REM END OF THIS BLOB OF CODE REM ************************************************