Interrupt clock...

Discuss software for the Apple 1/replica 1

Interrupt clock...

Postby fsafstrom » Dec Tue 11, 2007 2:33 am

I was just testing out the counter in VIA and wrote my first interrupt on the Replica... :D

So plug in your Expansion board, change the VIA address to whatever it supposed to be and re-compile, load up your Interrupt vector and give it a try...

Code: Select all
; **********************************************************************************
;
; Interrupt.asm
;
; Testing the Counter in VIA for Interrupt.
;
; **********************************************************************************


ACIA                = $C000
                                        ; Serial Port Controler
ACIA_CTRL           = ACIA+3
ACIA_CMD            = ACIA+2
ACIA_SR             = ACIA+1
ACIA_DAT            = ACIA

VIA                 = $C040
                                        ; I/O Controller
VIA_IOB             = VIA               ; Input/Output register B
VIA_IOA             = VIA+1             ; Input/Output register A
VIA_DDRB            = VIA+2             ; Data Direction Port B
VIA_DDRA            = VIA+3             ; Data Direction Port A
VIA_T1CL            = VIA+4             ; T1 Low Order Counter
VIA_T1CH            = VIA+5             ; T1 High Order Counter
VIA_T1LL            = VIA+6             ; T1 Low Order Latches
VIA_T1LH            = VIA+7             ; T1 High Order Latches
VIA_T2CL            = VIA+8             ; T2 Low Order Counter
VIA_T2CH            = VIA+9             ; T2 High Order Counter
VIA_SR              = VIA+10            ; Shift Register
VIA_ACR             = VIA+11            ; Auxiliary Control Register
VIA_PCR             = VIA+12            ; Pheriperal Control Register
VIA_IFR             = VIA+13            ; Interrupt Flag Register
VIA_IER             = VIA+14            ; Interrupt Enable Register
VIA_IOA2            = VIA+15            ; Input/Output register A, No handshake


INT_100             = $80
                                        ; Clock variables
INT_SEC             = $81
INT_MIN             = $82
INT_HOUR            = $83
INT_SEC2            = $84
INT_MIN2            = $85
INT_HOUR2           = $86
INT_HEX_IN          = $87
INT_DEC_OUT         = $88
INT_TEMP            = $89


; ****************
; * Main program *
; ****************

                    * = $1000           ; Start at $1000


MAIN                LDA VIA_ACR         ; VIA Control register
                    AND #$7F
                    ORA #$40            ; Set Interrupt.
                    STA VIA_ACR
                    LDA #$C0            ; Enable T1 Interrupt
                    STA VIA_IER

                    LDA #$0E
                    STA VIA_T1CL        ; Load $270E, 100 interrupts per second.
                    LDA #$27
                    STA VIA_T1CH

                    LDA #100
                                        ; Init counter
                    STA INT_100
                    LDA #0
                                        ; Init time.
                    STA INT_SEC
                    STA INT_MIN
                    STA INT_HOUR

                    CLI                 ; Clear Interrupt disable flag just in case
                    RTS



; ************************
; * The interrupt itself *
; ************************

; Note that you cannot modify A, X or Y in the interrupt.
; Save them and restore them when done.
; The Interrupt vector is stored at $FFFE
; My vector is $7800  ($FFFE = $00, $FFFF = $78)

                    * = $7800
                                        ; Set PC to my interrupt vector

INTERRUPT           PHA                 ; Save A
                    LDA VIA_T1CL        ; Reset Interrupt otherwise next interrupt will not occur
                    DEC INT_100         ; Count down
                    BNE .done           ; Done ?
                    LDA #100            ; Reset 100 count.
                    STA INT_100
                    INC INT_SEC         ; Increment seconds
                    LDA INT_SEC
                    CMP #60             ; Did we reach 60 seconds ?
                    BNE .convert        ; Nope, we are done
                    LDA #0
                    STA INT_SEC
                                        ; Reset seconds
                    INC INT_MIN
                                        ; Increase minutes
                    LDA INT_MIN
                    CMP #60
                                        ; Did we reach 60 minutes ?
                    BNE .convert        ; Nope, we are done
                    LDA #0
                    STA INT_MIN
                                        ; Reset minutes
                    INC INT_HOUR        ; Increase hours
                    LDA INT_HOUR
                    CMP #24             ; Did we reach 24 hours ?
                    BNE .convert        ; Nope, we are done
                    LDA #0
                    STA INT_HOUR


.convert            LDA INT_SEC         ; Convert seconds in Hex to dec
                    STA INT_HEX_IN
                    JSR HEX_TO_DEC
                    LDA INT_DEC_OUT
                    STA INT_SEC2
                    LDA INT_MIN         ; Convert minutes in Hex to dec
                    STA INT_HEX_IN
                    JSR HEX_TO_DEC
                    LDA INT_DEC_OUT
                    STA INT_MIN2
                    LDA INT_HOUR        ; Convert hours in Hex to dec
                    STA INT_HEX_IN
                    JSR HEX_TO_DEC
                    LDA INT_DEC_OUT
                    STA INT_HOUR2

.done               PLA                 ; Restore A
                    RTI                 ; Interrupt done


; *************************
; * HEX to DEC conversion *
; *************************

HEX_TO_DEC
                    LDA INT_HEX_IN      ; Load hex value
                    AND #$0F            ; Mask out upper bits
                    SED                 ; Set Decimal mode
                    CLC                 ; Clear Carry
                    ADC #0              ; Add 0 to convert hex to dec for the lower four bits.
                    STA INT_DEC_OUT     ; Save value
                    LDA INT_HEX_IN      ; Reload hex value
                    ROR
                    ROR
                    ROR
                    ROR                 ; Throw away lower four bits
                    ROR                 ; Check bit 5, this is worth 16
                    BCC .no_16          ; Bit is clear, do not add 16
                    STA INT_TEMP        ; Store our shifted bits
                    LDA INT_DEC_OUT     ; Get dec value
                    ADC #$15            ; Add 16, keep in mind that Carry is set
                    STA INT_DEC_OUT     ; Store dec
                    LDA INT_TEMP        ; Get our shifted bits
.no_16              ROR                 ; Check bit 6, this is worth 32
                    BCC .no_32          ; Bit is clear, do not add 32
                    LDA INT_DEC_OUT     ; Load dec
                    ADC #$31            ; Add 32, keep in mind that Carry is set
                    STA INT_DEC_OUT     ; Store dec.
.no_32              CLD                 ; Go back to Hex mode.
                    RTS
User avatar
fsafstrom
 
Posts: 154
Joined: Dec Tue 26, 2006 3:57 pm
Location: San Antonio, Texas

Postby Pepe » Dec Wed 12, 2007 4:18 am

Excellent example of using the VIA timer.
Just a tip though, do not do the conversion in the interrupt handler. Typically you want it to perform as fast as possible to avoid stalling the main program.

/Pepe
User avatar
Pepe
 
Posts: 32
Joined: Oct Fri 12, 2007 7:16 am
Location: The Plains of Skåne

Postby fsafstrom » Dec Wed 12, 2007 11:46 am

Or maybe write your whole program as an interrupt and then just have a dummy loop as the "normal" program... 8)

I agree, in real life the main program should do the conversion and you should optimize the interrupt handler as much as possible...
But it's a nice example of how to convert Hex to decimal (or BCD to be more precise).

Have anyone tried this on the official expansion bord for the Replica ?
Does it have the VIA wired to the IRQ ?
User avatar
fsafstrom
 
Posts: 154
Joined: Dec Tue 26, 2006 3:57 pm
Location: San Antonio, Texas


Return to Software

Who is online

Users browsing this forum: No registered users and 3 guests