"TIMER03A" 10 REM TIMER 20 REM To be used as a basis for software 30 REM requiring a millisecond timer. 40 50 REM V3.05 03/03/93 60 70 REM last changed by N. CARTER 80 90 REM PSYCHOLOGY DEPT 100 REM UNIVERSITY COLLEGE OF SWANSEA 110 REM SINGLETON PARK 120 REM SWANSEA SA2 8PP 130 140 REM Software by Harry Olive, Philip Heard & Neil Carter 150 160 REM==================================== 170 180 PROCinitialise1 190 PROCassembler 200 PROCinitialise2 210 MODE 7 220 CALL assemblyprog 230 END 240 250 REM------------------------------------ 260 DEF PROCinitialise1 270 modifier=1 280 maxreads%=10 290 ENDPROC 300 310 DEF PROCinitialise2 320 ?(adcoffset)=0 330 ?(maxoffset)=maxreads%*2 340 ENDPROC 350 360 DEF PROCgetdata 370 LOCAL timelo%,timehi%,analoglo%,analoghi% 380 timelo%=?timbuff:timehi%=?(timbuff+1) 390 time%=timelo%+(timehi%*256) 400 time%=time%*modifier 410 analoglo%=?(adcbase+adcoffset-2) 420 analoghi%=?(adcbase+adcoffset-1) 430 analog%=analoglo%+(analoghi%*256) 440 ENDPROC 450 460 REM==================================== 470 DEF PROCassembler 480 490 DIM assemblyram 1000, answer 5 500 irq2v=&206:screen=&7DEE 510 sysorb=&FE40:sysora=&FE41:sysddra=&FE43:sysifr=&FE4D:sysier=&FE4E 520 irb=&FE60:orb=&FE60:ddrb=&FE62 530 t1cl=&FE64:t1ch=&FE65 540 acr=&FE6B:pcr=&FE6C:ifr=&FE6D:ier=&FE6E 550 adcstart=&FEC0:adcstatus=&FEC0:adchigh=&FEC1:adclow=&FEC2 560 period=1000 570 580 FOR PASS=0 TO 3 STEP 3 590 600 P%=assemblyram 610 realmilisec=P%:realsec=P%+2 620 oldirq2v=P%+4 630 oldier=P%+6 640 convbyte=P%+7 650 lobyte=P%+8:hibyte=P%+9 660 loval=P%+10:hival=P%+11 670 adcbase=P%+12 680 adcoffset=P%+12+maxreads%*2 690 maxoffset=P%+12+maxreads%*2+1 700 P%=P%+12+maxreads%*2+2 710 720 REM==================================== 730[OPT PASS AUTO 740,10 .assemblyprog JSR asseminit JSR starttimer .begin JSR display LDA realsec CMP #&64 BCC begin JSR stoptimer RTS \--------------------------------------- .asseminit LDA #&00 STA realmilisec STA realmilisec+1 STA realsec STA realsec+1 \zero real timers RTS \--------------------------------------- .starttimer \initialise int system for our ms timer SEI \disable ints while setting-up LDA sysier STA oldier \get old system IER and save LDA #&7F STA sysier \disable all S-VIA ints LDA #&FF STA sysifr \clear pending system ints LDA irq2v STA oldirq2v \save original int vector 2 (lo-byte) LDA irq2v+1 STA oldirq2v+1 \save original int vector 2 (hi-byte) LDA #(inthandle MOD 256) STA irq2v \replace with vector lo-byte of our own ISR LDA #(inthandle DIV 256) STA irq2v+1 \replace with vector hi-byte of our own ISR LDA #(period MOD 256) STA t1cl \1000 decimal to U-VIA T1 latch lo-byte... LDA #(period DIV 256) STA t1ch \and hi-byte LDA #&40 STA acr \set up T1 continuous ints, PB7 disabled LDA #&C0 STA ier \enable T1 ints only CLI \enable ints RTS \--------------------------------------- .stoptimer \restore original int set-up SEI \disable ints LDA oldier STA sysier \restore original IER to S-VIA LDA oldirq2v STA irq2v \replace original int vector lo-byte LDA oldirq2v+1 STA irq2v+1 \replace original int vector hi-byte LDA #&40 STA ier \disable T1 ints LDA #&00 STA acr \de-select T1 CLI \enable ints RTS \--------------------------------------- .inthandle PHA \save all CPU registers... PHP LDA &FC PHA TXA PHA TYA PHA \all registers saved LDA ifr CMP #&C0 BNE endisr \if int is TIMER1 then... LDA t1cl \Clear int flag by dummy read INC realmilisec \increment real timer (ms) lo-byte BNE endinc1 \if overflow in lo-byte then... INC realmilisec+1 \increment hi-byte .endinc1 LDA realmilisec+1 CMP #&03 BNE endisr LDA realmilisec CMP #&E8 BNE endisr \if 1000 real ms elapsed then... INC realsec BNE endinc2 INC realsec+1 \increment real sec count .endinc2 LDA #&00 STA realmilisec STA realmilisec+1 \reset real ms for next second .endisr PLA \restore all CPU registers... TAY PLA TAX PLA STA &FC PLP PLA \all registers restored JMP (oldirq2v) \to original int handler \--------------------------------------- .display \writes 2 bytes hex to screen in 5 digit denary LDA realsec+1 \hi- byte of value for display (& conversion) STA hibyte LDA realsec \lo-byte STA lobyte JSR denaryconv \convert to denary LDX #&00 LDY #&04 .disploop \display 5 digits LDA answer,Y CLC ADC #&30 \convert to ASCII STA screen,X \write digit to screen INX DEY BPL disploop RTS \--------------------------------------- .denaryconv \converts 2 byte hex to 5 digit denary LDY #&04 LDA #&27 STA hival LDA #&10 STA loval JSR divide \divide by 10000 (divide hi/lo-byte by 10000) DEY LDA #&03 STA hival LDA #&E8 STA loval JSR divide \divide by 1000 DEY LDA #&00 STA hival LDA #&64 STA loval JSR divide \divide by 100 DEY LDA #&0A STA loval JSR divide \divide by 10 DEY LDA lobyte STA answer,Y \remainder=units RTS \--------------------------------------- .divide \performs 2 byte division (byte/val) LDX #&FF .convloop SEC \set borrow for subtraction INX LDA lobyte SBC loval STA lobyte \subtract lo-byte LDA hibyte SBC hival STA hibyte \subtract hi-byte BCS convloop \continue if remainder > divisor TXA STA answer,Y \store quotient LDA lobyte CLC ADC loval STA lobyte \add back divisor lo-byte LDA hibyte ADC hival STA hibyte \add back divisor hi-byte RTS \--------------------------------------- \Uses X-reg and Status-reg but doesn't save them .beep \makes a short (50ms) beep LDX #&0A \10 x 5ms delay JSR toneon \turn beep on .beeploop JSR delay5ms \wait X-reg x 5ms DEX BNE beeploop JSR toneoff \turn beep off RTS \--------------------------------------- \Uses X-reg and Accumulator but doesn't save them \Should also save Status-reg .toneon \turns on steady tone LDA #&FF STA sysddra \system VIA port A all outputs LDA #&C1 STA sysora \tone 1 freq 200Hz (first byte) LDA #&00 STA sysorb \strobe b0 lo (sound IC write enable) LDX #&05 .holdlo1 \hold b0 lo DEX BNE holdlo1 LDA #&08 STA sysorb \pull b0 hi LDA #&27 STA sysora \tone 1 freq 200Hz (second byte) LDA #&00 STA sysorb \strobe b0 lo (sound IC write enable) LDX #&05 .holdlo2 \hold b0 lo DEX BNE holdlo2 LDA #&08 STA sysorb \pull b0 hi LDA #&D0 STA sysora \tone 1 volume 15 LDA #&00 STA sysorb \strobe b0 lo (sound IC write enable) LDX #&05 .holdlo3 \hold b0 lo DEX BNE holdlo3 LDA #&08 STA sysorb \pull b0 hi RTS \--------------------------------------- \Uses X-reg and Accumulator, but doesn't save them \Should also save Status-reg .toneoff \turns tone off LDA #&DF STA sysora \tone 1 volume 0 (off) LDA #&00 STA sysorb \strobe b0 lo (sound IC write enable) LDX #&05 .holdlo4 \hold b0 lo DEX BNE holdlo4 LDA #&08 STA sysorb \pull b0 hi RTS \--------------------------------------- .readadc \reads ADC value LDA maxoffset CMP adcoffset BEQ endreadadc \only do maxpoint/2 reads of adc LDA #&08 \channel 1 10 bit STA adcstart \start conversion LDX #&FF .condelay \delay, before testing if conversion complete DEX BNE condelay .notcomplete \wait for conversion LDA adcstatus AND #&80 BNE notcomplete \b7 is lo if conversion complete LDA adclow \read ADC value (lo-byte)... AND #&C0 LDX adcoffset STA adcbase,X \and store in base+X reg byte INX LDA adchigh \read ADC value (hi-byte)... STA adcbase,X \and store in base+X reg byte INX STX adcoffset .endreadadc RTS \--------------------------------------- \Should save Accumulator and Status-reg .byte2vdu \displays 1-byte value on screen (MODE 7) \addresses &7C00 to &7FE7 STA convbyte \store display byte STX &70 \screen address lo-byte STY &71 \ " " hi-byte LDY #&01 .twopassloop LDA convbyte AND #&0F \one (lo-)nibble at a time CMP #&0A \test if number (0-9) or letter (A-F) BCC number CLC ADC #&07 \if letter, first add &07 to nibble .number CLC ADC #&30 \ascii = nibble + &30 STA (&70),Y \display nibble LSR convbyte LSR convbyte LSR convbyte LSR convbyte \transfer hi-nibble to lo-nibble DEY BPL twopassloop \do hi-nibble now RTS \--------------------------------------- .delay5ms \waits 5 ms, registers not corrupted PHP TXA PHA TYA PHA LDX #&08 .loop1 LDY #&ED .loop2 \simple nested loop delay DEY BNE loop2 DEX BNE loop1 PLA TAY PLA TAX PLP RTS \--------------------------------------- ] NEXT PASS ENDPROC ______________________________________________________________________ SYMBOL LIST LABELS acr &FE6B UVIA Auxiliary Control Register adchigh &FEC1 SVIA adclow &FEC2 adcstart &FEC0 adcstatus &FEC0 adrb &FE62 User Date Direction Register B ier &FE6E User Interrupt Enable Register ifr &FE6D User Interrupt Flag Register irb &FE60 User Input Register B irq2v &0206 Interrupt Request Vector #2 orb &FE60 User Output Register B (as orb) pcr &FE6C User Peripheral Control Register screen &7DEE Memory address for mid-screen position sysddra &FE43 System Data Direction Register sysier &FE4E System Interrupt Enable Register sysifr &FE4D System Interrupt Flag Register sysora &FE41 System Output Register A sysorb &FE40 System Output Register B t1ch &FE65 User Timer 1 High-order Counter t1cl &FE64 User Timer 1 Low-order Counter SYMBOLS assemblyram 2000 Space allocated for storage of assembly prog. adcbase - Start location for storage of ADC data adcoffset convbyte - Temporary storage of byte to be displayed in BYTE2VDU hibyte - Temporary storage of high byte to be converted to denary in CONVBYTE hival - Temporary storage of multiples of tens (high-order byte) used as divisors for denary conversion in DIVIDE lobyte - Temporary storage of in-byte to be converted to denary in CONVBYTE loval - Temporary storage of multiples of tens (low-order byte) used as divisors for denary conversion in DIVIDE maxoffset - End location for storage of ADC data oldier - Temporary storage of contents of enable register while timer is running oldirq2V(+1) - Temporary storage of original interrupt vectors, replaced by vectors for timer interrupt service routine (2-byte) (OLDIRQ2VLO/HI) period - Number of 1 microsecond clock-cycles between each timer interrupt. In this case, set to 1000 us (1ms) timbuff(+1) - Storage of count of single milliseconds, updated by timer interrupt service routine (2-byte) (TIMERLO/HI) 1991-10-10 Neil Carter