Sound Blaster 16 Programming Document

                         Written by Ethan Brodsky

                           Version 3.4 - 5/31/96

------------------------------------------------------------
                    Download SB16DOC.ZIP (6,509 bytes)
------------------------------------------------------------

                             Jump to section:

                                 * Disclaimer
                                * Introduction
                       * Sound Blaster 16 DSP I/O Ports
                             * Resetting the DSP
                             * Writing to the DSP
                          * Reading from the the DSP
                       * Programming the DMA Controller
                         * Setting the sampling rate
                            * Digitized sound I/O
                                * DSP Commands
                            * Auto-initialized DMA
                                 * References

------------------------------------------------------------

                                Disclaimer

  This information is distributed AS IS. The author specifically disclaims
 responsibility for any loss of profit or any consequential, incidental, or
  other damages resulting from the use or misuse of this information. This
     information may be freely distributed in any form as long as this
                        disclaimer remains intact.

                               Introduction

 The Sound Blaster 16 is capable of both FM and digitized sounds. Digitized
  sound capibilities range from 8-bit mono 5000 HZ sound all the way up to
 16-bit stereo sound at 44khz. This FAQ documents programming the SB16 DSP
 CT1341 chip for recording and playback of digitized audio. Prior knowledge
      on programming earlier Sound Blaster sound cards is necessary.

                    The Sound Blaster 16 DSP I/O Ports

  The SB16's DSP chip is programming using several I/O ports at a base I/O
 address determined by jumper settings. On the SB16, there are 16 I/O ports
  which are used for FM synthesized music, mixer settings, DSP programming
  and CD-ROM access. Five of these ports are used in programming the DSP.
                          They are listed below.

                              * 2x6h - DSP Reset
                              * 2xAh - DSP Read
      * 2xCh - DSP Write (Command/Data), DSP write-buffer status (Bit 7)
      * 2xEh - DSP Read-buffer status (Bit 7), DSP interrupt acknowledge
                  * 2xFh - DSP 16-bit interrupt acknowledge

                             Resetting the DSP

 You have to reset the DSP before you can program it. The DSP can be reset
                      using the following procedure:

                    1. Write a 1 to the reset port (2x6)
                         2. Wait for 3 microseconds
                    3. Write a 0 to the reset port (2x6)
        4. Poll the read-buffer status port (2xE) until bit 7 is set
          5. Poll the read data port (2xA) until you receive an AA

 The DSP usually takes about 100 microseconds to initialized itself. After
 this period of time, if the return value is not AA or there is no data at
 all, then the SB card may not be installed or an incorrect I/O address is
                                being used.

                            Writing to the DSP

   To write a byte to the SB16, the following procedure should be used:

      1. Read the write-buffer status port (2xC) until bit 7 is cleared
                 2. Write the value to the write port (2xC)

                           Reading from the DSP

   To read a byte from the SB16, the following procedure should be used:

        1. Read the read-buffer status port (2xE) until bit 7 is set
                 2. Read the value from the read port (2xA)

                      Programming the DMA Controller

 The DMA (Direct Memory Access) controller controls data transfers between
I/O devices and memory without using the CPU. An Intel 8237 DMAC integrated
   circut is used to control this. An IBM compatible computer has two DMA
 controllers, one for 8-bit transfers and one for 16-bit transfers. The DMA
     controller, coupled with an external page register, is capable of
 transfering blocks of up 64k to the SB16. Here is information on I/O ports
            and register settings necessary for sound card I/O:

        I/O port addresses for the DMA Address and Count Registers

                                  [Image]

               I/O port addresses for the control registers

                                  [Image]

                I/O port addresses for lower page registers

                                  [Image]

                       Mode register bit assignments

                                  [Image]

                     Write single mask bit assignments

                                  [Image]

DMAC2 is used for 16-bit I/O and DMAC1 is used for 8-bit I/O. The procedure
for starting a transfer is complicated, so I'll list the steps for starting
               the type of DMA transfers used for sound I/O:

           1. Calculate the absolute linear address of your buffer

                     LinearAddr := Seg(Ptr^)*16 + Ofs(Ptr^));

  2. Disable the sound card DMA channel by setting the appropriate mask bit

                      Port[MaskPort] := 4 + (Channel mod 4);

                     3. Clear the byte pointer flip-flop

                          Port[ClrBytePtr] := AnyValue;

                   4. Write the DMA mode for the transfer
        The mode selection bits should be set to 01 for single-mode. The
        address inc/dec bit should be set to 0 for address increment. The
       auto-initialization bit should be set appropriately. I will discuss
      auto-initialized DMA later. The transfer bits should be set to 10 for
     playback and 01 for recording. The channel select should be set to the
      sound card DMA channel. Be aware that "read" means a read from memory
     (Write to sound card) and that "write" means a write to system memory.

                    Port[ModePort] := Mode + (Channel mod 4);

                             Some often used modes are:

                       o 48h+Channel - Single-cycle playback
                     o 58h+Channel - Auto-initialized playback
                        o 44h+Channel - Single-cycle record
                    o 54h+Channel - Auto-initialized recording
    5. Write the offset of the buffer, low byte followed by high byte. For
       sixteen bit data, the offset should be in words from the start of a
      128kbyte page. The easiest method for computing 16-bit parameters is
         to divide the linear address by two before calculating offset.

                                  if SixteenBit
                                       then
                                        begin
                      BufOffset := (LinearAddr div 2) mod 65536;
                         Port[BaseAddrPort] := Lo(BufOffset);
                         Port[BaseAddrPort] := Hi(BufOffset);
                                         end
                                       else
                                        begin
                          BufOffset := LinearAddr mod 65536;
                         Port[BaseAddrPort] := Lo(BufOffset);
                         Port[BaseAddrPort] := Hi(BufOffset);
                                        end;

     6. Write the transfer length, low byte followed by high byte. For an
       8-bit transfer, write the number of bytes-1. For a 16-bit transfer,
                          write the number of words-1.

                     Port[CountPort] := Lo(TransferLength-1);
                        Port[CountPort] := Hi(TransferLength-1);

             7. Write the buffer page to the DMA page register.

                     Port[PagePort] := LinearAddr div 65536;

  8. Enable the sound card DMA channel by clearing the appropriate mask bit

                       Port[MaskPort] := DMAChannel mod 4;

                           Setting the sampling rate

        Unlike earlier Sound Blasters, the SB16 is programmed with actual
       sampling rates instead of time constants. On the SB16, the sampling
       rate is set using DSP commands 41h and 42h. Command 41h is used for
      output and 42h is used for input. I have heard that on the SB16, both
     these command currently do the same thing, but I would recommend using
      the individual commands to guarantee compatibility with future sound
             cards. The procedure for setting the sampling rate is:

          1. Write the command (41h for output rate, 42h for input rate)
          2. Write the high byte of the sampling rate (56h for 22050 hz)
          3. Write the low byte of the sampling rate (22h for 22050 hz)

                              Digitized sound I/O

              To record or play back sound, you should use the following
                                      sequence:

           1. Allocate a buffer that does not cross a 64k physical page
                                      boundary
                     2. Install an interrupt service routine
              3. Program the DMA controller for background transfer
                             4. Set the sampling rate
                       5. Write the I/O command to the DSP
                    6. Write the I/O transfer mode to the DSP
             7. Write the block size to the DSP (Low byte/high byte)

                     Upon interrupt when using single-cycle DMA:

                     1. Program DMA controller for next block
                          2. Program DSP for next block
                      3. Copy next block if double-buffering
         4. Acknowledge the interrupt with the SB by reading from port 2xE
                    for 8-bit sound or port 2xF for 16-bit sound.
        5. Acknowledge the end of interrupt with the PIC by writing 20h to
            port 20h. If the sound card is on IRQ8-15, you must also write
                                     20h to A0h.

                                  DSP commands

                                       D0
            Pause 8-bit DMA mode digitized sound I/O initiated by command
                                        Cxh.
            Applicable to both single-cycle and auto-initialized DMA I/O.
                                       D4
           Continue 8-bit DMA mode digitized sound I/O paused using command
                                         D0.
            Applicable to both single-cycle and auto-initialzied DMA I/O.
                                       D5
            Pause 16-bit DMA mode digitized sound I/O initiated by command
                                        Bxh.
            Applicable to both single-cycle and auto-initialized DMA I/O.
                                       D6
          Continue 16-bit DMA mode digitized sound I/O paused using command
                                         D5.
            Applicable to both single-cycle and auto-initialized DMA I/O.
                                       D9
           Exit 16-bit auto-initialized DMA mode digitized sound I/O after
                            the end of the current block.
                                       DA
            Exit 8-bit auto-initialized DMA mode digitized sound I/O after
                            the end of the current block.
                                       E1
          Get DSP version number. After sending this command, read back two
            bytes form the DSP. The first byte is the major version number
            and the second byte is the minor version number. A SB16 should
          have a DSP version of 4.00 or greater. Check this before using an
                               SB16 specific commands.
                                       Bx
                     Program 16-bit DMA mode digitized sound I/O
             Command sequence: Command, Mode, Lo(Length-1), Hi(Length-1)

                                      Command:
                                       [Image]

                                     Common commands:

                            + B8 - 16-bit single-cycle input
                           + B0 - 16-bit single-cycle output
                          + BE - 16-bit auto-initialized input
                         + B6 - 16-bit auto-initialized output

                                    Mode: [Image]

                                       Cx
                     Program 8-bit DMA mode digitized sound I/O
                 Same procedure as 16-bit sound I/O using command Bx

                                     Common commands:

                            + C8 - 8-bit single-cycle input
                            + C0 - 8-bit single-cycle output
                          + CE - 8-bit auto-initialized input
                          + C6 - 8-bit auto-initialized output

       The FIFO is used to eliminate inconsistencies in the sample period
     when the sound card is not able to get DMA when it needs it. With FIFO
     disabled, the card attempts DMA at precisely the instant that it needs
      a sample. If another device with a higher priority is accessing DMA,
        the sound card waits for the sample and the sampling rate may be
       decreased. The FIFO allows the DMA sample period to be more erratic
       without affecting the audio quality. The FIFO is cleared whenever a
          command is sent to the DSP. In Single-cycle mode, the DSP is
      constantly being reprogrammed. The FIFO may still contain data which
      has not been output when it cleared. To avoid this problem, the FIFO
      should be turned off for single-cycle mode. When in auto-initialized
     mode, the DSP is never reprogrammed. The FIFO can be left on and sound
                           quality will be improved.

                              Auto-initialized DMA

      When single-cycle DMA is used, sound output stops at the end of each
       block. The interrupt handler can start another transfer, but there
       will be a break in output. This causes a click between each block,
        reducing sound quality. When auto-initialized DMA is used, sound
     output loops around at the end of the buffer. The DMA controller keeps
         transfering the same block of memory that the DMA transfer was
      initiated with. When the end of the buffer is reached, it will start
      sending the buffer again by auto-initializing the current offset and
       count registers with the values stored in the base offset and count
        registers. The usual method for achieving click-less output is to
        allocate a buffer and divide it into two blocks. Program the DMA
      controller with the length of the whole buffer, but program the SB16
      with the length of a block. (Half of the buffer) An interrupt occurs
      for each sound card block, so two interrupts will occur each time the
     buffer is played, once at the midpoint (Start of the second block) and
          once at the end (In effect, the start of the first block) The
         interrupt handler should copy data into the block that was just
      finished so that the data is ready when it is needed for output. The
          programming procedure for an auto-initialized DMA transfer is
       identical to the procedure for a single-cycle DMA transfer, except
      that bit 4 of the DMA mode register and bit 3 of the DSP command are
                                      set.

                   Upon interrupt when using auto-initialized DMA:

          1. Copy next chunk into output buffer block that just finished
         2. Acknowledge the interrupt with the SB by reading from port 2xE
                    for 8-bit sound or port 2xF for 16-bit sound.
        3. Acknowledge the end of interrupt with the PIC by writing 20h to
            port 20h. If the sound card is on IRQ8-15, you must also write
                                     20h to A0h.

                             To stop sound immediately:

          o 8-bit - Write DSP command D0h (Pause 8-bit DMA mode digitized
                                     sound I/O)
         o 16-bit - Write DSP command D5h (Pause 16-bit DMA mode digitized
                                     sound I/O)

          Both commands stop sound immediately, without an interrupt.

                To stop the sound at the end of the currently block:

          o 8-bit - Write DSP command DAh (Stop 8-bit auto-init DMA sound
                                        I/O)
         o 16-bit - Write DSP command D9h (Stop 16-bit auto-init DMA sound
                                        I/O)

        These two commands will stop the sound at the end of the current
      block. If your program is not prepared for an interrupt after output
                      is finished, it may cause problems.

       You can also end auto-initialized mode by reprogramming the DSP for
       single-cycle mode. The card then switches from A/I mode to S/C mode
      after the next interrupt. It will then contiue to play or record for
      the length specified, generate an interrupt and stop. This will allow
      you to stop output exactly at the end of the data, without requiring
         the remainder of the DMA buffer to be filled with silence. This
     technique may or may not be useful to you. I would recommend using the
        pause commands documented in in the immediate stop section unless
                 another method is more suited to your purpose.

                                   References

           o Title - - Developer Kit for the Sound Blaster Series, Second
                                      Edition.
                      o Publisher - Creative Technology Ltd.
           o Title 486 Microcomputer Model 401 Board Technical Reference
                                       Manual
                          o Publisher - Intel Corporation
                            o Order-number - 504366-002
        o Title - 8237A High Performance Programmable DMA Controller specs
                          o Publisher - Intel Corporation
                            o Order-number - 231466-005
              o Title - 8259A Programmable Interrupt Controller specs
                          o Publisher - Intel Corporation
                            o Order-number - 231468-003
                            o Title - SMIX Sound System
                             o Author - Ethan Brodsky
                           o Title - SB16SND Sound Code
                             o Author - Ethan Brodsky

  Thanks to Douglas Kaden at Creative Labs for information on 16-bit DMA,
                       FIFO mode, and other topics.

------------------------------------------------------------
                             Back to Home Page
                           View SMIX information
                         View SB16SND information
------------------------------------------------------------

                    Ethan Brodsky 

Discuss this article in the forums


Date this article was posted to GameDev.net: 7/16/1999
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
Audio

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!