Subject: Odd Happenings....

From: "Marc H" <[email-masked]>
Date: Sat, 29 Oct 2011 18:04:39 -0000

While goofing around today I noticed something.....

I have been programming some music (cacophony really) using the VDP interrupt for the timer.  Not by hooking the ISR but by monitoring >8802 directly like this...

loop    movb  @8802,r1
        andi  r1,>8000
        jne   loop1

The rest of the program does very little so the bulk of the time is spent in this little loop.  Problem is I was getting more misses than correct hits.  The music was way out of time.  I took a chance and put a delay in the monitoring loop of >00ff between reads of >8802 and that seems to have solved the problems which brings up this theory and question.....

I surmise that if the CPU is trying to read >8802 while the VDP is trying to write to it then the VDP write is inhibited and the VDP interrupt is missed for that cycle.  Does anyone know if this is correct or not.  (Maybe my machine is sick...)

---

From: mark wills <[email-masked]>
Date: Sat, 29 Oct 2011 21:37:02 +0100 (BST)

Sounds like a valid explanation to me. Is there some bus contention going on? I guess the VDP can't get a slice of time to assert itself on the bus?

>________________________________
>From: Marc H <[email-masked]>
>To: [email-masked]
>Sent: Saturday, 29 October 2011, 19:04
>Subject: [TI994A] Odd Happenings....
>
>------------------------------------
>
>Yahoo! Groups Links
>
>
>
>
>
>

---

From: "Stuart" <[email-masked]>
Date: Sat, 29 Oct 2011 22:49:11 -0000

According to the VDP manual "... Reading the (status) register will clear the interrupt flag, F. However, asynchronous reads will cause the (interrupt/frame) flag F to be reset and therefore missed. Consequently, the status register should be read only when the VDP interrupt is pending."

Which, translated, possibly means if you read it directly too often, it ain't going to work!

Stuart.

---

From: ti99_forever <[email-masked]>
Date: Sat, 29 Oct 2011 16:35:18 -0700 (PDT)

You are disabling the regular interrupts? Meaning the console interrupt routine? It reads the VDP interrupt and stores it in scratchpad, thereby resetting the flag.

>From: Stuart <[email-masked]>
>Sent: Saturday, October 29, 2011 6:49 PM
>Subject: [TI994A] Re: Odd Happenings....
>

---

From: Tony Knerr <[email-masked]>
Date: Sat, 29 Oct 2011 19:50:25 -0400

As Emeril would say,

Bam!

:)

On 10/29/2011 7:35 PM, ti99_forever wrote:
> You are disabling the regular interrupts? Meaning the console 
> interrupt routine? It reads the VDP interrupt and stores it in 
> scratchpad, thereby resetting the flag.
>
>     ------------------------------------------------------------------------
>     *From:* Stuart <[email-masked]>
>     *To:* [email-masked]
>     *Sent:* Saturday, October 29, 2011 6:49 PM
>     *Subject:* [TI994A] Re: Odd Happenings....
>
>     According to the VDP manual "... Reading the (status) register
>     will clear the interrupt flag, F. However, asynchronous reads will
>     cause the (interrupt/frame) flag F to be reset and therefore
>     missed. Consequently, the status register should be read only when
>     the VDP interrupt is pending."
>
>     --- In [email-masked] <mailto:[email-masked]>,
>     "Marc H" <marc.hull@...> wrote:
>     >
>     > I have been programming some music (cacophony really) using the
>     VDP interrupt for the timer.  Not by hooking the ISR but by
>     monitoring >8802 directly like this...
>     >
>     > loop    movb  @8802,r1
>     >        andi  r1,>8000
>     >        jne  loop1
>     >
>     > The rest of the program does very little so the bulk of the time
>     is spent in this little loop.  Problem is I was getting more
>     misses than correct hits.  The music was way out of time.  I took
>     a chance and put a delay in the monitoring loop of >00ff between
>     reads of >8802 and that seems to have solved the problems which
>     brings up this theory and question.....
>     >
>     > I surmise that if the CPU is trying to read >8802 while the VDP
>     is trying to write to it then the VDP write is inhibited and the
>     VDP interrupt is missed for that cycle.  Does anyone know if this
>     is correct or not.  (Maybe my machine is sick...)
>     >
>

---

From: Marc Hull <[email-masked]>
Date: Sat, 29 Oct 2011 19:19:01 -0700 (PDT)

yes... limi 0

--- On Sat, 10/29/11, ti99_forever <[email-masked]> wrote:

From: ti99_forever <[email-masked]>
Subject: Re: [TI994A] Re: Odd Happenings....
To: "[email-masked]" <[email-masked]>
Date: Saturday, October 29, 2011, 6:35 PM

  

Subject: [TI994A]
 Re: Odd Happenings....

Stuart.

  jne   loop1

Yahoo! Groups Links

---

From: Insane Multitasker <[email-masked]>
Date: Sat, 29 Oct 2011 21:43:31 -0500

It might be all the fumes from cleaning my house this evening.... but why are you not just using the VDP interrupt CRU bit?  Am I missing something besides a little O2? ;)

To: [email-masked]
From: [email-masked]
Date: Sat, 29 Oct 2011 21:37:02 +0100
Subject: Re: [TI994A] Odd Happenings....

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: Marc Hull <[email-masked]>
Date: Sun, 30 Oct 2011 07:09:52 -0700 (PDT)

uh....   What the hell is the VDP CRU interrupt bit ?    That's not like a left handed screw driver or board stretcher is it ?

--- On Sat, 10/29/11, Insane Multitasker <[email-masked]> wrote:

From: Insane Multitasker <[email-masked]>
Subject: RE: [TI994A] Odd Happenings....
To: [email-masked]
Date: Saturday, October 29, 2011, 9:43 PM

  

      

 

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: Tony Knerr <[email-masked]>
Date: Sun, 30 Oct 2011 10:58:20 -0400

On 10/30/2011 10:09 AM, Marc Hull wrote:
>
> uh....   What the hell is the VDP CRU interrupt bit ?    That's not 
> like a left handed screw driver or board stretcher is it ?
>

Here's some code that may help, shamelessly stolen from Ben Yates. I 
hope he doesn't mind. :)   Tony

* This routine hooks the timer interrupts
* It expects a delay value in R0
* and a branch vector in R1 (or >0000 to use a forever loop)
TIMEON SOCB @H20,@>83FC Set timer interrupt flag bit
MOV R12,@OLDR12 Preserve caller's R12
CLR R12 CRU base address >0000
SBZ 1 Disable peripheral interrupts
SBZ 2 Disable VDP interrupts
SBO 3 Enable timer interrupts
MOV R1,@>83E2 Zero if we want to wait in a forever loop
JEQ EVERLP
SETO @>83E2 Flad: we intend to branch elsewhere
MOV R1,@>83EC Set address where to go
SLA R0,1 Make room for clock bit
INC R0 Set the clock bit to put TMS9901 in clock
mode
LDCR R1,15 Load the clock bit + the delay
SBZ 0 Back to normal mode: start timer
MOV @OLDR12,R12 Restore caller's R12
B *R11
* This routines "unhooks" the timer interrupt
TIMOFF SZCB @H20,@>83FC Clear timer interrupt flag bit
MOV R12,@OLDR12 Preserve caller's R12
CLR R12 CRU base address >0000
SBO 1 Enables peripheral interrupts
SBO 2 Enables VDP interrupts
SBZ 3 Disables timer interrupts
MOV @OLDR12,R12 Restore caller's R12
B *R11
OLDR12 DATA 0 Temporary buffer for caller's R12
* This is our ISR. All it does is to count the number of times it is called.
OURISR INC @COUNT Count the number of times the timer fired
LWPI >83C0 Back to interrupt workspace (R13, R15
unchanged)
MOV @RETPT,R14 Get the return point (as R14 contains OURISR)

RTWP Return to IRET
COUNT DATA 0 The event counter
RETPT DATA 0 The return point
* This is the main program. It starts the timer with a delay of 1/3 second
* and uses the value in COUNT to time a process.
MAIN LI R0,>3D09 That's 333 usec
LI R1,OURISR That's our hook
CLR @COUNT Reset the counter
BL @TIMEON Start the timer
...
LI R11,IRET
MOV R11,@RETPT Set the return point
LOOP LIMI 2 There must be such a loop in the timed
process
IRET LIMI 0 Since our ISR will return here
... Perform the action to be timed
JNE LOOP Until done

BL @TIMOFF Stops the timer
MOV @COUNT,R1 Divide by 3 to get the number of seconds
...

---

From: Jeffrey White <[email-masked]>
Date: Sun, 30 Oct 2011 08:11:55 -0700 (PDT)

Because interrupts are tied to Level 1 on the 99/4A, the CRU (9901) is used to 
determine the source.  This can be seen by reading the interrupt service routine 
(TI Intern).

If you are going to poll the VDP for the interrupt, you should poll the VDP 
interrupt CRU bit (CLR R12; TB 2) to catch it when it occurs, clear the bit in 
the VDP status byte by reading it, and clear/enable the VDP interrupt (SBO 2).

Jeff White

________________________________
From: Marc Hull <[email-masked]>
To: [email-masked]
Sent: Sun, October 30, 2011 10:09:52 AM
Subject: RE: [TI994A] Odd Happenings....

uh....   What the hell is the VDP CRU interrupt bit ?    That's not like a left 
handed screw driver or board stretcher is it ?

--- On Sat, 10/29/11, Insane Multitasker <[email-masked]> wrote:

>It might be all the fumes from cleaning my house this evening.... but why are 
>you not just using the VDP interrupt CRU bit?  Am I missing something besides a 
>little O2? ;)
>
> 
>
>
>Sounds like a valid explanation to me. Is there some bus contention going on? I 
>guess the VDP can't get a slice of time to assert itself on the bus?
>
>
>
>
>
>
>
>>I have been programming some music (cacophony really) using the VDP interrupt 
>>for the timer.  Not by hooking the ISR but by monitoring >8802 directly like 
>>this...
>>
>>loop    movb  @8802,r1
>>        andi  r1,>8000
>>        jne  loop1
>>
>>The rest of the program does very little so the bulk of the time is spent in 
>>this little loop.  Problem is I was getting more misses than correct hits.  The 
>>music was way out of time.  I took a chance and put a delay in the monitoring 
>>loop of >00ff between reads of >8802 and that seems to have solved the problems 
>>which brings up this theory and question.....
>>
>>I surmise that if the CPU is trying to read >8802 while the VDP is trying to 
>>write to it then the VDP write is inhibited and the VDP interrupt is missed for 
>>that cycle.  Does anyone know if this is correct or not.  (Maybe my machine is 
>>sick...)
>>
>>
>>
>>

---

From: Insane Multitasker <[email-masked]>
Date: Sun, 30 Oct 2011 14:42:23 -0500

When you see Jeff's response, it could elicit one of these: 
 
http://s3.amazonaws.com/kym-assets/entries/icons/original/000/000/554/facepalm.jpg?1282626490

To: [email-masked]
From: [email-masked]
Date: Sun, 30 Oct 2011 07:09:52 -0700
Subject: RE: [TI994A] Odd Happenings....

  

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: ti99_forever <[email-masked]>
Date: Sun, 30 Oct 2011 14:18:43 -0700 (PDT)

Where'd *that* code come from... there must be another Ben Yates...

>From: Tony Knerr <[email-masked]>
>Sent: Sunday, October 30, 2011 10:58 AM

---

From: Tony Knerr <[email-masked]>
Date: Sun, 30 Oct 2011 19:30:10 -0400

It  _ was_ another Ben Yates, a much younger one... :-)

On 10/30/2011 5:18 PM, ti99_forever wrote:
>     *From:* Tony Knerr <[email-masked]>
>     *Sent:* Sunday, October 30, 2011 10:58 AM
>     *Subject:* Re: [TI994A] Odd Happenings....
>
>
>
>>     uh....   What the hell is the VDP CRU interrupt bit ?    That's
>>     not like a left handed screw driver or board stretcher is it ?
>>
>
>     Here's some code that may help, shamelessly stolen from Ben Yates.
>     I hope he doesn't mind. :)   Tony
>
>
>     TIMEON SOCB @H20,@>83FC Set timer interrupt flag bit <snip>
>

---

From: Marc Hull <[email-masked]>
Date: Sun, 30 Oct 2011 18:39:10 -0700 (PDT)

Well it would if I had an inkling of what he meant ;-).  

Seriously I have come to the conclusion that simultaneous accesses to >8802 by the VDP and the CPU cause the VDP status to be corrupt.  The delay loop seems to have corrected the issue or at least reduced the probability of such a clash.  

Perhaps a simple explanation as to why I should be using the CRU and how it is behaving might help me see the light....

--- On Sun, 10/30/11, Insane Multitasker <[email-masked]> wrote:

From: Insane Multitasker <[email-masked]>
Subject: RE: [TI994A] Odd Happenings....
To: [email-masked]
Date: Sunday, October 30, 2011, 2:42 PM

  

      

 

  

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

    [email-masked]

---

From: Insane Multitasker <[email-masked]>
Date: Sun, 30 Oct 2011 23:58:48 -0500

Well, best I can tell, you want to perform an operation based on the 60hz 
video interrupt.  Your best bet is to test whether or not an interrupt occured
prior to reading the status register.  Assuming the console ISR is disabled,
you would do so by checking for a VDP interrupt via CRU bit 2, 
with R12=0, something like this: 
 
LIMI 0
LOOP  CLR R12
TB 2
JEQ NOVIDINT
movb @>8802,R1   (I think this is the right sequence)
...do your timed activity here
...
NOVIDINT  *skip timed activity, do other things
JMP  LOOP
 
If you are using the ISR together with your own code, you may be able to 
tell the console ISR to ignore VDP interrupt processing, then hook into the 
user ISR to test for vid interrupts yourself and take action (ie, your own
sprite motion or sound handling routines) accordingly. 
 
Your delay loop is no longer required because you have shifted the
VDPINT test from a byte transfer to a CRU transfer.
 
:)
 
There are many ways to skin this 'cat'...

To: [email-masked]
From: [email-masked]
Date: Sun, 30 Oct 2011 18:39:10 -0700
Subject: RE: [TI994A] Odd Happenings....

  

  

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: Insane Multitasker <[email-masked]>
Date: Mon, 31 Oct 2011 00:02:56 -0500

Some great info here from Thierry...
 
http://www.nouspikel.com/ti99/tms9901.htm
 
VDP interrupts
The videoprocessor TMS9918 can be programmed to issue an interrupt each time it refreshes the screen, which occurs 60 times per second (50 times per second for the European model TMS9929A). This interrupt is routed to the interrupt controller TMS9901 that echos it on CRU bit 2 and triggers the INTREQ* line.
Once the ISR has determined that the interrupt came from the VDP it does the following: 

Move sprites in auto-motion, if any. 
Play sound list, if any. 
Test <quit> key, reset the TI-99/4A if it's pressed. 
Read VDP status and place it in byte >837B. 
Increment by two a timeout counter and turn the screen off when it reaches zero. 
Call a user defined ISR, if any. 
Four bits in byte >83C2 are used to enable/disable the first 3 functions: 
If the first bit (weight >80) is set, the ISR jumps directly to point 4. 
If the second bit (>40) is set, the ISR won't handle sprites. 
If the third bit (>20) is set, the ISR won't process the sound list. 
If the fourth bit (>10) is set, the ISR won't test the <quit> key.

To: [email-masked]
From: [email-masked]
Date: Sun, 30 Oct 2011 23:58:48 -0500
Subject: RE: [TI994A] Odd Happenings....

LIMI 0
LOOP  CLR R12
TB 2
JEQ NOVIDINT

 
:)

 

  

  

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: Marc Hull <[email-masked]>
Date: Mon, 31 Oct 2011 13:46:08 -0700 (PDT)

Well I'm trying to avoid using the ISR.  I am aware of the hook but have decided to go another way although I am not so sure that the advice I took was so correct on this point.  Here is a question.....

Once the CRU bit is set does it stay set until the VDP register connected at >8802 is cleared or is it only active when the interrupt is being issued ?  

--- On Mon, 10/31/11, Insane Multitasker <[email-masked]> wrote:

From: Insane Multitasker <[email-masked]>
Subject: RE: [TI994A] Odd Happenings....
To: [email-masked]
Date: Monday, October 31, 2011, 12:02 AM

  

      

VDP interrupts

 

 
LIMI 0
LOOP  CLR R12
TB 2
JEQ NOVIDINT

 
:)

 

  

  

loop    movb  @8802,r1
        andi  r1,>8000
        jne  loop1

Yahoo! Groups Links

---

From: Insane Multitasker <[email-masked]>
Date: Mon, 31 Oct 2011 21:51:07 -0500

Understood.  I only copied the info for reference. The first paragraph is most important and ties into the previous email.  
 
From my experience, the CRU bit 2 remains set until cleared by reading the status register or until you turn VDP
interrupts off.  Thus a tight loop checking CRU 2 will never miss an interrupt. What you do after the encounter
it is up to you.    To catch the next interrupt, you must first read (clear) the status register.   It may be 
prudent to do so immediately upon catching the vid interrupt, but likely won't matter, since you would not
know if you exceeded 1/60th of a second without some fancy footwork or timing.  

To: [email-masked]
From: [email-masked]
Date: Mon, 31 Oct 2011 13:46:08 -0700
Subject: RE: [TI994A] Odd Happenings....

 
 
:)

---

From: "Michael Zapf" <[email-masked]>
Date: Tue, 01 Nov 2011 10:39:45 -0000

Seems to match the description in the TMSS9918 manual (on Whtech):

<quote>
2.3.1 Interrupt Flag (F)

The F status flag in the status register is set to 1 at the end of the raster scan of the last line of the active display. It is reset to 0 after the status register is read or when the VDP is externally reset. If the Interrupt Enable Bit in VDP Register 1 is active (1), the VDP interrupt output (INT) will be active (low) whenever the F status flag is a 1.

Note that the status register needs to be read frame by frame in order to clear the interrupt and receive the new interrupt of the next frame.
</quote>

As for the CRU lines, the interrupt inputs do not latch values, so they have the value of their input pin at all times.

Michael

---

From: Jeffrey White <[email-masked]>
Date: Wed, 2 Nov 2011 22:40:59 -0700 (PDT)

The CRU, 9901, and interrupts can be confusing.  The following all effectively 
disable VDP interrupts:

--To Ignore All Interrupts--
LIMI 0  turn off all interrupts

--To Ignore Just the VDP Interrupt--
CLR R12  set CRU base to 0
SBZ 2 disable INT2 on the 9901, which comes from the VDP

--To Disable the VDP Interrupt--
***IN THE DATA SEGMENT***
VDPIE    BYTE >20 3rd msbit is interrupt enable 
EVEN
...
***IN THE PROGRAM CODE***
LI R0,>0081 setup lsbyte for write to VDP register 1
MOVB (at)VDPR1,R0 get CPU RAM-stored contents of VDP register 1
SZCB (at)VDPIE,R0 clear the bit
MOVB R0,(at)VDPWA write the data to VDP
SWPB R0 
MOVB R0 move the data written to VDP into register 1
-----------------------

Except in the last case, you can always determine a VDP interrupt with something 
like the following:

CLR R12 set CRU base to 0
SBZ 0 set 9901 to interrupt mode
TB 2 check INT2, the VDP interrupt
JNE VDPINT yes, there was a VDP interrupt
...
VDPINT MOVB (at)VDPSTA,(at)VSTAT read the VDP status register, clearing the 
interrupt
...

While the VDP interrupt is enabled with the 3rd msbit of VDP register 1, it will 
always be activated on the VDP interrupt output line to the Interrupt 2 input of 
the 9901 once the Interrupt Flag bit -- msbit of VDP status register -- is set.  
The VDP interrupt at the 9901 is not reset until the VDP interrupt output is 
reset, which happens when the VDP status register is read or the VDP interrupt 
enable in VDP Register 1 is cleared.

That last point I made is important.  When the VDP status register is read to 
clear the interrupt, it could be set again almost immediately -- even in the 
middle of the CPU instruction used to read the status.

Thus, depending on what the rest of your code is doing, you may want to 
synchronize to the interrupt cycle.

Jeff White

p.s.: I used "(at)" in place of the at-symbol.

Sent: Mon, October 31, 2011 10:51:07 PM

Understood.  I only copied the info for reference. The first paragraph is most 
important and ties into the previous email.  

From my experience, the CRU bit 2 remains set until cleared by reading the 
status register or until you turn VDP
interrupts off.  Thus a tight loop checking CRU 2 will never miss an interrupt. 
What you do after the encounter
it is up to you.    To catch the next interrupt, you must first read (clear) the 
status register.   It may be 

prudent to do so immediately upon catching the vid interrupt, but likely won't 
matter, since you would not
know if you exceeded 1/60th of a second without some fancy footwork or timing.  

Well I'm trying to avoid using the ISR.  I am aware of the hook but have decided 
to go another way although I am not so sure that the advice I took was so 
correct on this point.  Here is a question.....

Once the CRU bit is set does it stay set until the VDP register connected at 
>8802 is cleared or is it only active when the interrupt is being issued ?

---

From: "Stuart" <[email-masked]>
Date: Thu, 03 Nov 2011 12:53:33 -0000

Although not directly related to what Marc is trying to do now, there's also some info on setting up and using VDP interrupts from 'first principles' on my website here:

<www.avjd51.dsl.pipex.com/tm990/tm990.htm#using_vdp_interrupts>

This is primarily for my TM990 board where I'm able to set/modify the INT 2 interrupt vector at the bottom of memory. With the TI-99/4A, you've got to work within the constraints of the existing ROM power-on code, ISR and hardware.

Stuart.

--- In [email-masked], Jeffrey White <ti994a@...> wrote:
> From: Insane Multitasker <insane_m@...>
> From: marc.hull@...
> --- On Mon, 10/31/11, Insane Multitasker <insane_m@...> wrote:
> 
> 
> >

---

From: Marc Hull <[email-masked]>
Date: Thu, 3 Nov 2011 14:20:23 -0700 (PDT)

I appreciate the reply's to my dilemma.  I guess a better explanation of what I am doing is in order.   I am not reaaly using the VDP interrupt to interrupt anythiong.  I am just using it as a throttle of sorts to limit execution speed.  When the signal fires off the program executes one loop and then waits for the next signal.

The problem I was having was that during the pause while checking >8802 I was creating misses by the extremely fast rate of checking.  I believe the CRU method will prevent this and am happy to steal this gem ;-).

As I understand it....  when the VDP signals the interrupt then the CRU bit is set (or reset) and the register @>8802 is written to.  Reading the CRU bit does NOT effect it but clearing the VDP register @>8802 resets the bit.

--- On Thu, 11/3/11, Stuart <[email-masked]> wrote:

From: Stuart <[email-masked]>
Subject: [TI994A] Re: Odd Happenings....
To: [email-masked]
Date: Thursday, November 3, 2011, 7:53 AM

  

Stuart.

--- In [email-masked], Jeffrey White <ti994a@...> wrote:

---

From: mark wills <[email-masked]>
Date: Thu, 3 Nov 2011 21:28:23 +0000 (GMT)

Can you not use the 9901 for exactly this?

Hmmm... I guess the 9901 can't interrupt the 9900 when the timer expires?

How does cassette loading/saving work then?

These are the questions! We demand answers! :)

>Sent: Thursday, 3 November 2011, 21:20

---

From: Marc Hull <[email-masked]>
Date: Thu, 3 Nov 2011 16:07:08 -0700 (PDT)

yes the 9901 can be used for this exact thing but it has it's own pitfalls.

--- On Thu, 11/3/11, mark wills <[email-masked]> wrote:

From: mark wills <[email-masked]>
Subject: Re: [TI994A] Re: Odd Happenings....
To: "[email-masked]" <[email-masked]>
Date: Thursday, November 3, 2011, 4:28 PM

  

        

--- On Thu,
 11/3/11, Stuart <[email-masked]> wrote:

 

Stuart.

--- In [email-masked], Jeffrey White <ti994a@...> wrote:

---

From: "Michael Zapf" <[email-masked]>
Date: Fri, 04 Nov 2011 00:51:08 -0000

> Hmmm... I guess the 9901 can't interrupt the 9900 when the timer expires?

Sure it can. The VDP interrupt line connects to INT2* of the TMS9901, and if that input is configured to trigger an interrupt (must do a SBO 2 for this) it causes the INTREQ* to the CPU to become active on each VDP interrupt which happens once the bottom of the screen is reached.

Unfortunately, TI decided to hardwire the interrupt level indicator to 0001, so that any interrupt via the INTREQ* line is set to level 1. It can be blocked by LIMI 0 and enabled by LIMI 1 (so any LIMI 2 in the TI-99/4A could as well be a LIMI 1). 

The only problem here is that with a LIMI 2 you will also enable the whole console-internal interrupt handling code which may cause a visible performance loss.

So it may indeed be must faster to poll the CRU bit with interrupts disabled in the CPU (LIMI 0), and active in the 9901. Polling will not affect the VDP flag, but as I recently posted here you *must* read the status, or the flag will never be reset.

Michael

---

From: Jeffrey White <[email-masked]>
Date: Thu, 3 Nov 2011 22:06:04 -0700 (PDT)

The console interrupt handling is sufficient for what it was designed to do.

Setting up a user interrupt routine which ties to the console interrupt routine 
is doable, but the overhead in doing it makes polling attractive in many cases.  
I believe someone has calculated the minimal overhead added by the console 
interrupt routine when all that was needed is a user interrupt routine.  Might 
have been nicer had the user interrupt routine hook been the first thing checked 
by the console.

I believe Mark Wills is suggesting the use of the 9901 internal clock/event 
timer interrupt.  Well, in fact the 9901 can interrupt the 9900 when 
the internal clock/event timer expires.  This will happen on Interrupt 3 of the 
9901.  

Unfortunately, the INT3 pin of the 9901 is used for keyboard/joystick input.  
Keys N, M, comma, period, forward slash, equal sign, and the two joystick fire 
buttons are read on the external INT3 programmed as an input.

(Maybe putting the VDP interrupt on INT3 instead of INT2 would have been a 
better idea.  Thus, if the 9901 internal clock/event timer was active, it would 
mask the VDP interrupt.)

INT3 through INT10 of the 9901 are connected to the keyboard/joystick 
interface.  These inputs are active low just like the VDP interrupt is active 
low.  It is possible to set up keypresses or joystick to activate the interrupt 
routine by playing with the 9901 interrupt mask bits.

9901 Output CRU bits 18, 19, and 20 select the keyboard/joystick inputs at CRU 
bits 3 through 10 (INT3 through INT10).  If bits 18-20 are all zero, then the 
CRU bits 3 through 10 are defined as follows:

INT3 -- equal sign 
INT4 -- space bar
INT5 -- ENTER
INT6 -- not used
INT7 -- FCTN
INT8 -- SHIFT
INT9 -- CTRL
INT10 -- not used

The above also gives a clue as to why FCTN= was used for the quit keypress -- 
FCTN and = are on the same "row" of the keyboard.

FCTN is in "column" 7, along with: 1, 2, 3, 4, 5, joystick 1 up, joystick 2 up, 
and alpha lock.  Note that is 9 keys, and there are only 8 rows.  Alpha lock has 
its own "row select", CRU output bit 21.

That is enough of that for now.

Jeff White

Sent: Thu, November 3, 2011 7:07:08 PM