Document Navigation
Table Of Contents
Index
Notes
Previous
Next


Interrupts (IRQ)

ReFLEX offers a facility to provide a fairly regular source of interrupts to the 6809's IRQ input.

Note: The emulator's version of FLEX is not at this point configured to respond to an IRQ, so you must turn off interrupts when FLEX or a FLEX utility command is running unless you have defined a service that will not be disturbed by operations within FLEX and the various utility commands FLEX runs. Remember that some UC's destroy memory in the $C100 area, and others run in low user memory. I would suggest using the higher areas for your IRQ service if you want it to be safe, or using the FLEX memend info & controls to move the end of memory down past your service. However, not all FLEX commands properly pay attention to memend! For this reason, I again suggest using high memory if you expect your IRQ service to run concurrently with FLEX. The $E800-$F37F range is ideal.

The interrupt rate may be set via the Execute/IRQ Timing menu item, which specifies how many 6809 instructions are to go by (multiplied by 20) before an interrupt is generated.

The interrupt capability is not based upon a timer, as Windows 95 offers only a timer with a minimum interval of 55 ms and an interval granularity of 55 ms. The "count of instructions" interrupt mechanism that is implemented for the emulator offers an effective granularity of 20 instructions, or about 100 microseconds for a 1 Mhz equivalent machine.

There's a catch, though (isn't there always?). Because the emulator runs faster or slower depending on the speed of the host computer, the settings for a particular interrupt rate will vary across machines. For instance, the game RB that I supply as a graphics demonstration was designed around a 16.66 ms interrupt. I've provided a default interrupt rate (1200*) that approximates this for my 133 Mhz Micron Pentium. On your machine, the game will almost certainly run too fast, or too slow - and you'll need to adjust the interrupt rate accordingly. You can get "in the ballpark" just by using a ratio between my CPU speed and yours; for instance, if you have a P166, then the ratio of 166/133=1.25 applies, and so your setting would be 1.25*1200=1497.

* As a point of interest, the average 6809 instruction length is 4.5 uS (that's an average of all the 6809 instruction cycle times, there's no other way to get even close because instruction usage varies in every program). On my Micron P133, I have to use a value of 1200 to set my interrupt rate to 16.666666 ms. This rate gives an approximate instruction execution time which is .6944 microseconds per instruction (1.44 Mhz average instruction execution rate), or 24,000 instructions in 16.666666 ms. That's about .1543 uS per clock cycle (.6944/4.5), which is an instruction clock of 6.48 Mhz (1/.1543 uS), and a chip clock of 25.9 Mhz (4 x 6.48 Mhz). That's your basic fast 6809!

The application is not multithreaded for the emulation code, so multiple processors shouldn't affect the timing. MMX CPUs likewise shouldn't affect it a great deal as the emulation deals almost exclusively with 8 and 16 bit data items under a large memory model.

What will affect the timing are differences in memory architecture, cache mechanisms, available memory, and for operations that use graphics or large amounts of text manipulation, the display adaptor. If you're looking for a particular interrupt rate, you should be able to get close but you'll have to create a test program, determine the approximate number of instructions per second your machine runs the emulation at, and use that number to set the Execute/IRQ Timing value accordingly.

There is a hidden benefit here, and that is that with an interrupt rate like this, as the emulation slows down due to system factors, the interrupt rate slows in exact proportion, so your program won't be overrun (or at least, it's no more likely to do so that it would be in a real machine.

The Interrupt Mechanism

Interrupts are managed by an emulated 6522 VIA, using its IERG, IFRG and T2CL registers. This is essentially similar to managing the VIA's T2 timer in real hardware, with the exception that the actual timer value is set from the Execute/IRQ Timing menu item, which is necessary because of the extreme difference in host processor speeds and the lack of any but the most primitive timer facilities in Windows 95.

A very serious consequence of this is that you cannot vary the IRQ rate under program control. If newer versions of Windows 95 (98?) have better timer controls available that allow a more precise emulation of the VIAs, I'll almost certainly modify the emulator IRQ handling to reflect that. I believe that in most every case, a "real" interrupt rate is preferable to what we have now.

The following table describes the various actions available to your programs to control IRQ interrupts:

AddressItemProgram ActionEffect
$E04EVIA2+IERGWrite $40T2 Interrupt Off
$E04EVIA2+IERGWrite $C0T2 Interrupt On
$E04DVIA2+IFRGRead: b7=IRQ, b6=T2 flag1 = T2 timer fired
$E048VIA2+T2CLReadTurn off T2 flag
$F3F8PSYMON IRQ VectorWrite address of IRQ serviceLink your IRQ service
CC b4CPU IRQ BitSetInterrupts masked
CC b4CPU IRQ BitClearInterrupts enabled

There are two VIA's. VIA 1 is at $E030-$E03F, VIA 2 is at $E040-$E04F.

AddressRegisterFunction
0DATBB data register in and out
1DATAA data register in and out
2DDRBB data direction register
3DDRAA data direction register
4T1CLTimer 1 counter low byte
5T1CHTimer 1 counter high byte
6T1LLTimer 1 latch low byte
7T1LHTimer 1 latch high byte
8T2CLTimer 2 counter low byte
9T2CHTimer 2 counter high byte
ASFTRShift register
BACRGAuxillary control register
CPCRGPeripheral control register
DIFRGInterrupt flag register
EIERGInterrupt enable register
FDXTAA data output only, no handshake

Note:The emulation of the 6522 VIAs is only complete to the degree required for the interrupt and graphics emulations to function.


Below are minimal interrupt service routines. To use them, follow this procedure:

  1. Call I_INIT
  2. Call I_ON
  3. Call I_OFF. You can now change the interrupt service routines, if needed, or you can turn them back on by calling I_ON. Note that it is generally not sufficient to just mask the I bit in the condition codes; before returning to FLEX, call I_OFF. You don't want FLEX to jump into your custom IRQ service, generally speaking. The exception to that is, of course, things like print spooling (which I've not yet implemented).


PSYIRQ EQU  $F3F8
VIA2   EQU  $E040
IERG   EQU  $E
T2CL   EQU  $8
IN_BIT EQU  $10
IY_MSK EQU  255-IN_BIT

I_INIT PSHS D          SAVE REGS USED
       LDD #I_SVC      POINT TO INTERRUPT SERVICE
       STD >PSYIRQ     INSTALL VECTOR TO PSYMON
       PULS D,PC       RETURN TO CALLER, REGS INTACT

I_ON   PSHS A          SAVE REGS USED
       LDA  #%11000000 TURN ON IS B7=1, T2 FLAG IS B6
       STA  >VIA2+IERG HIT VIA, TURN T2 INTERRUPTS ON
       ANDCC #IY_MSK   ALLOW IRQ'S
       PULS A,PC       RESTORE & EXIT

I_OFF  PSHS A          SAVE REGS USED
       ORCC #IN_BIT    DISALLOW IRQ'S
       LDA  #%01000000 TURN OFF IS B7=0, T2 FLAG IS B6
       STA  >VIA2+IERG HIT VIA, TURN T2 INTERRUPTS OFF
       LDA  >VIA2+T2CL MAKE SURE LAST POTENTIAL IRQ IS ACK'ED
       PULS A,PC       RESTORE & RETURN

*
* REMEMBER: THE IRQ INTERRUPT STACKS EVERYTHING, SO YOU'LL
*           NEED TO ALWAYS HAVE ROOM FOR ALL THE CPU
*           REGISTERS ON THE STACK WHEN USING IRQ SERVICING,
*           PLUS ANY REGISTERS YOU SAVE LOCALLY ON THE STACK
*           WITHIN THE IRQ SERVICE.
*
I_SVC  LDA  >VIA2+T2CL "ACK" INTERRUPT & DROP T2 IRQ FLAG
*
* HERE IS WHERE YOU INSERT YOUR CUSTOM INTERRUPT CODE
*
       RTI             RETURN FROM IRQ SERVICE


Table Of Contents
Index
Notes
Previous
Next
Document Navigation