source: buchla-68k/ram/timeint.s

Last change on this file was 16badfe, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Use correct FLOPVBL address.

  • Property mode set to 100644
File size: 12.4 KB
Line 
1| ------------------------------------------------------------------------------
2| timeint.s -- MIDAS-VII timer interrupt handler
3| Version 15 -- 1989-07-20 -- D.N. Lynx Crowe
4| ------------------------------------------------------------------------------
5
6| This code replaces the interrupt handler in bios.s, which is known to
7| have a bug in it, and adds support for the VSDD and an array of programable
8| timers with 1 Ms resolution.
9
10| WARNING: There are equates to addresses in the bios EPROM which may change
11| when the bios is reassembled. If the bios is reassembled be sure to update
12| the equates flagged by "<<<=====".
13
14| The addresses currently in the equates are for EPROMs dated 1988-04-18 or
15| 1988-06-20 ONLY.
16
17| ------------------------------------------------------------------------------
18| Hardware timer usage:
19| ---------------------
20| Timer 1 PLL divider for score clock -- fixed at 64
21| Timer 2 PLL divider for score clock -- nominally 3200
22| Timer 3 1 Ms Real Time Clock
23
24| ------------------------------------------------------------------------------
25
26 .text
27
28 .xdef tsetup | tsetup() -- timer setup function
29 .xdef timeint | timer interrupt handler
30
31 .xdef M1IoRec | MIDI channel 1 IoRec
32 .xdef M2IoRec | MIDI channel 2 IoRec
33 .xdef S1IoRec | RS232 channel 1 IoRec
34 .xdef S2IoRec | RS232 channel 2 IoRec
35 .xdef timers | timer array -- short timers[NTIMERS]
36 .xdef vi_clk | VSDD scroll delay timer
37 .xdef vi_tag | VSDD VI tag
38
39 .xref lclsadr | score object base address
40 .xref lclscrl | score object scroll offset
41 .xref v_odtab | VSDD object descriptor table
42
43 .page
44| ==============================================================================
45
46FRAMES = 0 | set non-zero to enable frame pulses
47
48| Equates to variables in bios.s:
49| -------------------------------
50| These variables are permanently assigned.
51
52TIMEVEC = 0x00000400 | LONG - System timer trap vector
53
54FC_SW = 0x00000420 | WORD - Frame clock switch
55FC_VAL = 0x00000422 | LONG - Frame clock value
56
57HZ_1K = 0x0000049A | LONG - 1000 Hz clock
58HZ_200 = 0x0000049E | LONG - 200 Hz clock
59FRCLOCK = 0x000004A2 | LONG - 50 Hz clock
60
61T3COUNT = 0x000004AA | WORD - Timer 3 count
62
63| ------------------------------------------------------------------------------
64
65| WARNING: The address of "FLOCK" depends on the version of the bios EPROM.
66| The address below is for EPROMs dated 1988-04-18 or 1988-06-20 ONLY.
67
68FLOCK = 0x00000E0C | WORD - Floppy semaphore <<<=====
69
70| ==============================================================================
71
72| Equates to routines in bios.s:
73| ------------------------------
74
75| WARNING: The address of "FLOPVBL" depends on the version of the bios EPROM.
76| The address below is for EPROMs dated 1988-04-18 or 1988-06-20 ONLY.
77
78FLOPVBL = 0x001016FE | floppy VI handler address <<<=====
79
80| ==============================================================================
81
82 .page
83
84| Hardware address equates:
85| -------------------------
86TI_VEC = 0x00000070 | Timer interrupt autovector
87
88TIMER = 0x003A0001 | Timer base address
89M1_ACIA = 0x003AC001 | MIDI ACIA channel 1 base address
90
91| ------------------------------------------------------------------------------
92
93| Timer register equates:
94| -----------------------
95TIME_CRX = TIMER | Control register 1 or 3
96TIME_CR2 = TIMER+2 | Control register 2
97TIME_T1H = TIMER+4 | Timer 1 high byte
98TIME_T1L = TIMER+6 | Timer 1 low byte
99TIME_T2H = TIMER+8 | Timer 2 high byte
100TIME_T2L = TIMER+10 | Timer 2 low byte
101TIME_T3H = TIMER+12 | Timer 3 high byte
102TIME_T3L = TIMER+14 | Timer 3 low byte
103
104| Serial I/O equates:
105| -------------------
106ACIA_CFR = 2 | CFR offset from ACIA base
107DTR_BIT = 1 | DTR bit in ACIA CFR1
108
109IO_CFR1 = 29 | cfr1 offset in M1IoRec
110
111| ==============================================================================
112
113| Miscellaneous equates:
114| ----------------------
115IPL7 = 0x0700 | IPL mask for interrupt disable
116
117FCMAX = 0x00FFFFFF | Maximum frame counter value
118FCMIN = 0x00000000 | Minimum frame counter value
119
120NTIMERS = 8 | Number of timers in the timer array
121
122XBIOS = 14 | XBIOS TRAP number
123X_PIOREC = 0 | X_PIOREC code
124SR1_DEV = 0 | RS232 ACIA channel 1
125SR2_DEV = 1 | RS232 ACIA channel 2
126MC1_DEV = 3 | MIDI ACIA channel 1
127MC2_DEV = 4 | MIDI ACIA channel 2
128| ==============================================================================
129
130 .page
131| ==============================================================================
132| tsetup -- tsetup() -- timer setup function
133| ==============================================================================
134
135tsetup: move.w sr,-(a7) | Save old interrupt mask
136 ori.w #IPL7,sr | Disable interrupts
137
138 move.w #SR1_DEV,-(a7) | Establish S1IoRec
139 move.w #X_PIOREC,-(a7) | ...
140 trap #XBIOS | ...
141 add.l #4,a7 | ...
142 move.l d0,S1IoRec | ...
143
144 move.w #SR2_DEV,-(a7) | Establish S2IoRec
145 move.w #X_PIOREC,-(a7) | ...
146 trap #XBIOS | ...
147 add.l #4,a7 | ...
148 move.l d0,S2IoRec | ...
149
150 move.w #MC1_DEV,-(a7) | Establish M1IoRec
151 move.w #X_PIOREC,-(a7) | ...
152 trap #XBIOS | ...
153 add.l #4,a7 | ...
154 move.l d0,M1IoRec | ...
155
156 move.w #MC2_DEV,-(a7) | Establish M2IoRec
157 move.w #X_PIOREC,-(a7) | ...
158 trap #XBIOS | ...
159 add.l #4,a7 | ...
160 move.l d0,M2IoRec | ...
161
162 .page
163
164 clr.w FC_SW | Stop the frame clock
165 clr.l FC_VAL | ... and reset it
166 clr.w vi_tag | Clear VSDD VI tag
167 clr.w vi_clk | Clear VSDD delay timer
168 clr.w lclsadr | Clear score scroll address
169 clr.w lclscrl | Clear score scroll offset
170
171 lea timers,a0 | Point at timer array
172 move.w #NTIMERS-1,d0 | Setup to clear timer array
173
174tclr: clr.w (a0)+ | Clear a timer array entry
175 dbra d0,tclr | Loop until done
176
177 move.l #nullrts,TIMEVEC | Set timer interrupt vector
178 move.l #timeint,TI_VEC | Set timer trap vector
179
180 move.b #0x00,TIME_T1H | Setup timer 1 (PLL)
181 move.b #0x1F,TIME_T1L | ... for divide by 64
182 move.b #0x0C,TIME_T2H | Setup timer 2 (FC)
183 move.b #0x7F,TIME_T2L | ... for divide by 3200
184 move.b #0x03,TIME_T3H | Setup timer 3 (RTC)
185 move.b #0x20,TIME_T3L | ... for 1Ms interval
186 move.b #0x42,TIME_CRX | Setup CR3
187 move.b #0x41,TIME_CR2 | Setup CR2
188 move.b #0x81,TIME_CRX | Setup CR1
189 move.b #0x80,TIME_CRX | Start the timers
190
191 move.w (a7)+,sr | Restore interrupts
192
193nullrts: rts | Return to caller
194
195 .page
196| ==============================================================================
197| timeint -- timer interrupt handler
198| ==============================================================================
199
200timeint: movem.l d0-d7/a0-a6,-(a7) | Save registers
201 move.b TIME_CR2,d0 | Get timer interrupt status
202| ------------------------------------------------------------------------------
203| process 1 MS timer
204| ------------------------------------------------------------------------------
205 btst.l #2,d0 | Check timer 3 status
206 beq tmi02 | Jump if not active
207
208 move.b TIME_T3H,d1 | Read timer 3 count
209 lsl.w #8,d1 | ...
210 move.b TIME_T3L,d1 | ...
211 move.w d1,T3COUNT | ... and save it
212
213 addq.l #1,HZ_1K | Update 1ms clock (1 KHz)
214
215 move.l d0,-(a7) | Preserve D0
216| ------------------------------------------------------------------------------
217| process VSDD timer
218| ------------------------------------------------------------------------------
219 tst.w vi_tag | Does the VSDD need service ?
220 beq updtime | Jump if not
221
222 move.w vi_clk,d0 | Get VSDD scroll delay timer
223 subq.w #1,d0 | Decrement timer
224 move.w d0,vi_clk | Update timer
225 bne updtime | Jump if it's not zero yet
226
227 move.w lclsadr,v_odtab+12 | Update scroll address
228 move.w lclscrl,v_odtab+10 | Update scroll offset
229 clr.w vi_tag | Reset the tag
230
231 .page
232
233| ------------------------------------------------------------------------------
234| process programable timers
235| ------------------------------------------------------------------------------
236
237updtime: move.w #NTIMERS-1,d0 | Setup timer array counter
238 lea timers,a0 | Point at timer array
239
240tdcr: move.w (a0),d1 | Get timer array entry
241 beq tdcr1 | Jump if already 0
242
243 subq.w #1,d1 | Decrement timer
244
245tdcr1: move.w d1,(a0)+ | Store updated timer value
246 dbra d0,tdcr | Loop until done
247
248| ------------------------------------------------------------------------------
249| process timer hook vector
250| ------------------------------------------------------------------------------
251 movea.l TIMEVEC,a0 | Get RTC vector
252 move.w #1,-(a7) | Pass 1 msec on stack
253 jsr (a0) | Process RTC vector
254 addq.l #2,a7 | Clean up stack
255
256 move.l (a7)+,d0 | Restore D0
257
258 .page
259| ------------------------------------------------------------------------------
260| process 5 Ms clock
261| ------------------------------------------------------------------------------
262 move.w tdiv1,d1 | Update divider
263 addq.w #1,d1 | ...
264 move.w d1,tdiv1 | ...
265
266 cmpi.w #5,d1 | Do we need to update HZ_200 ?
267 blt tmi02 | Jump if not
268
269 addq.l #1,HZ_200 | Update 5ms clock (200 Hz)
270| ------------------------------------------------------------------------------
271| process 20 Ms floppy clock
272| ------------------------------------------------------------------------------
273 move.w tdiv2,d1 | Update divider
274 addq.w #1,d1 | ...
275 move.w d1,tdiv2 | ...
276
277 cmpi.w #4,d1 | Do we need to update FRCLOCK ?
278 blt tmi01 | Jump if not
279
280 addq.l #1,FRCLOCK | Update 20 Ms clock (50 Hz)
281 tst.w FLOCK | See if floppy is active
282 bne tmi00 | Don't call FLOPVBL if so
283
284 jsr FLOPVBL | Check on the floppy
285
286tmi00: move.w #0,tdiv2 | Reset tdiv2
287
288tmi01: move.w #0,tdiv1 | Reset tdiv1
289
290 .page
291| ------------------------------------------------------------------------------
292| process PLL timers
293| ------------------------------------------------------------------------------
294
295tmi02: btst.l #0,d0 | Check timer 1 int
296 beq tmi03 | Jump if not set
297
298 move.b TIME_T1H,d1 | Read timer 1 to clear int.
299 move.b TIME_T1L,d1 | ...
300
301tmi03: btst.l #1,d0 | Check for timer 2 int.
302 beq tmi04 | Jump if not set
303
304 move.b TIME_T2H,d1 | Read timer 2 to clear int.
305 move.b TIME_T2L,d1 | ...
306
307 .page
308| ------------------------------------------------------------------------------
309| update score frame counter
310| ------------------------------------------------------------------------------
311 tst.w FC_SW | Should we update the frame ?
312 beq tmi04 | Jump if not
313
314 bmi tmi05 | Jump if we count down
315
316 move.l FC_VAL,d0 | Get the frame count
317 cmp.l #FCMAX,d0 | See it we've topped out
318 bge tmi06 | Jump if limit was hit
319
320 addq.l #1,d0 | Count up 1 frame
321 move.l d0,FC_VAL | Store updated frame count
322
323 .ifne FRAMES
324 move.w sr,d1 | Preserve interrupt status
325 ori.w #0x0700,sr | Disable interrupts
326
327 movea.l M1IoRec,a0 | Point at M1IoRec
328 move.b IO_CFR1(a0),d0 | Get MIDI-1 CFR1 value
329 or.b #0x80,d0 | Force MSB = 1 for CFR1 output
330 movea.l #M1_ACIA,a0 | Point at MIDI-1 ACIA channel
331 bchg.l #DTR_BIT,d0 | Toggle DTR for output
332 move.b d0,ACIA_CFR(a0) | Output toggled DTR
333 bchg.l #DTR_BIT,d0 | Toggle DTR for output
334 move.b d0,ACIA_CFR(a0) | Output toggled DTR
335 move.w d1,sr | Restore interrupts
336 .endc
337
338 bra tmi04 | Done
339
340tmi07: move.l #FCMIN,FC_VAL | Force hard limit, just in case
341 bra tmi04 | Done
342
343tmi06: move.l #FCMAX,FC_VAL | Force hard limit, just in case
344 bra tmi04 | Done
345
346tmi05: move.l FC_VAL,d0 | Get the frame count
347 ble tmi07 | Done if already counted down
348
349 subq.l #1,d0 | Count down 1 frame
350 move.l d0,FC_VAL | Store udpated frame count
351 bra tmi04 | Done
352
353 nop | Filler to force equal paths
354
355tmi04: movem.l (a7)+,d0-d7/a0-a6 | Restore registers
356 rte | Return to interrupted code
357
358 .page
359| ==============================================================================
360 .bss
361| ==============================================================================
362
363| A note on tdiv1 and tdiv2:
364| --------------------------
365
366| tdiv1 and tdiv2 are actually defined in the bios, but since they could move
367| we define them here and ignore the ones in the bios.
368
369tdiv1: .ds.w 1 | Timer divider 1 (divides HZ_1K)
370tdiv2: .ds.w 1 | Timer divider 2 (divides HZ_200)
371
372| ------------------------------------------------------------------------------
373
374timers: .ds.w NTIMERS | Timer array -- short timers[NTIMERS];
375
376vi_clk: .ds.w 1 | VSDD scroll delay timer
377vi_tag: .ds.w 1 | VSDD VI 'needs service' tag
378
379S1IoRec: .ds.l 1 | address of RS232 channel 1 IoRec
380S2IoRec: .ds.l 1 | address of RS232 channel 2 IoRec
381M1IoRec: .ds.l 1 | address of MIDI channel 1 IoRec
382M2IoRec: .ds.l 1 | address of MIDI channel 2 IoRec
383| ==============================================================================
384
385 .end
Note: See TracBrowser for help on using the repository browser.