Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match_all(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 700

Warning: Invalid argument supplied for foreach() in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 701

Warning: preg_replace(): Compilation failed: group name must start with a non-digit at offset 4 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 705

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722

Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722
Introducing Interrupts - Intellivision Wiki

Introducing Interrupts


Warning: preg_match(): Compilation failed: group name must start with a non-digit at offset 8 in /home/content/30/6867330/html/intellivision/wiki/includes/MagicWord.php on line 722
From Intellivision Wiki

Jump to: navigation, search
(Step 3: Displaying the time)
m (Protected "Introducing Interrupts" ([edit=autoconfirmed] (indefinite) [move=autoconfirmed] (indefinite)))
 
Line 1: Line 1:
 +
[[Category: Programming]][[Category: Tutorial]]
 +
Interrupts are a way for a device in the system to ask the CPU to stop what  
Interrupts are a way for a device in the system to ask the CPU to stop what  
it's currently doing and do something on its behalf, or to inform the CPU
it's currently doing and do something on its behalf, or to inform the CPU
Line 77: Line 79:
         when we return from the interrupt.
         when we return from the interrupt.
     </LI>
     </LI>
-
     <LI>The CPU then jumps to location $1004.  The hardware determines
+
     <LI>The CPU then jumps to location $1004.  The hardware sets
         this address, and there's no easy way to change this address on
         this address, and there's no easy way to change this address on
         the Intellivision.
         the Intellivision.
Line 200: Line 202:
What value gets left in <CODE>VAR</CODE>?  In this case, it looks like the  
What value gets left in <CODE>VAR</CODE>?  In this case, it looks like the  
decrement never happened.  That's because the <CODE>[[MVO]] R0, VAR</CODE>  
decrement never happened.  That's because the <CODE>[[MVO]] R0, VAR</CODE>  
-
writes the incremented value after <CODE>[[MVO]] R1, VAR</CODE> wrote its
+
writes the incremented value after <CODE>[[MVO]] R1, VAR</CODE> wrote the decremented
value.  Also, the decremented value isn't even the right value.
value.  Also, the decremented value isn't even the right value.
<br/><br/>
<br/><br/>
Line 208: Line 210:
call analogy above, this is similar to carrying a hot bowl of soup:  You  
call analogy above, this is similar to carrying a hot bowl of soup:  You  
don't want to spill the soup, and carrying it requires your full attention,  
don't want to spill the soup, and carrying it requires your full attention,  
-
so you want to do so without interruption.
+
so you want to do so without interruption until you safely set down the soup.
<br/><br/>
<br/><br/>
To fix the example above, you can wrap the critical code with  
To fix the example above, you can wrap the critical code with  
Line 285: Line 287:
<br/><br/>
<br/><br/>
-
= Example Using Interrupts:  A simple timer =  
+
= Example 1:  A simple "elapsed time" clock =  
The following example attempts to demonstrate how interrupts work without
The following example attempts to demonstrate how interrupts work without
getting caught up in too many details of how the rest of the system works.
getting caught up in too many details of how the rest of the system works.
-
This example shows a simple timer onscreen that shows how many hours,
+
This example shows a simple elapsed-time clock on screen that shows how many hours,
minutes, seconds and 60<SUP>th</SUP>s of a second (tics) have elapsed  
minutes, seconds and 60<SUP>th</SUP>s of a second (tics) have elapsed  
since the program started.  It uses an interrupt handler to keep track of  
since the program started.  It uses an interrupt handler to keep track of  
Line 302: Line 304:
<OL>
<OL>
-
     <LI>Increment the number of tics per second.  If that number is less than
+
     <LI>Increment the number of tics that have occurred this second.  If that number is less than 60, then we're done updating the time so skip to the end.
-
        60, then we're done updating the time so skip to the end.
+
     </LI>
     </LI>
     <LI>Zero out the # of tics/second and increment the number of seconds.
     <LI>Zero out the # of tics/second and increment the number of seconds.
Line 437: Line 438:
interrupts and read the time with interrupts off.  This copy of the time  
interrupts and read the time with interrupts off.  This copy of the time  
is guaranteed to be consistent no matter what.  For the purposes of this
is guaranteed to be consistent no matter what.  For the purposes of this
-
example, we'll read the time and put a copy of it on the stack with [[PSHR]].
+
example, we'll read the time and put a copy of it on the stack with <CODE>[[PSHR]]</CODE>.
         [[DIS]]                    ; Disable ints (begin critical section)
         [[DIS]]                    ; Disable ints (begin critical section)
Line 464: Line 465:
To display the time, we'll use the [http://sdk-1600.spatula-city.org/ SDK-1600]
To display the time, we'll use the [http://sdk-1600.spatula-city.org/ SDK-1600]
routine <CODE>PRNUM16</CODE>, found  
routine <CODE>PRNUM16</CODE>, found  
-
[http://sdk-1600.spatula-city.org/examples/library/prnum16.asm here].  The
+
[[prnum16.asm|here]].  The
<CODE>PRNUM16.z</CODE> routine prints the number in R0 in a fixed width field,
<CODE>PRNUM16.z</CODE> routine prints the number in R0 in a fixed width field,
complete with leading zeroes.  It prints the value to the screen, starting at  
complete with leading zeroes.  It prints the value to the screen, starting at  
Line 554: Line 555:
         [[CMP]]    PTIC,  R0      ; Has the time changed?
         [[CMP]]    PTIC,  R0      ; Has the time changed?
         [[BEQ]]    @@wait_time    ; No:  Keep looping
         [[BEQ]]    @@wait_time    ; No:  Keep looping
-
+
 
         ;; Step 2:  Snapshot the time  
         ;; Step 2:  Snapshot the time  
         [[DIS]]                    ; Disable ints (begin critical section)
         [[DIS]]                    ; Disable ints (begin critical section)
Line 566: Line 567:
         [[MVI]]    HOUR,  R0      ; Read hours count
         [[MVI]]    HOUR,  R0      ; Read hours count
         [[EIS]]                    ; Enable ints (end critical section)
         [[EIS]]                    ; Enable ints (end critical section)
-
 
+
         ;; Step 3:  Display the updated time
         ;; Step 3:  Display the updated time
         [[MVII]]    #2,    R2      ; Set our field width to 2
         [[MVII]]    #2,    R2      ; Set our field width to 2
         [[MVII]]    #7,    R3      ; Set our format word to "white"
         [[MVII]]    #7,    R3      ; Set our format word to "white"
         [[MVII]]    #$200 + 5*20 + 5, R4    ; Start in row 5, column 5
         [[MVII]]    #$200 + 5*20 + 5, R4    ; Start in row 5, column 5
-
 
+
         [[CALL]]    PRNUM16.z      ; Display the hours
         [[CALL]]    PRNUM16.z      ; Display the hours
         [[INCR]]    R4              ; Leave a blank space after hours
         [[INCR]]    R4              ; Leave a blank space after hours
-
 
+
         [[PULR]]    R0              ; Get minutes
         [[PULR]]    R0              ; Get minutes
         [[CALL]]    PRNUM16.z      ; Display the minutes
         [[CALL]]    PRNUM16.z      ; Display the minutes
Line 605: Line 606:
Labels are free.  Don't be afraid to add labels if it makes the code clearer.
Labels are free.  Don't be afraid to add labels if it makes the code clearer.
<br/><br/>
<br/><br/>
 +
== Setting Things Up ==
== Setting Things Up ==
Line 674: Line 676:
with 0 as well.  It seems like we should be able to combine the two acts.
with 0 as well.  It seems like we should be able to combine the two acts.
<br/><br/>
<br/><br/>
-
It turns out we can.  Addresses $01F0 - $01FF refer to the [[Programmable
+
It turns out we can.  Addresses $01F0 - $01FF refer to the [[Programmable Sound Generator]] (aka. PSG).  We can safely write 0s to all of its locations.
-
Sound Generator]] (aka. PSG).  We can safely write 0s to all of its locations.
+
In fact, this is the preferred way to initialize the PSG when its state is
In fact, this is the preferred way to initialize the PSG when its state is
otherwise unknown.  Thus, we can combine the <CODE>FILLZERO</CODE> and  
otherwise unknown.  Thus, we can combine the <CODE>FILLZERO</CODE> and  
Line 689: Line 690:
us already.)
us already.)
<br/><br/>
<br/><br/>
 +
=== Setting up the Interrupt Handler ===
=== Setting up the Interrupt Handler ===
Finally, all that's left is setting up the interrupt handler to point to
Finally, all that's left is setting up the interrupt handler to point to
-
the timer code we wrote above.  Recall that our routine is called  
+
the time counting code we wrote above.  Recall that our routine is called  
<CODE>MYISR</CODE>.  The following code sets that up:
<CODE>MYISR</CODE>.  The following code sets that up:
Line 707: Line 709:
and INCLUDE directives for all of the library functions.  This particular
and INCLUDE directives for all of the library functions.  This particular
example needs  
example needs  
-
<CODE>[http://sdk-1600.spatula-city.org/examples/library/fillmem.asm fillmem.asm]</CODE>  
+
<CODE>[[fillmem.asm]]</CODE>  
and  
and  
-
<CODE>[http://sdk-1600.spatula-city.org/examples/library/prnum16.asm prnum16.asm]</CODE> from SDK-1600.  Download these files and put them in a directory.
+
<CODE>[[prnum16.asm]]</CODE> from SDK-1600.  Download these files and put them in a directory.
-
Then put the following source code in a new file named <CODE>timer.asm</CODE>
+
Then put the following source code in a new file named <CODE>elapsed.asm</CODE>
in the same directory.  This source code contains all of the snippets from
in the same directory.  This source code contains all of the snippets from
above, along with a ROM header to make it work.  The added portions are in  
above, along with a ROM header to make it work.  The added portions are in  
Line 724: Line 726:
   
   
  <B>
  <B>
-
 
         ROMW    16      ; 16-bit ROM
         ROMW    16      ; 16-bit ROM
         ORG    $5000  ; Standard ROM memory map starts at $5000
         ORG    $5000  ; Standard ROM memory map starts at $5000
-
 
+
  ;----------------------------------------------------------------------------
  ;----------------------------------------------------------------------------
  ; EXEC-friendly ROM header.
  ; EXEC-friendly ROM header.
Line 743: Line 744:
  ONES:  DECLE  1, 1, 1, 1, 1  ; Color stack initialization
  ONES:  DECLE  1, 1, 1, 1, 1  ; Color stack initialization
  ;----------------------------------------------------------------------------
  ;----------------------------------------------------------------------------
-
 
+
-
  TITLE  STRING  $107, "Timer Demo", 0  ; Title string and date (2007)
+
  TITLE  STRING  $107, "Elapsed Time Demo", 0  ; Title string and date (2007)
   
   
  MAIN    PROC
  MAIN    PROC
Line 777: Line 778:
         [[MVI]]    HOUR,  R0      ; Read hours count
         [[MVI]]    HOUR,  R0      ; Read hours count
         [[EIS]]                    ; Enable ints (end critical section)
         [[EIS]]                    ; Enable ints (end critical section)
-
 
+
         ;; Step 3:  Display the updated time
         ;; Step 3:  Display the updated time
         [[MVII]]    #2,    R2      ; Set our field width to 2
         [[MVII]]    #2,    R2      ; Set our field width to 2
         [[MVII]]    #7,    R3      ; Set our format word to "white"
         [[MVII]]    #7,    R3      ; Set our format word to "white"
         [[MVII]]    #$200 + 5*20 + 5, R4    ; Start in row 5, column 5
         [[MVII]]    #$200 + 5*20 + 5, R4    ; Start in row 5, column 5
-
 
+
         [[CALL]]    PRNUM16.z      ; Display the hours
         [[CALL]]    PRNUM16.z      ; Display the hours
         [[INCR]]    R4              ; Leave a blank space after hours
         [[INCR]]    R4              ; Leave a blank space after hours
-
 
+
         [[PULR]]    R0              ; Get minutes
         [[PULR]]    R0              ; Get minutes
         [[CALL]]    PRNUM16.z      ; Display the minutes
         [[CALL]]    PRNUM16.z      ; Display the minutes
Line 846: Line 847:
To assemble the code above, type:
To assemble the code above, type:
-
     as1600 -o timer -l timer.lst timer.asm
+
     as1600 -o elapsed -l elapsed.lst elapsed.asm
And that's it.
And that's it.
Line 855: Line 856:
the main program loop.
the main program loop.
<br/><br/>
<br/><br/>
-
In the background, the interrupt handler updates the time every timer tic.
+
In the background, the interrupt handler updates the elapsed time with every interrupt from the STIC.
This causes the <CODE>@@wait_time</CODE> loop in the main program to exit,
This causes the <CODE>@@wait_time</CODE> loop in the main program to exit,
and the rest of the code to update the displayed time. Wash, rinse, repeat.
and the rest of the code to update the displayed time. Wash, rinse, repeat.
<br/><br/>
<br/><br/>
-
 
+
== Further Things to Contemplate About the Elapsed Time Demo ==
-
== Further Things to Contemplate ==
+
This timer is a pretty simple piece of code.  It's also specific to NTSC
This timer is a pretty simple piece of code.  It's also specific to NTSC
Line 884: Line 884:
The background color behind the timer display is brown.  Why is this?  How
The background color behind the timer display is brown.  Why is this?  How
might you change this?
might you change this?
 +
 +
= Example 2: A simple "wait timer" =
 +
 +
The purpose of this example is to demonstrate how to introduces pauses in
 +
a program.  The "wait timer" consists of two parts:  A short bit of code
 +
in the ISR that decrements a count if it's non-zero, and a separate function
 +
that sets the count and waits for it to become zero.
 +
<br/><br/>
 +
The wait-timer serves two purposes:
 +
<UL>
 +
<LI>Long waits can space events out.  This can be useful if you want to display a message for a moment or otherwise choreograph events.</LI>
 +
<LI>Short waits (such as 1 tic) are useful for waiting to ensure that the screen has updated since changing something that the
 +
interrupt handler might have acted on.  That is, it's a way of figuring out
 +
that an interrupt has occurred.</LI>
 +
</UL>
 +
We'll see an example of the first way of using the wait timer in this example.
 +
Future tutorials will reuse this mechanism for both purposes, which is the
 +
main reason I'm introducing it here.
 +
<br/><br/>
 +
== The Interrupt Handler Code ==
 +
 +
The wait timer code can be inserted into any interrupt handler.  The code
 +
for the wait timer is very simple.  It decrements the value of the variable
 +
<CODE>WTIMER</CODE> if it's non-zero, as shown below:
 +
 +
        [[MVI]]    WTIMER, R0      ; Get current timer count
 +
        [[DECR]]    R0              ; Decrement it
 +
        [[BMI]]    @@expired      ; If it went negative, it's expired
 +
        [[MVO]]    R0,    WTIMER  ; Store updated count
 +
@@expired:
 +
 +
 +
This code can be inserted into any ISR easily.  Alternately, you can set up
 +
many ISRs to call this at the end of their run before exiting.  That's
 +
entirely up to how you want your program to work.  In this example, we'll have
 +
a simple ISR that enables the screen, counts down the wait timer, and then
 +
exits.  The entire ISR is shown below:
 +
 +
 +
;; ======================================================================== ;;
 +
;;  MYISR -- A simple interrupt service routine                            ;;
 +
;; ======================================================================== ;;
 +
MYISR  PROC
 +
        [[MVO]]    R0,    $20    ; Enable the display
 +
         
 +
        [[MVI]]    WTIMER, R0      ; Get current timer count
 +
        [[DECR]]    R0              ; Decrement it
 +
        [[BMI]]    @@expired      ; If it went negative, it's expired
 +
        [[MVO]]    R0,    WTIMER  ; Store updated count
 +
@@expired:
 +
       
 +
        [[JR]]      R5              ; return from interrupt
 +
        ENDP
 +
 +
A more complicated program would clearly have more stuff in its interrupt
 +
handler.  We'll see this in future tutorials.
 +
<br/><br/>
 +
== The Wait Code ==
 +
 +
Programs will call the following function to actually wait for something to
 +
happen.  This function has two entry points.  <CODE>WAIT</CODE> will wait
 +
for the number of tics specified in the word after the <CODE>[[CALL]]</CODE>.
 +
(See
 +
[[Introducing_the_Instruction_Set_Part_3#Passing_Arguments_via_Return_Address|the branch tutorial]] for an explanation of this technique.)  The second entry
 +
point expects the number of tics to wait to be in R0.
 +
 +
;; ======================================================================== ;;
 +
;;  WAIT -- Wait for some number of tics                                    ;;
 +
;;                                                                          ;;
 +
;;  INPUTS for WAIT                                                        ;;
 +
;;      1 decle after call:  Number of tics to wait                        ;;
 +
;;                                                                          ;;
 +
;;  INPUTS for WAIT.1                                                      ;;
 +
;;      R0  Number of tics to wait                                          ;;
 +
;;                                                                          ;;
 +
;;  OUTPUTS                                                                ;;
 +
;;      R0  Zeroed                                                          ;;
 +
;;                                                                          ;;
 +
;;  NOTE                                                                    ;;
 +
;;      Requires WTIMER code in ISR, and interrupts enabled.                ;;
 +
;;                                                                          ;;
 +
;; ======================================================================== ;;
 +
WAIT    PROC
 +
        [[MVI@]]    R5,    R0          ; Get # of tics to wait from after CALL
 +
@@1:    [[MVO]]    R0,    WTIMER      ; Set up wait timer
 +
 
 +
        [[CLRR]]    R0                  ; \
 +
@@wait: [[CMP]]    WTIMER, R0          ;  |- Wait for WTIMER = 0
 +
        [[BNEQ]]    @@wait              ; /
 +
 
 +
        [[JR]]      R5                  ; return
 +
        ENDP
 +
 +
== The Rest ==
 +
 +
For this example, we'll display "Hello" and "World" about one second apart in
 +
as we did previously in the [[Hello World Tutorial]].  We'll also use the
 +
an infinite loop.  We'll reuse [http://sdk-1600.spatula-city.org/ SDK-1600's]
 +
[[print.asm|PRINT]] and [[fillmem.asm|CLRSCR]]
 +
functions.  This results in the following code:
 +
 +
MAIN    PROC
 +
 
 +
        [[CALL]]    CLRSCR              ; Clear the screen
 +
 
 +
        [[MVII]]    #MYISR, R0          ; \
 +
        [[MVO]]    R0,    $100        ;  |_ Write out "MYISR" to $100-$101
 +
        [[SWAP]]    R0                  ;  |  [[Double Byte Data]].
 +
        [[MVO]]    R0,    $101        ; /
 +
        [[EIS]]                        ; Make sure interrupts are enabled
 +
 
 +
@@loop:
 +
        ;; Print "Hello" at row #5, column #7. 
 +
        [[CALL]]    PRINT.fls
 +
        DECLE  7, $200 + 5*20 + 7
 +
        STRING  "Hello", 0
 +
 
 +
        ;; Wait for 1 second
 +
        [[CALL]]    WAIT
 +
        DECLE  60
 +
 
 +
        ;; Print "World" at row #5, column #7. 
 +
        [[CALL]]    PRINT.fls
 +
        DECLE  7, $200 + 5*20 + 7
 +
        STRING  "world", 0
 +
 
 +
        ;; Wait for 1 second
 +
        [[CALL]]    WAIT
 +
        DECLE  60
 +
 
 +
        ;; Do it again
 +
        [[B]]  @@loop
 +
 
 +
        ENDP
 +
 +
 +
There really isn't much to this example, is there?
 +
 +
== Putting it All Together ==
 +
 +
The source listing below puts all the fragments above into a complete program.
 +
Mainly, this just adds the cartridge header, the <CODE>INCLUDE</CODE>
 +
directives to include [[print.asm]] and [[fillmem.asm]]
 +
from SDK-1600, and assigns <CODE>WTIMER</CODE> a location in 8-bit memory. 
 +
The bold portions are the new portions.
 +
 +
<B>
 +
WTIMER  EQU    $102    ; Put WTIMER into 8-bit memory
 +
 +
        ROMW    16      ; 16-bit ROM
 +
        ORG    $5000  ; Standard ROM memory map starts at $5000
 +
 +
;----------------------------------------------------------------------------
 +
; EXEC-friendly ROM header.
 +
;----------------------------------------------------------------------------
 +
ROMHDR: BIDECLE ZERO            ; MOB picture base  (points to NULL list)
 +
        BIDECLE ZERO            ; Process table      (points to NULL list)
 +
        BIDECLE MAIN            ; Program start address
 +
        BIDECLE ZERO            ; Bkgnd picture base (points to NULL list)
 +
        BIDECLE ONES            ; GRAM pictures      (points to NULL list)
 +
        BIDECLE TITLE          ; Cartridge title/date
 +
        DECLE  $03C0          ; Flags:  No ECS title, run code after title,
 +
                                ; ... no clicks
 +
ZERO:  DECLE  $0000          ; Screen border control
 +
        DECLE  $0000          ; 0 = color stack, 1 = f/b mode
 +
ONES:  DECLE  1, 1, 1, 1, 1  ; Color stack initialization
 +
;----------------------------------------------------------------------------
 +
 +
TITLE  STRING  $107, "Wait Timer Demo", 0  ; Title string and date (2007)
 +
 +
MAIN    PROC
 +
</B>
 +
        [[CALL]]    CLRSCR              ; Clear the screen
 +
 
 +
        [[MVII]]    #MYISR, R0          ; \
 +
        [[MVO]]    R0,    $100        ;  |_ Write out "MYISR" to $100-$101
 +
        [[SWAP]]    R0                  ;  |  [[Double Byte Data]].
 +
        [[MVO]]    R0,    $101        ; /
 +
        [[EIS]]                        ; Make sure interrupts are enabled
 +
 
 +
@@loop:
 +
        ;; Print "Hello" at row #5, column #7. 
 +
        [[CALL]]    PRINT.FLS
 +
        DECLE  7, $200 + 5*20 + 7
 +
        STRING  "Hello", 0
 +
 
 +
        ;; Wait for 1 second
 +
        [[CALL]]    WAIT
 +
        DECLE  60
 +
 
 +
        ;; Print "World" at row #5, column #7. 
 +
        [[CALL]]    PRINT.FLS
 +
        DECLE  7, $200 + 5*20 + 7
 +
        STRING  "world", 0
 +
 
 +
        ;; Wait for 1 second
 +
        [[CALL]]    WAIT
 +
        DECLE  60
 +
 
 +
        ;; Do it again
 +
        [[B]]  @@loop
 +
 
 +
        ENDP
 +
 
 +
;; ======================================================================== ;;
 +
;;  MYISR -- A simple interrupt service routine                            ;;
 +
;; ======================================================================== ;;
 +
MYISR  PROC
 +
        [[MVO]]    R0,    $20    ; Enable the display
 +
         
 +
        [[MVI]]    WTIMER, R0      ; Get current timer count
 +
        [[DECR]]    R0              ; Decrement it
 +
        [[BMI]]    @@expired      ; If it went negative, it's expired
 +
        [[MVO]]    R0,    WTIMER  ; Store updated count
 +
@@expired:
 +
       
 +
        [[JR]]      R5              ; return from interrupt
 +
        ENDP
 +
 
 +
;; ======================================================================== ;;
 +
;;  WAIT -- Wait for some number of tics                                    ;;
 +
;;                                                                          ;;
 +
;;  INPUTS for WAIT                                                        ;;
 +
;;      1 decle after call:  Number of tics to wait                        ;;
 +
;;                                                                          ;;
 +
;;  INPUTS for WAIT.1                                                      ;;
 +
;;      R0  Number of tics to wait                                          ;;
 +
;;                                                                          ;;
 +
;;  OUTPUTS                                                                ;;
 +
;;      R0  Zeroed                                                          ;;
 +
;;                                                                          ;;
 +
;;  NOTE                                                                    ;;
 +
;;      Requires WTIMER code in ISR, and interrupts enabled.                ;;
 +
;;                                                                          ;;
 +
;; ======================================================================== ;;
 +
WAIT    PROC
 +
        [[MVI@]]    R5,    R0          ; Get # of tics to wait from after CALL
 +
@@1:    [[MVO]]    R0,    WTIMER      ; Set up wait timer
 +
 
 +
        [[CLRR]]    R0                  ; \
 +
@@wait: [[CMP]]    WTIMER, R0          ;  |- Wait for WTIMER = 0
 +
        [[BNEQ]]    @@wait              ; /
 +
 
 +
        [[JR]]      R5                  ; return
 +
        ENDP
 +
<B>
 +
;; ======================================================================== ;;
 +
;;  Library includes                                                        ;;
 +
;; ======================================================================== ;;
 +
        INCLUDE    "fillmem.asm"
 +
        INCLUDE    "print.asm"
 +
</B>
 +
 +
Copy this out to a file, <CODE>wtdemo.asm</CODE>, along with copies of
 +
<CODE>print.asm</CODE> and <CODE>fillmem.asm</CODE> that were linked to above.
 +
Then assemble with:
 +
 +
    as1600 -o wtdemo -l wtdemo.lst wtdemo.asm
 +
 +
Ta da!  When you run this program, you should get a display that alternates
 +
between "Hello" and "World" in the middle of the screen with a 1 second
 +
delay between each.

Latest revision as of 08:42, 4 December 2010

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox