<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="hu">
	<id>http://wiki.amigaspirit.hu/index.php?action=history&amp;feed=atom&amp;title=Amiga_Machine_Language_%28Chapter_5%29</id>
	<title>Amiga Machine Language (Chapter 5) - Laptörténet</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.amigaspirit.hu/index.php?action=history&amp;feed=atom&amp;title=Amiga_Machine_Language_%28Chapter_5%29"/>
	<link rel="alternate" type="text/html" href="http://wiki.amigaspirit.hu/index.php?title=Amiga_Machine_Language_(Chapter_5)&amp;action=history"/>
	<updated>2026-04-23T00:31:31Z</updated>
	<subtitle>Az oldal laptörténete a wikiben</subtitle>
	<generator>MediaWiki 1.39.10</generator>
	<entry>
		<id>http://wiki.amigaspirit.hu/index.php?title=Amiga_Machine_Language_(Chapter_5)&amp;diff=1171&amp;oldid=prev</id>
		<title>Chain-Q: intial import as separate page</title>
		<link rel="alternate" type="text/html" href="http://wiki.amigaspirit.hu/index.php?title=Amiga_Machine_Language_(Chapter_5)&amp;diff=1171&amp;oldid=prev"/>
		<updated>2009-05-25T13:29:27Z</updated>

		<summary type="html">&lt;p&gt;intial import as separate page&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Új lap&lt;/b&gt;&lt;/p&gt;&lt;div&gt;      CHAPTER 5.&lt;br /&gt;
      ---------&lt;br /&gt;
      5.Hardware Registers.&lt;br /&gt;
      --------------------&lt;br /&gt;
        You can get information about hardware functions without using&lt;br /&gt;
        library functions.You can use the hardware registers instead.These&lt;br /&gt;
        are memory locations at particular addresses that are neither in&lt;br /&gt;
        RAM nor in ROM.They are direct interfaces between the processor&lt;br /&gt;
        and its peripheral devices.&lt;br /&gt;
        Each device has a number of hardware registers that the processor&lt;br /&gt;
        accesses to control graphics,sound and input/output.There are lots&lt;br /&gt;
        of possibilities for assembly language programmers.We&amp;#039;ll only be&lt;br /&gt;
        able to go into a few examples.&lt;br /&gt;
        The registers are generally used in byte-wise fashion.You&amp;#039;ll find&lt;br /&gt;
        an example in the next chapter.&lt;br /&gt;
&lt;br /&gt;
      5.1.Checking For Special Keys.&lt;br /&gt;
      -----------------------------&lt;br /&gt;
        Load AssemPro and enter the debugger,select &amp;quot;Parameter-Display-&lt;br /&gt;
        From-Address&amp;quot;and enter $BFEC00.Next select &amp;quot;Parameter-Display-Hex&lt;br /&gt;
        -Dump&amp;quot;to display the memory.(To use the SEKA assembler or a similar&lt;br /&gt;
        monitor program,enter &amp;quot;q $bfec00&amp;quot;.)&lt;br /&gt;
        Yoy&amp;#039;ll see a byte-wise listing of the addresses starting at&lt;br /&gt;
        $BFEC00 in which two bytes always repeat.These two bytes represent&lt;br /&gt;
        the status of the two hardware registers.&lt;br /&gt;
        The mirroring occurs because not all the address bits are used in&lt;br /&gt;
        decoding the address.In addressing this register,only the upper&lt;br /&gt;
        two bytes of the address and the low bit,bit 0,are used.The&lt;br /&gt;
        address of the two registers goes like this:$BFECxx,where the&lt;br /&gt;
        lower address byte xx doesn&amp;#039;t contain any information in bits 1-7.&lt;br /&gt;
        Only bit 0 contains information about the desired register.You&amp;#039;ll&lt;br /&gt;
        find this odd form of addressing with most hardware registers.&lt;br /&gt;
        Let&amp;#039;s look at the information in these registers.Let&amp;#039;s look at the&lt;br /&gt;
        second register,$BFEC01.Hold down the&amp;lt;ALT&amp;gt;key and select&amp;quot;Parameter&lt;br /&gt;
        -Display-HEX-Dump&amp;quot;to redisplay the screen.(SEKA owners must enter&lt;br /&gt;
        &amp;quot;q $bfec00&amp;quot;and press the&amp;lt;ALT&amp;gt;key right after pressing the&amp;lt;Return&amp;gt;&lt;br /&gt;
        key.)You&amp;#039;ll see that contents of every two bytes($BFEC01,$BFEC03,&lt;br /&gt;
        etc...)have been changed to $37.This is the status of the special&lt;br /&gt;
        keys.This is also true for the other special keys.The following&lt;br /&gt;
        keys produce the bytes:&lt;br /&gt;
&lt;br /&gt;
            Shift left      $3F&lt;br /&gt;
            Shift right     $3D&lt;br /&gt;
            Control         $39&lt;br /&gt;
            Alternate       $37&lt;br /&gt;
            Amiga left      $33&lt;br /&gt;
            Amiga right     $31&lt;br /&gt;
&lt;br /&gt;
        You can use this register to have a machine language program check&lt;br /&gt;
        if one of these keys was pressed and then respond by calling or&lt;br /&gt;
        ending a function.A program section might look like this:&lt;br /&gt;
&lt;br /&gt;
        skeys=$bfec01&lt;br /&gt;
              ...&lt;br /&gt;
              cmp.b   #$37,skeys   ;Alternate pressed?&lt;br /&gt;
              beq     function1    ;Yes!&lt;br /&gt;
              cmp.b   #$31,skeys   ;or right Amiga?&lt;br /&gt;
              beq     function2    ;Yes!&lt;br /&gt;
              ...                  ;and so on...&lt;br /&gt;
&lt;br /&gt;
      5.2.Timing.&lt;br /&gt;
      ----------&lt;br /&gt;
        If you want to find out how much time elapsed between two events,&lt;br /&gt;
        you can use a hardware register to keep track of time quickly and&lt;br /&gt;
        precisely.The Amiga contains just such a timekeeper:the I/O port&lt;br /&gt;
        componant.The chip has a 24 bit wide counter that has a 60 Hertz&lt;br /&gt;
        clock.&lt;br /&gt;
        These 24 bits can&amp;#039;t be read at once,for instance with a MOVE.L&lt;br /&gt;
        command,because the register is divided into three bytes.The low &lt;br /&gt;
        byte is at address $BFE801,the middle at $BFE901,and the high byte&lt;br /&gt;
        with bits 16-23 at $BFEA01.&lt;br /&gt;
        Here&amp;#039;s an example of a way to use this register:finding out how&lt;br /&gt;
        long a subroutine takes to run.&lt;br /&gt;
&lt;br /&gt;
        test:&lt;br /&gt;
               bsr     gettime     ;put current time in D7&lt;br /&gt;
               move.l  d7,d6       ;save it in D6&lt;br /&gt;
               bsr     routine     ;routine to be timed&lt;br /&gt;
               bsr     gettime     ;get the time again&lt;br /&gt;
               sub.l   d6,d7       ;elapsed time in&lt;br /&gt;
               ...                 ;1/50 seconds in D7!&lt;br /&gt;
               nop                 ;set break point here to stop&lt;br /&gt;
&lt;br /&gt;
        routine:                   ;test routine&lt;br /&gt;
               move    #500,d0     ;delay counter&lt;br /&gt;
          &lt;br /&gt;
        loop:&lt;br /&gt;
               dbra    d0,loop     ;count down&lt;br /&gt;
               rts&lt;br /&gt;
&lt;br /&gt;
        gettime:&lt;br /&gt;
               move.b  $bfea01,d7  ;hi-byte in D0&lt;br /&gt;
               lsl.l   #4,d7       ;shift twice by 4 bits&lt;br /&gt;
               lsl.l   #4,d7       ;(8 bits shifted)&lt;br /&gt;
               move.b  $bfe901,d7  ;get mid-byte&lt;br /&gt;
               lsl.l   #4,d7       &lt;br /&gt;
               lsl.l   #4,d7       ;shift again&lt;br /&gt;
               move.b  $bfe801,d7  ;get the lo-byte&lt;br /&gt;
               rts                 ;done&lt;br /&gt;
         &lt;br /&gt;
      5.3.Reading The Mouse-Joystick.&lt;br /&gt;
      -------------------------------&lt;br /&gt;
        There are two hardware registers for the mouse and the joystick.&lt;br /&gt;
        They contain the state(or the position)of these input devices.Its&lt;br /&gt;
        interesting that the same port is used with both the mouse and the&lt;br /&gt;
        joystick even through they work completely different.&lt;br /&gt;
        The joystick as four switches that are closed during movement and&lt;br /&gt;
        give off a potential(-)that is related to the movement of the&lt;br /&gt;
        joystick/mouse.The mouses movements give off lots of quick signals&lt;br /&gt;
        -two for horizontal and two for vertical movements.&lt;br /&gt;
        The computor must keep an eye on the ports so that it can evaluate&lt;br /&gt;
        the signals and calculate the new mouse position.This isn&amp;#039;t the&lt;br /&gt;
        work of the processor though;it already has too much to do.&lt;br /&gt;
        You find the status of the mouse/joystick port at address $DFF00A&lt;br /&gt;
        for port 1 and $DFF00C for port 2.The information in these words&lt;br /&gt;
        is for vertical mouse movement in the lower byte and for&lt;br /&gt;
        horizontal movement in the upper byte.&lt;br /&gt;
        AssemPro owners be careful!Don&amp;#039;t read these addresses,because for&lt;br /&gt;
        some reason that causes the computor to crash.This looks&lt;br /&gt;
        interesting(the screen begins to dance)but you can only recover by&lt;br /&gt;
        pressing &amp;lt;RESET&amp;gt;and losing all your data.&lt;br /&gt;
        To read this register,lets write a short program:&lt;br /&gt;
&lt;br /&gt;
        ;(5.3A) mouse&lt;br /&gt;
&lt;br /&gt;
        test:&lt;br /&gt;
              jsr     run       ;test subroutine&lt;br /&gt;
              jmp     test      ;continue until broken&lt;br /&gt;
              nop               ;breakpoint here&lt;br /&gt;
&lt;br /&gt;
        joy= $dff00a&lt;br /&gt;
         &lt;br /&gt;
        run:&lt;br /&gt;
              move    joy,d6    ;data item 1 in D6&lt;br /&gt;
              move    joy+2,d7  ;data item 2 in D7&lt;br /&gt;
              jmp     run       ;rts for SEKA and other&lt;br /&gt;
&lt;br /&gt;
              end&lt;br /&gt;
&lt;br /&gt;
        If you assemble the program and start breakable in the debugger&lt;br /&gt;
        (SEKA-&amp;quot;j run&amp;quot;),D6 and D7 contain the contents of the two registers&lt;br /&gt;
        Move the mouse a bit and watch the register contents.&lt;br /&gt;
        As you see,the value in D6 is different.If you just move the mouse&lt;br /&gt;
        horizontaly,only the upper bytes value is different,if just moved&lt;br /&gt;
        vertically only the upper byte is different.&lt;br /&gt;
        You are not getting the absolute position of the mouse pointer on&lt;br /&gt;
        the screen.You can see that easily by moving the mouse in the&lt;br /&gt;
        upper left corner,then reading the value by restarting the program&lt;br /&gt;
        and moving the mouse left again.As you can see,the registers&lt;br /&gt;
        contents are always relative.&lt;br /&gt;
        Change the program as follows:&lt;br /&gt;
&lt;br /&gt;
        ;(5.3B)                   mouse difference&lt;br /&gt;
&lt;br /&gt;
        test:&lt;br /&gt;
              jsr      run        ;test subroutine&lt;br /&gt;
              jmp      test       ;continue until broken&lt;br /&gt;
              nop                 ;breakpoint here&lt;br /&gt;
&lt;br /&gt;
        joy= $dff00a&lt;br /&gt;
&lt;br /&gt;
        run:&lt;br /&gt;
              move     d7,d6      ;old position in D6&lt;br /&gt;
              move     joy,d7     ;new position in D7&lt;br /&gt;
              sub      d7,d6      ;difference in D6&lt;br /&gt;
              jmp      run        ;rts for SEKA and other&lt;br /&gt;
&lt;br /&gt;
              end&lt;br /&gt;
&lt;br /&gt;
        Start Breakable(right-Amiga-A)in the AssemPro debugger and watch&lt;br /&gt;
        D6,the result is zero or D7.(SEKA owners have to start the program&lt;br /&gt;
        two times.The result in D6 is zero.)If you move the mouse,D6&lt;br /&gt;
        contains the difference between the old and new positions since&lt;br /&gt;
        the start.You&amp;#039;ll find the vertical and horizontal positions of the&lt;br /&gt;
        mouse relative to the last time you looked.In this way,you can use&lt;br /&gt;
        this register to find the relative mouse movement between two&lt;br /&gt;
        checks.&lt;br /&gt;
        Now to check the joysticks.Put a joystick in port 2 and change the&lt;br /&gt;
        address $DFF00A to $DFF00C in the program.Start Breakable in the&lt;br /&gt;
        AssemPro debugger and watch D6,the result is zero or D7.(SEKA&lt;br /&gt;
        owners have to start the program two times.The result in D6 is&lt;br /&gt;
        zero.)&lt;br /&gt;
        Move the joystick up.You&amp;#039;ll get the value $FF00.One was subtracted&lt;br /&gt;
        from the upper byte.Let the joystick loose.This time you get the&lt;br /&gt;
        value $100-one is added.You&amp;#039;ll get the same effect if you move the&lt;br /&gt;
        joystick left-after you let go,one is subtracted.&lt;br /&gt;
        The individual movements and their effects on the joystick program&lt;br /&gt;
        are:&lt;br /&gt;
&lt;br /&gt;
                       UP      $FF00       HI-BYTE -1&lt;br /&gt;
                       DOWN    $FFFF       LO-BYTE -1&lt;br /&gt;
                       LEFT    $0100       HI-BYTE +1&lt;br /&gt;
                       RIGHT   $0001       LO-BYTE +1&lt;br /&gt;
&lt;br /&gt;
        These values aren&amp;#039;t terribly reliable.If you move the joystick a&lt;br /&gt;
        lot and then look at the value,you&amp;#039;ll find a crazy value in D6.&lt;br /&gt;
        This is because the input driver thinks that a mouse is attached.&lt;br /&gt;
        Nevertheless,this is the quickest way to read a joystick.In this&lt;br /&gt;
        way,an external device that gives off evaluatable TTL signals can&lt;br /&gt;
        be connected to the port and watched by a machine language&lt;br /&gt;
        program.&lt;br /&gt;
        Now you just need to find out whether the fire button has been&lt;br /&gt;
        pressed,and you&amp;#039;ll know how to get all the information you need&lt;br /&gt;
        from the joystick.The buttons state is in bit 7 of the byte that&lt;br /&gt;
        is in memory location $BFE001.If the bit is set,the button was&amp;#039;nt&lt;br /&gt;
        pressed.That&amp;#039;s true for the joystick connected to port 2.Bit 6 of&lt;br /&gt;
        this byte contains the buttons state when the joystick is in port&lt;br /&gt;
        1 or the state of the left mouse button.&lt;br /&gt;
        Let&amp;#039;s stay on port 2.You can test bit 7 to execute a function when&lt;br /&gt;
        the joystick button is pressed without any problems.Bit 7 is the&lt;br /&gt;
        sign bit.You can use this program segment:&lt;br /&gt;
&lt;br /&gt;
             tst.b   $bfe001     ;was fire button 2 hit?&lt;br /&gt;
             bpl     fire        ;yes!branch&lt;br /&gt;
&lt;br /&gt;
        The TST.B instruction tests the addressed byte and sets the Z and&lt;br /&gt;
        the N flag.If the N flag is set,you know that bit 7 of the tested&lt;br /&gt;
        byte is set.Since the fire button turns on LO potential,the bit is&lt;br /&gt;
        erased when the button is pressed.The N flag works that way with&lt;br /&gt;
        the TST command as well.The BPL command in the program above&lt;br /&gt;
        branches if the button was pressed.The PL stands for plus and is&lt;br /&gt;
        set when the sign bit is cleared.&lt;br /&gt;
        Here is the complete program to check the fire button and joystick&lt;br /&gt;
        difference:&lt;br /&gt;
&lt;br /&gt;
        ;(5.3C) fire button and joy difference&lt;br /&gt;
&lt;br /&gt;
        test:&lt;br /&gt;
               jsr     run        ;test subroutine&lt;br /&gt;
               tst.b   $bfe001    ;was fire button 2 hit?&lt;br /&gt;
               bpl     fire       ;yes! branch&lt;br /&gt;
               jmp     test       ;continue until broken&lt;br /&gt;
&lt;br /&gt;
        joy = $dff00a&lt;br /&gt;
        run:&lt;br /&gt;
               move    d7,d6      ;old position in D6&lt;br /&gt;
               move    joy,d7     ;new position in D7&lt;br /&gt;
               sub     d7,d6      ;difference in D6&lt;br /&gt;
               jmp     run        ;rts for SEKA and other&lt;br /&gt;
&lt;br /&gt;
        fire:&lt;br /&gt;
               nop                ;breakpoint here&lt;br /&gt;
&lt;br /&gt;
               end&lt;br /&gt;
&lt;br /&gt;
      5.4.Tone Production.&lt;br /&gt;
      -------------------&lt;br /&gt;
        It&amp;#039;s fun to make noises and sounds.The Amiga lets you use Audio&lt;br /&gt;
        Devices and various I\O structures to play tones,noises and/or&lt;br /&gt;
        music pieces in the background.You&amp;#039;ll leave this method to C or&lt;br /&gt;
        Basic programmers,since you can use short machine language&lt;br /&gt;
        programs to directly program the audio hardware.&lt;br /&gt;
        The Paula chip has all the capabilities needed for tone production&lt;br /&gt;
        This chip can be accessed using the hardware registers of the&lt;br /&gt;
        processor.No library of any high level language can do more than&lt;br /&gt;
        you can-program the chip.&lt;br /&gt;
        How does it work?Since the disk uses Direct Memory Access(DMA)to&lt;br /&gt;
        get information,you just need to tell it where to look for the&lt;br /&gt;
        tone or tone sequences that you would like played.You also need to&lt;br /&gt;
        tell it how to interpret the data.&lt;br /&gt;
        Lets start with the easiest case-producing a constant tone.A tone&lt;br /&gt;
        like this consists of a single oscillation that is repeated over&lt;br /&gt;
        and over.If you make a diagram of the oscillation,you see the wave&lt;br /&gt;
        form of the oscillation.There are several standard waves: sine,&lt;br /&gt;
        square,triangle and saw tooth.The simplest is the square wave.&lt;br /&gt;
        To produce a square wave,you just need to turn the loud speaker on&lt;br /&gt;
        and off.The frequency that occurs here is the frequency of the&lt;br /&gt;
        tone. &lt;br /&gt;
        You want to produce such a tone using the Amiga.First you need to&lt;br /&gt;
        make a table that contains the amplitude of the tone you wish to&lt;br /&gt;
        produce.For a square wave,you only need two entries in the table,a&lt;br /&gt;
        large and a small value.Since the sound chip in the Amiga has&lt;br /&gt;
        amplitude values between -128 and +127,our table looks like this:&lt;br /&gt;
&lt;br /&gt;
        soundtab:&lt;br /&gt;
               dc.b -100,100&lt;br /&gt;
&lt;br /&gt;
        You need to give the address of the table to the sound chip.You&lt;br /&gt;
        have four choices,since the Amiga as four sound channels.The&lt;br /&gt;
        address of the hardware register in which the table address for&lt;br /&gt;
        channel 0 must be written is $DFF0A0;for channel 1 it is $DFF0B0;&lt;br /&gt;
        for channel 2 its $DFF0C0;for channel 3 its $DFF0D0.For stereo&lt;br /&gt;
        output,channels 0 and 3 control the left loud speaker.Channels 1&lt;br /&gt;
        and 2 control the right loud speaker.For example,choose channel 0&lt;br /&gt;
        and write the following:&lt;br /&gt;
&lt;br /&gt;
               move.l  #soundtab,$DFF0A0   ;address of the table&lt;br /&gt;
&lt;br /&gt;
        Next you need to tell the sound chip how many items there are in&lt;br /&gt;
        the table.The data is read from beginning to end and sent to the&lt;br /&gt;
        loud speaker.Once it reaches the end,it starts over at the&lt;br /&gt;
        beginning.Since the sound chip gets this one word at a time,even&lt;br /&gt;
        though the data is in bytes,the table must always have an even&lt;br /&gt;
        number of bytes.The length that you give it is the number of words&lt;br /&gt;
        the number of bytes/2.&lt;br /&gt;
        You put the length for channel 0 in the register at address&lt;br /&gt;
        $DFF0A4(for channel x just add x*$10!):&lt;br /&gt;
&lt;br /&gt;
               move  #1,$dff0a4   ;length of table in words&lt;br /&gt;
&lt;br /&gt;
        Now you have to tell it how quickly to read the data and output it&lt;br /&gt;
        to the loud speaker.This word determines the frequency.However,it&lt;br /&gt;
        does this &amp;quot;backwards&amp;quot;.The larger the value,the lower the frequency&lt;br /&gt;
        Choose the value 600 for this example:&lt;br /&gt;
&lt;br /&gt;
               move  #600,$dff0a6   ;read in rate&lt;br /&gt;
&lt;br /&gt;
        Now you need to decide the loudness level for the tone or noise.&lt;br /&gt;
        You have 65 different levels to choose from.Lets choose the middle&lt;br /&gt;
        value 40 for our example:&lt;br /&gt;
&lt;br /&gt;
               move  #40,$dff0a8    ;loudness level&lt;br /&gt;
&lt;br /&gt;
        Thats the data that the sound chip needs to produce the tone.&lt;br /&gt;
        However nothing happens yet.What next?The chip can&amp;#039;t tell if the&lt;br /&gt;
        data thats in the registers is valid,so it doesn&amp;#039;t know if it&lt;br /&gt;
        should use the data.&lt;br /&gt;
        You need to work with the DMA control register at address $DFF096&lt;br /&gt;
        to let it know.You only need six bits of this word for your&lt;br /&gt;
        purposes:&lt;br /&gt;
&lt;br /&gt;
        Bit 15 ($8000)  If this bit is set,every bit that is written to&lt;br /&gt;
                        this internal register is set.Otherwise the bits&lt;br /&gt;
                        are erased.Zero bits aren&amp;#039;t affected.This is very&lt;br /&gt;
                        useful because this word also contains DMA&lt;br /&gt;
                        information for disk operations that should&amp;#039;nt be&lt;br /&gt;
                        changed.&lt;br /&gt;
&lt;br /&gt;
        Bit 9 ($200)    This bit makes it posible for the chip to access&lt;br /&gt;
                        DMA memory.If you want to start playing the tone,&lt;br /&gt;
                        you need to set this bit.&lt;br /&gt;
&lt;br /&gt;
        Bit 0-3         Turn channel 0-3 on when bits are set.&lt;br /&gt;
&lt;br /&gt;
        You&amp;#039;ll start your tone by setting bits 15,9 and 0:&lt;br /&gt;
&lt;br /&gt;
               move   #$8000+$200+1,$dff096   ;start DMA&lt;br /&gt;
&lt;br /&gt;
        Heres an example of tone production-this time with tone using a&lt;br /&gt;
        sine wave:&lt;br /&gt;
&lt;br /&gt;
        ;**Sound Generation using hardware registers** (5.5A)&lt;br /&gt;
&lt;br /&gt;
        ctlw = $dff096              ;DMA control&lt;br /&gt;
        cothi = $dff0a0             ;table address HI&lt;br /&gt;
        c0tlo = $c0thi+2            ;table address LO&lt;br /&gt;
        c0tl = $c0thi+4             ;table length&lt;br /&gt;
        c0per = $c0thi+6            ;read in rate&lt;br /&gt;
        c0vol = $c0thi+8            ;loudness level&lt;br /&gt;
        &lt;br /&gt;
        run:                        ;*Produce a simple tone&lt;br /&gt;
             move.l  #table,c0thi   ;table beginning&lt;br /&gt;
             move    #8,c0tl        ;table length--8 words&lt;br /&gt;
             move    #400,c0per     ;read in rate&lt;br /&gt;
             move    #40,c0vol      ;loudness level (volume)&lt;br /&gt;
             move    #$8201,ctlw    ;DMA/Start sound&lt;br /&gt;
             rts&lt;br /&gt;
&lt;br /&gt;
        data                        ;&amp;gt;500K place in CHIP memory&lt;br /&gt;
        table:                      ;sound table:sine&lt;br /&gt;
         dc.b -40,-70,-40,0,40,70,40,0&lt;br /&gt;
&lt;br /&gt;
             end&lt;br /&gt;
&lt;br /&gt;
        To test this subroutine,use AssemPro to assemble the routine,save&lt;br /&gt;
        the program and load it into the debugger.Next set a breakpoint at&lt;br /&gt;
        the RTS,to set the breakpoint in AssemPro select the correct&lt;br /&gt;
        address with the mouse and press the right-Amiga-B keys.Start the&lt;br /&gt;
        program and listen to the tone.You need another routine to turn&lt;br /&gt;
        the tone off,turn your sound down for now.&lt;br /&gt;
        To turn the tone off,you just need to erase bit 0 of the DMA&lt;br /&gt;
        control register.To do this,you just need to write a 0 in bit 15&lt;br /&gt;
        and all the set bits in this register are erased.To erase bit 0,&lt;br /&gt;
        just write a one to the memory location:bit 15=0=&amp;gt; bit 0 is erased&lt;br /&gt;
        Heres a small routine to stop the tone coming from channel 0:&lt;br /&gt;
&lt;br /&gt;
        still:                   ;*turn off tone&lt;br /&gt;
               move    #1,ctlw   ;turn off channel 1&lt;br /&gt;
               rts&lt;br /&gt;
&lt;br /&gt;
        Now lets use the routine in a program to produce a short peep tone&lt;br /&gt;
        that you culd,for instance,use as a key click:&lt;br /&gt;
&lt;br /&gt;
        ;** Producing a Peep Tone **&lt;br /&gt;
        ctlw = $dff096                ;DMA control&lt;br /&gt;
        c0thi = $dff0a0               ;HI table address&lt;br /&gt;
        c0tlo = $c0thi+2              ;LO table address&lt;br /&gt;
        c0tl = $c0thi+4               ;table length&lt;br /&gt;
        c0per = $c0thi+6              ;read in rate&lt;br /&gt;
        c0vol = $c0thi+8              ;volume&lt;br /&gt;
&lt;br /&gt;
        beep:                         ;*Produce a short peep tone&lt;br /&gt;
               move.l  #table,c0thi   ;table beginning&lt;br /&gt;
               move    #8,c0tl        ;table length&lt;br /&gt;
               move    #400,c0per     ;read in rate&lt;br /&gt;
               move    #65,c0vol      ;volume&lt;br /&gt;
               move    #$8201,ctlw    ;Start DMA (sound)&lt;br /&gt;
               move.l  #20000,d0      ;delay counter&lt;br /&gt;
&lt;br /&gt;
        loop:&lt;br /&gt;
               dbra    d0,loop        ;count down&lt;br /&gt;
        &lt;br /&gt;
        still:&lt;br /&gt;
               move    #1,ctlw        ;turn off tone&lt;br /&gt;
               rts&lt;br /&gt;
&lt;br /&gt;
        table:&lt;br /&gt;
               dc.b 40,70,90,100,90,70,40,0,-4,0&lt;br /&gt;
               end&lt;br /&gt;
&lt;br /&gt;
        You can play upto four tones at the same time in such a way that&lt;br /&gt;
        they are independant of each other.The Amiga also offers another&lt;br /&gt;
        method of making the sound more interesting:you can modulate the&lt;br /&gt;
        tone.&lt;br /&gt;
        Lets produce a siren tone.You could do this by figuring out the&lt;br /&gt;
        entire sequence and programming it.However,as you can well imagine&lt;br /&gt;
        thats a lot of work.&lt;br /&gt;
        Its much easier to use two tone channels.Lets use channel 1 for&lt;br /&gt;
        the bass tone and channel 0 for its modulation.Channel 0 needs to&lt;br /&gt;
        hold the envelope of the siren tone.It needs to give the expanding&lt;br /&gt;
        and contracting of the tone at the right speed.&lt;br /&gt;
        You then have two ways that you can have channel zero work with&lt;br /&gt;
        channel one.You can control the volume via channel 0,the read in&lt;br /&gt;
        rate(frequency),or both.For our example,you&amp;#039;ll use frequency&lt;br /&gt;
        modulation.&lt;br /&gt;
&lt;br /&gt;
        Change the program as follows:&lt;br /&gt;
&lt;br /&gt;
        ;** Modulated sound generation via hardware registers **&lt;br /&gt;
        ctlw = $dff096                   ;DMA control&lt;br /&gt;
        adcon = $dff09e                  ;Audio/Disk control&lt;br /&gt;
        c0thi = $dff0a0                  ;HI table address&lt;br /&gt;
        c0tlo = c0thi+2                  ;LO table address&lt;br /&gt;
        c0tl = c0thi+4                   ;table length&lt;br /&gt;
        c0per = c0thi+6                  ;read in rate&lt;br /&gt;
        c0vol = c0thi+8                  ;volume&lt;br /&gt;
&lt;br /&gt;
        run:&lt;br /&gt;
                move.l  #table,c0thi+16  ;table start for channel 1&lt;br /&gt;
                move    #8,c0tl+16       ;table length--8 words&lt;br /&gt;
                move    #300,c0per+16    ;read in rate&lt;br /&gt;
                move    #40,c0vol+16     ;volume&lt;br /&gt;
&lt;br /&gt;
                move.l  #table2,c0thi    ;table start for channel 0&lt;br /&gt;
                move    #8,c0tl          ;table length&lt;br /&gt;
                move    #60000,c0per     ;read in rate&lt;br /&gt;
                move    #30,c0vol        ;volume&lt;br /&gt;
&lt;br /&gt;
                move    #$8010,adcon     ;modulation mode:FM&lt;br /&gt;
                move    #$8203,ctlw      ;start DMA&lt;br /&gt;
                rts&lt;br /&gt;
&lt;br /&gt;
        still:                           ;*Turn Off Tone&lt;br /&gt;
                move    #$10,adcon       ;no more modulations&lt;br /&gt;
                move    #3,ctlw          ;turn off channels&lt;br /&gt;
                rts&lt;br /&gt;
&lt;br /&gt;
        table:                           ;data for basic tone&lt;br /&gt;
         dc.b -40,-70,-90,-100,-90,-70,-40,0&lt;br /&gt;
         dc.b 40,70,90,100,90,70,40,0&lt;br /&gt;
&lt;br /&gt;
        table2:                          ;data for modulation&lt;br /&gt;
         dc.w 400,430,470,500,530,500,470,430&lt;br /&gt;
&lt;br /&gt;
                end&lt;br /&gt;
&lt;br /&gt;
        When you start the program,you&amp;#039;ll here a siren.You can change this&lt;br /&gt;
        tone to your hearts content.&lt;br /&gt;
        Did you notice the added &amp;quot;adcon&amp;quot;register.This register controls&lt;br /&gt;
        the modulation of the audio channel as well as handling disk&lt;br /&gt;
        functions.The same technique is used here as for the DMA control&lt;br /&gt;
        register,bits can only be set if bit 15 is.As a result,you don&amp;#039;t&lt;br /&gt;
        have to worry about the disk bits.I&amp;#039;d recommend against&lt;br /&gt;
        experimentation.&lt;br /&gt;
        Control bit 15 isn&amp;#039;t the only one of interest to you.You can also &lt;br /&gt;
        use bits 0-7,because they determine which audio channel modulates&lt;br /&gt;
        another channel.There is a restriction,though.A channel can only&lt;br /&gt;
        modulate the next higher numbered channel.For this reason you use&lt;br /&gt;
        channel 1 for the basic tone and channel 0 for the modulation in&lt;br /&gt;
        the example.You can&amp;#039;t for example,modulate channel three with&lt;br /&gt;
        channel zero.Channel 3 can&amp;#039;t be used to modulate any other&lt;br /&gt;
        channel.&lt;br /&gt;
&lt;br /&gt;
        Here is an overview of bits 0-7 of the &amp;quot;adcon&amp;quot;register.&lt;br /&gt;
&lt;br /&gt;
        Bit       Function&lt;br /&gt;
        -----------------------------------------------------------------&lt;br /&gt;
         0        Channel 0 modulates the volume of channel 1&lt;br /&gt;
         1        Channel 1 modulates the volume of channel 2&lt;br /&gt;
         2        Channel 2 modulates the volume of channel 3&lt;br /&gt;
         3        Turn of channel 3&lt;br /&gt;
         4        Channel 0 modulates the frequency of channel 1&lt;br /&gt;
         5        Channel 1 modulates the frequency of channel 2&lt;br /&gt;
         6        Channel 2 modulates the frequency of channel 3&lt;br /&gt;
         7        Turn off channel 3&lt;br /&gt;
&lt;br /&gt;
        In the example,you set bit 4,which put channel 0 in charge of&lt;br /&gt;
        channel one&amp;#039;s frequency modulations.&lt;br /&gt;
        When you&amp;#039;ve chosen a channel for use in modulating another channel&lt;br /&gt;
        some of the parameters of the channel change.You don&amp;#039;t need to&lt;br /&gt;
        give volume for this channel,so you can omit it.Now the tables&lt;br /&gt;
        data is looked at as words instead of as bytes.These words are&lt;br /&gt;
        read into the register of the modulated register at a&lt;br /&gt;
        predetermined rate.The Read in Rate Register determines the rate.&lt;br /&gt;
        If you want to modulate the frequency and the volume of another&lt;br /&gt;
        channel,(In the example,set bits 0 and 4 of &amp;quot;adcon&amp;quot;),the data is&lt;br /&gt;
        interpreted a little differently.The first word in the table is&lt;br /&gt;
        the volume,the second is the read in rate,and so on.It alternates&lt;br /&gt;
        back and forth.In this way,you can for instance,produce the siren&lt;br /&gt;
        tone.&lt;br /&gt;
&lt;br /&gt;
      5.5.Hardware Registers Overview.&lt;br /&gt;
      -------------------------------&lt;br /&gt;
        The following tables should give you an overview of the most&lt;br /&gt;
        important hardware registers.Theres not enough room to describe&lt;br /&gt;
        each register,so I&amp;#039;d recommend getting a hold of the appropriate&lt;br /&gt;
        literature.If you experiment with these registers,you should keep&lt;br /&gt;
        in mind that this can cause the computor to crash.Save your data&lt;br /&gt;
        to disk and then take the disk out of the drive,because you might&lt;br /&gt;
        cause the disk drive to execute some wierd functions.&lt;br /&gt;
        Lets start with the PIA&amp;#039;s.This covers the PIA type 8520.You should&lt;br /&gt;
        keep in mind that some functions and connection of the 8520 are&lt;br /&gt;
        integrated into the Amiga and so there are limitations on what you&lt;br /&gt;
        can do with the PIA&amp;#039;s.&lt;br /&gt;
&lt;br /&gt;
        PIA A       PIA B       Registers Meaning&lt;br /&gt;
        ------------------------------------------------------------------&lt;br /&gt;
        BFE001      BFE000      Data register A&lt;br /&gt;
        BFE101      BFE100      Data register B&lt;br /&gt;
        BFE201      BFE200      Data direction register A&lt;br /&gt;
        BFE301      BFE300      Data direction register B&lt;br /&gt;
        BFE401      BFE400      Timer A LO&lt;br /&gt;
        BFE501      BFE500      Timer A HI&lt;br /&gt;
        BFE601      BFE600      Timer B LO&lt;br /&gt;
        BFE701      BFE700      Timer B HI&lt;br /&gt;
        BFE801      BFE800      Event register Bits 0-7&lt;br /&gt;
        BFE901      BFE900      Event register Bits 8-15&lt;br /&gt;
        BFEA01      BFEA00      Event register Bits 16-23&lt;br /&gt;
        BFEB01      BFEB00      Unused&lt;br /&gt;
        BFEC01      BFEC00      Serial data register&lt;br /&gt;
        BFED01      BFED00      Interrupt control register&lt;br /&gt;
        BFEE01      BFEE00      Control register A&lt;br /&gt;
        BFEF01      BFEF00      Control register B&lt;br /&gt;
&lt;br /&gt;
        Some internal meanings:&lt;br /&gt;
&lt;br /&gt;
        $BFE101    Data register for parallel interface&lt;br /&gt;
        $BFE301    Data direction register for the parallel interface&lt;br /&gt;
        $BFEC01    State of the keyboard,contains the last special key&lt;br /&gt;
                   pressed(Shift,Alternate,Control,Amiga)&lt;br /&gt;
&lt;br /&gt;
        Now come the registers that are used for tone production.The first&lt;br /&gt;
        two registers should be treated especially carefully-if they are&lt;br /&gt;
        used wrong,very nasty effects can occur.&lt;br /&gt;
        These registers can be either read or written only.This&lt;br /&gt;
        information is included under R/W in the table.&lt;br /&gt;
&lt;br /&gt;
        Address       R/W    Meaning&lt;br /&gt;
        ------------------------------------------------------------------&lt;br /&gt;
        DFF096         W     Write DMA Control&lt;br /&gt;
        DFF002         R     Read DMA Control and Blitter Status&lt;br /&gt;
        --Audio Channel 0--&lt;br /&gt;
        DFF0AA         W     Data register&lt;br /&gt;
        DFF0A0         W     Pointer to table beginning Bits 16-18&lt;br /&gt;
        DFF0A2         W     Pointer to table beginning Bits 0-15&lt;br /&gt;
        DFF0A4         W     Table length&lt;br /&gt;
        DFF0A6         W     Read in Rate&lt;br /&gt;
        DFF0A8         W     Volume&lt;br /&gt;
        --Audio Channel 1--&lt;br /&gt;
        DFF0BA         W     Data register&lt;br /&gt;
        DFF0B0         W     Pointer to table beginning Bits 16-18&lt;br /&gt;
        DFF0B2         W     Pointer to table beginning Bits 0-15&lt;br /&gt;
        DFF0B4         W     Table length&lt;br /&gt;
        DFF0B6         W     Read in Rate&lt;br /&gt;
        DFF0B8         W     Volume&lt;br /&gt;
        --Audio Channel 3--&lt;br /&gt;
        DFF0CA         W     Data register&lt;br /&gt;
        DFF0C0         W     Pointer to table beginning Bits 16-18&lt;br /&gt;
        DFF0C2         W     Pointer to table beginning Bits 0-15&lt;br /&gt;
        DFF0C4         W     Table length&lt;br /&gt;
        DFF0C6         W     Read in Rate&lt;br /&gt;
        DFF0C8         W     Volume&lt;br /&gt;
        --Audio Channel 4--&lt;br /&gt;
        DFF0DA         W     Data register&lt;br /&gt;
        DFF0D0         W     Pointer to table beginning Bits 16-18&lt;br /&gt;
        DFF0D2         W     Pointer to table beginning Bits 0-15&lt;br /&gt;
        DFF0D4         W     Table length&lt;br /&gt;
        DFF0D6         W     Read in Rate&lt;br /&gt;
        DFF0D8         W     Volume&lt;br /&gt;
&lt;br /&gt;
        Now for the registers that contain information about the joystick,&lt;br /&gt;
        mouse or potentiometer.These addresses have been gone over in part&lt;br /&gt;
        previously.&lt;br /&gt;
&lt;br /&gt;
        Address       R/W    Meaning&lt;br /&gt;
        ------------------------------------------------------------------&lt;br /&gt;
        DFF00A         R     Joystick/Mouse Port 1&lt;br /&gt;
        DFF00C         R     Joystick/Mouse Port 2&lt;br /&gt;
        DFF012         R     Potentiometer pair 1 Counter&lt;br /&gt;
        DFF014         R     Potentiometer pair 2 Counter&lt;br /&gt;
        DFF018         R     Potentiometer connection&lt;br /&gt;
        DFF034         W     Potentiometer port direction&lt;/div&gt;</summary>
		<author><name>Chain-Q</name></author>
	</entry>
</feed>