<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>
Date   : Tue, 02 Dec 1986 18:49:32 GMT
From   : Jon Mandrell <jon@amc.uucp>
Subject: Re: Interrupts on the N* Advantage

Sorry, I tried to mail this, but it got bounced.


If the UART which you are using is a Z80 SIO or DART, then the interrupts
are easy.  If you have something like and 8251, then things get a bit worse.

All of the following assumes that you have a Z80 device out there:

  The Z80 actually has 3 interrupt modes:
  Mode 0:
  A device toggles the INTR line, and the Z80 reads one byte off of the data
bus and executes it.  This instruction is usually a RST, since these are one-
byte CALLs (so they can be forced easily).  The RST instructions run you to
one of 8 locations in low memory (0000, 0008, 0010, 0018, 0020, 0028, 0030,
or 0038).  Actually, you can force any instruction onto the bus, but it doesn't
really make sense to do a INC or whatever when an interrupt happens.
 This is not the mode you would be using.

 Mode 1:
 A device toggles the INTR line, and the Z80 branches to location 0038.  It
pushes the current PC onto the stack, so that you can perform an RET and get
back to your program.  This mode is rarely used.

 Mode 2:
 Welcome to the real power of interrupts.  In this mode, the I register
contains the top 8 bits of an address.  When a device toggles the INTR line,
the Z80 acknowledges it, and then reads in one byte.  This is the bottom
8 bits of an address.

       ((I reg) * 256) + (byte read in)

The Z80 goes to the calculated address, and grabs the word there.  This is
the address vector of the interrupt routine.  Perhaps an example would help.

Suppose you had the following code at location XX00 (any page boundary):



; channel B of the SIO

       dw      chbtx           ; transmitter empty
       dw      chbstat         ; external status change
       dw      chbrx           ; receive char available
       dw      chbspec         ; special receive condition

; channel A of the SIO

       dw      chatx           ; transmitter empty
       dw      chastat         ; external status change
       dw      charx           ; receive char available
       dw      chaspec         ; special receive condition



Then, if you perform the following code:



       ld      a,XX            ; the page number of the interrupt table
       ld      i,a             ; setup the interrupt register



Any interrupt vectors that are placed on the bus will access the above
table.  Still with me?

Now, you need to set the SIO up.  You might want to find a DART or SIO
manual for this code to make sense, but here goes.  I use the OTIR to
output a block of data to the same port.  You need to know the ports that
the SIO resides at.



       ld      hl,table        ; the address of the table
       ld      b,tlen          ; the length of the table
       ld      c,SIO_PORT      ; the port address
       otir



with a table that looks like this:



table:
       db      0               ; junk.  Make sure we are at register 0
       db      18h             ; reset the SIO
       db      4               ; switch to register 4
       db      44h             ; X16 clock, 1 stop, no parity
       db      3               ; switch to register 3
       db      0c1h            ; rx 8 bits, rx enable
       db      5               ; switch to register 5
       db      0eah            ; dtr, tx 8 bits, tx enable, RTS
       db      1               ; register 1 (interrupt enable)
; set Y to 1 if you want a transmitter interrupt, or to 0 if you want to
; poll.  0 is probably the way you want to go.  Note that the value given
; below disables interrupts for special receive conditions, and for status
; changes (modem signals), so that the entries into the interrupt table above
; need not have them.
       db      000110Y0b       ; rx int on all chars
; if this is channel B of the SIO which you are initializing, add the following
       db      2               ; switch to register 2
       db      0               ; vector value
tlen   equ     $-table         ; calculate the length of the table



If you are not initializing channel B with the above code, you need to send
a 2 and a 0 to channel B's control port also.

Well, that is the very basics.  Make sure your interrupt routines end with
the RETI instruction, instead of a RET.  If you have any questions, send
me some mail, or give me a call at (206) 882-5252.

-- 
Jon Mandrell    (ihnp4!uw-beaver!tikal!amc!jon)
Applied Microsystems Corp.

"flames >& /dev/null" - me
<< Previous Message Main Index Next Message >>
<< Previous Message in Thread This Month Next Message in Thread >>