summaryrefslogtreecommitdiff
path: root/roms/7seg_counter_irq_timer_start_stop.asm
diff options
context:
space:
mode:
Diffstat (limited to 'roms/7seg_counter_irq_timer_start_stop.asm')
-rw-r--r--roms/7seg_counter_irq_timer_start_stop.asm170
1 files changed, 170 insertions, 0 deletions
diff --git a/roms/7seg_counter_irq_timer_start_stop.asm b/roms/7seg_counter_irq_timer_start_stop.asm
new file mode 100644
index 0000000..3c7aed5
--- /dev/null
+++ b/roms/7seg_counter_irq_timer_start_stop.asm
@@ -0,0 +1,170 @@
+PORTA = $6001
+DDRA = $6003
+T1LCL = $6004
+T1LCH = $6005
+ACR = $600b
+PCR = $600c
+IFR = $600d
+IER = $600e
+
+SER = %00000001
+RCLK = %00000010
+SRCLK = %00000100
+
+INTERVAL = 33 ; increase counter 3 times per scond
+WAIT_INTERVAL = 99 ; wait one second on button press
+
+CURRENT = $0 ; current counter
+VISIBLE = $1 ; visible counter (as last printed to the 7-segment display)
+TICKS = $2 ; internal ticks counter (on overflow increment counter)
+RUNNING = $3 ; if counter is running or stopped
+COUNTER = $4 ; counter, increment on button press, show only shortly when button pressed
+
+ .org #$f800
+
+reset:
+ sei ; disallow interrupts during initialization
+
+ ldx #$FF ; initialize call stack to $1FF
+ txs
+
+ lda #%11000010 ; enable CA1 and timer1 interrupts
+ sta IER
+ lda #$0 ; negative edge triggering
+ sta PCR
+
+ lda ACR
+ and #$7F
+ ora #%01000000 ; setup timer for free running timer1, no PB7
+ sta ACR
+
+ lda #%00000111 ; set output on 7seg control pins of PORTA
+ sta DDRA
+
+ lda #$0 ; initialize 8-bit counter and tick counter
+ sta CURRENT
+ lda #$FF ; the visible counter is different at init, so we force
+ sta VISIBLE ; the drawing of the initial value
+ lda #INTERVAL
+ sta TICKS
+ lda #$FF
+ sta RUNNING
+
+ lda #$0 ; initialize button press counter
+ sta COUNTER
+
+ lda #$0F ; initialize counter of VIA timer1 ($270f = 9999 at 1MHz)
+ sta T1LCL
+ lda #$27
+ sta T1LCH
+
+ cli ; allow interrupts now
+
+mainloop: ; main loop, just print value of counter
+ sei
+ lda CURRENT
+ cmp VISIBLE
+ cli
+ beq mainloop
+ jsr print7seg ; update value
+ sei
+ lda CURRENT
+ sta VISIBLE
+ cli
+ jmp mainloop
+
+print7seg:
+ ldy #$8 ; 8 bits to shift
+loop7seg:
+ rol a
+ bcc zerobit ; C=0, bang a zero to SER
+onebit:
+ ldx #(SER) ; C=1, bang a one to SER
+ stx PORTA
+ ldx #(SER | SRCLK)
+ stx PORTA
+ ldx #(SER)
+ stx PORTA
+ jmp next
+zerobit:
+ ldx #$0 ; C=0, bang a zero to SER
+ stx PORTA
+ ldx #SRCLK
+ stx PORTA
+ ldx #$0
+ stx PORTA
+ jmp next
+next:
+ dey
+ bne loop7seg
+ rol a ; restore A register
+output:
+ ldx #0 ; bang RCLK to store output in latch
+ stx PORTA
+ ldx #RCLK
+ stx PORTA
+ ldx #0
+ stx PORTA
+ rts
+
+nmi:
+ rti
+
+irq:
+ pha ; save state
+ txa
+ pha
+ tya
+ pha
+ lda IFR ; check interrupt register of VIA
+ bpl irq_done ; bit 7 set? if not, not an interrupt of the VIA
+ asl ; bit 6 in sign (timer1)
+ bmi timer1
+ asl ; bit 5 in sign (timer2, unused)
+ asl ; bit 4 in sign (cb1, unused)
+ asl ; bit 3 in sign (cb2, unused)
+ asl ; bit 2 in sign (shift, unused)
+ asl ; bit 1 in sign (CA1)
+ bmi ca1
+ asl ; bit 0 in sign (CA2, unused)
+ jmp irq_done ; no more interrupt to handle from VIA
+
+timer1:
+ bit T1LCL ; clear timer1 interrupt
+ lda #$FF
+ cmp RUNNING
+ bne irq_done
+
+tick:
+ dec TICKS
+ bne irq_done
+ lda #INTERVAL
+ sta TICKS
+ inc CURRENT ; increment internal counter
+ jmp irq_done
+
+ca1:
+ lda RUNNING ; toggle running flag
+ eor #$FF
+ sta RUNNING
+ inc COUNTER
+ lda COUNTER
+ sta CURRENT
+ lda #WAIT_INTERVAL
+ sta TICKS
+ bit PORTA ; clear CA1 interrupt (button press)
+ jmp irq_done
+
+irq_done:
+ pla
+ tay
+ pla
+ tax
+ pla
+ cli
+ rti
+
+ .org #$fffa
+ .word nmi
+ .word reset
+ .word irq