summaryrefslogtreecommitdiff
path: root/roms/7seg_counter_irq_timer_start_stop.asm
blob: 3c7aed5b8ecbbf028d36e5409df0975978bdede1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
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