home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 355 / APDEVKIT.ZIP / AUDIOP.DOC
Text File  |  1992-05-12  |  62KB  |  1,602 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.                     ----==================================----
  7.                     ----====< Audio Port Programming >====----
  8.                     ----==================================----
  9.  
  10.  
  11.  
  12.                                  TABLE OF CONTENTS
  13.  
  14.  
  15.  
  16.                         1. Audio Port overview
  17.  
  18.  
  19.                         2. Programming Considerations
  20.  
  21.                             A. Hardware I/O Addresses
  22.                             B. Audio Port Interface Controller
  23.                             C. Command/Data Handshaking
  24.  
  25.  
  26.                         3. Digital Audio programming
  27.  
  28.                             A. Sending Micro Commands/Data
  29.                             B. Reading Micro Data
  30.                             C. Reading FIFO data
  31.                             D. Writing FIFO data
  32.                             E. Micro Commands
  33.  
  34.  
  35.                         4. FM programming.
  36.  
  37.  
  38.                         5. Interrupt processing.
  39.  
  40.  
  41.                         Appendix A - Hardware Ports & States
  42.  
  43.  
  44.                         Appendix B - Example routines
  45.  
  46.  
  47.  
  48.  
  49.                                    AUDIO PORT OVERVIEW
  50.  
  51.  
  52.             The Audio Port is a portable audio device designed for
  53.         use with laptop or desktop computers. This device, which
  54.         attaches to the standard IBM PC parallel port, can record
  55.         and playback 22khz mono digital audio. Included with the
  56.         Audio Port is a built-in FM synthesis chip, the Yamaha 3812.
  57.  
  58.             The Audio Port supports ADPCM hardware compression, and
  59.         decompression, in real-time, at rates up to 22khz. Speci-
  60.         fically, the device support 2-to-1 and 4-to-1 compression
  61.         ratios.
  62.  
  63.             The programming interface is based upon the standard
  64.         parallel port I/O scheme, with a few bits redefined. The
  65.         parallel port on the IBM PC uses 3 I/O addresses; one output
  66.         data, one input status, and one output control. On certain
  67.         IBM AT compatible machines, the data port has been made into
  68.         a bi-directional data path for use with network adapters,
  69.         and other peripherals. The Audio Port supports this
  70.         bi-directional 8 bit data path.
  71.  
  72.             The Audio Port interfaces the FM and microcontroller
  73.         chip to the PC via the Audio Port Interface Controller; aka,
  74.         the APIC. The following diagram illustrates the data/control
  75.         path.
  76.  
  77.  
  78.  
  79.            ┌──────┐                                     ┌─┐/│
  80.            │      │      ┌────────────────────────┐     │ │ │
  81.            │      ├─┐    ┴┌───────┐    ┌─────┐    │ ┌───┤ │ │
  82.            │      │p├─────┤       ╞════╡ FM  ├──┐ │ │   │ │ │
  83.            │ IBM  │a├─────┤       │    └─────┘  │ │ │   └─┘\│
  84.            │      │r├─────┤Audio  │    ┌───────┐│ ┴ │
  85.            │ PC/  │a├─────┤Port   ╞════╡DAC/   ├┴───┘
  86.            │      │l├─────┤Interfc│    │ADC    ├────┐
  87.            │ AT   │l├─────┤Ctlr   │    └──┬────┘  ┬ │     ┌─┐
  88.            │      │e├─────┤       │    ┌──┴──┐    │ │┌────┤░│
  89.            │      │l├─────┤       ╞════╡Micro│    │ └┤    │░│
  90.            │      ├─┘    ┬└───────┘    └─────┘    │  └────┤░│
  91.            │      │      └────────────────────────┘       └─┘
  92.            └──────┘
  93.  
  94.  
  95.  
  96.             The APIC handles the actual clocking of data, and
  97.         determines the target device, either FM or the micro-
  98.         controller. In certain DAC/ADC modes, the APIC will drive
  99.         the DAC/ADC without intervention from the microcontroller
  100.         through the use of an internal 1k FIFO.
  101.  
  102.             Data sent to the different devices require some
  103.         handshaking to guarantee that commands and data do not
  104.         overrun. This control is a single bit that is multiplexed
  105.         between the FM and Micro.
  106.  
  107.  
  108.  
  109.  
  110.  
  111.                  ----====< PROGRAMMING CONSIDERATIONS >====----
  112.  
  113.  
  114.                   H A R D W A R E   I / O   A D D R E S S E S
  115.  
  116.  
  117.             On the IBM PC/AT, three parallel ports can be found at
  118.         several addresess. For each of the parallel port there are
  119.         three I/O ports for communications to the external parallel
  120.         devices. The following map defines the three I/O ports,
  121.         across the three ranges of addresses.
  122.  
  123.  
  124.                 NAME             LPT1  LPT2  MONO  DESCRIPTION
  125.                ┌───────────┬───┬─────┬─────┬─────┬──────────────────┐
  126.                │Data Output│R/W│ 378 │ 278 │ 3BC │ write output data│
  127.                ├───────────┼───┼─────┼─────┼─────┼──────────────────┤
  128.                │Status     │ R │ 379 │ 279 │ 3BD │ read status/data │
  129.                ├───────────┼───┼─────┼─────┼─────┼──────────────────┤
  130.                │Control    │ W │ 37A │ 27A │ 3BE │ control lines    │
  131.                └───────────┴───┴─────┴─────┴─────┴──────────────────┘
  132.  
  133.  
  134.             The following illustrations show the actual bit definitions
  135.         of the three parallel port I/O addresses:
  136.  
  137.  
  138.             Data Register Definitions:
  139.  
  140.                          D7   D6   D5   D4   D3   D2   D1   D0
  141.                ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
  142.                │Data   │bit7│bit6│bit5│bit4│bit3│bit2│bit1│bit0│
  143.                └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
  144.                          |    |    |    |    |    |    |    |
  145.                          +----+----+----+----+----+----+----+-- Data lines
  146.  
  147.  
  148.             Status Register Definitions:
  149.  
  150.                          D7   D6   D5   D4   D3   D2   D1   D0
  151.                ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
  152.                │Status │ W  │IRQ │PAR │SRQ │ DA │ X  │ X  │ X  │
  153.                └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
  154.                          |    |    |    |    |    |    |    |
  155.                          |    |    |    |    |    +----+----+-- unused
  156.                          |    |    |    |    +----------------- Data Available
  157.                          |    |    |    +----------------------  SRQ/D4/D0
  158.                          |    |    +---------------------------  PAR/D5/D1
  159.                          |    +--------------------------------  IRQ/D6/D2
  160.                          +------------------------------------- WAIT/D7/D3
  161.  
  162.                         D7 - Wait status bit. It presents the
  163.                              command/data register full for either
  164.                              the FM or Micro registers, depending
  165.                              on the control register state.
  166.  
  167.                         D6 - IRQ is pending bit. Same as the
  168.                              parallel port definition.
  169.  
  170.                         D5 - Input Data Enabled.
  171.  
  172.                         D4 - Service ReQuest. This bit is used
  173.                              by the digital audio FIFO to indicate
  174.                              if the FIFO can take more data.
  175.  
  176.                         D3 - Data is available from the Micro or
  177.                              FIFO. FM never sends data to the PC.
  178.  
  179.                         When the control register is in a read
  180.                         state, D4-D7 become input lines presenting
  181.                         each nibble of the 8 bit byte. During the
  182.                         control port read idle state, the low nibble
  183.                         is presented. During a read data state, the
  184.                         high nibble is presented.
  185.  
  186.  
  187.             Control Register Definitions:
  188.  
  189.                          D7   D6   D5   D4   D3   D2   D1   D0
  190.                ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
  191.                │Control│PAR │PAR │PAR │IRQ │ AS │MFM │ DS │ RW │
  192.                └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
  193.                          |    |    |    |    |    |    |    |
  194.                          |    |    |    |    |    |    |    +-- Read(0)/Write(1)
  195.                          |    |    |    |    |    |    +------- Data Strobe
  196.                          |    |    |    |    |    +------------ Micro/FM select
  197.                          |    |    |    |    +----------------- Address Strobe
  198.                          |    |    |    +---------------------- IRQ Enable
  199.                          +----+----+--------------------------- Parallel Input
  200.  
  201.                         D0-D3. These lines control the clocking to
  202.                                the API . It is best to view these
  203.                                four lines as control words with 16
  204.                                possible states. A list of the control
  205.                                states follows.
  206.  
  207.                         D4     When this bit is set to 1, interrupts
  208.                                are allowed to be pass to the 8259
  209.                                interrupt controller on the mother-
  210.                                board. Using interrupts from the
  211.                                parallel port is never advised. It is
  212.                                best to a faster system timer to
  213.                                perform interrupt duties.
  214.  
  215.                         D5-D7  With these bits high, some bi-
  216.                                directional parallel ports become
  217.                                active, that is, allow for 8 bit data
  218.                                to be read from the data port.
  219.  
  220.  
  221.             The DATA port is used for sending data/commands to the
  222.         Audio Port. In cases where the computer supports bi-
  223.         directional data transfers, data can be read from the Audio
  224.         Port via this register. IBM did not design the parallel port
  225.         to be bi-directional, so in most cases, this feature will
  226.         not be used.
  227.  
  228.  
  229.  
  230.         A U D I O   P O R T    I N T E R F A C E   C O N T R O L L E R
  231.  
  232.  
  233.             It is important to understand the concepts of talking to
  234.         the APIC. This device is the front-end to the separate
  235.         pieces of the Audio Port. The PC software is responsible for
  236.         creating the proper handshaking with the APIC. As implied by
  237.         it's name, there are specific hardware states for driving
  238.         either FM, or digital audio. The following is a list of all
  239.         the possible states for the Audio Port:
  240.  
  241.                    Value    State Name   Function
  242.  
  243.                     00h     RdFMIdle     Read FM Idle
  244.                     01h     WrFMIdle     Write FM Idle
  245.                     02h     invalid      invalid state
  246.                     03h     WrFMData     Write FM Data
  247.                     04h     RdIdle       Read Sound Idle
  248.                     05h     WrIdle       Write Sound Idle
  249.                     06h     RdSndData    Read Sound Data
  250.                     07h     WrSndData    Write Sound Data
  251.                     08h     RdFMStat     Get FM Status
  252.                     09h     WrFMAddr     Write FM Address
  253.                     0Ah     invalid      invalid state
  254.                     0Bh     invalid      And another Reset
  255.                     0Ch     RdSndStat    Read Sound Status
  256.                     0Dh     WrSndCmd     Write Sound Command
  257.                     0Eh     invalid      invalid state
  258.                     0Fh     WrReset2     Write Reset
  259.  
  260.             The four low order bits in the Control register
  261.         determine the state of the interface. Notice that some of
  262.         the states are invalid. Never assume that setting an invalid
  263.         state is harmless! An invalid state may present certain
  264.         clocking signals that may, for instance, load PCM data into
  265.         the FM index register. Other transitions from or to an
  266.         invalid state may have undetermined effects on the Audio
  267.         Port.
  268.  
  269.             The actual APIC logic requires the PC to program the
  270.         Audio Port in a concise manner. Transitions from idle to
  271.         active, then back to idle states, must be strictly adhered
  272.         to, or unpredictable results may occur. The basic programm-
  273.         ing convention is to leave the control port in Write Idle
  274.         mode when idle. This way, another state can be transistioned
  275.         in and out. Another benefit of leaving the control port in
  276.         Write Idle is that the status register is switched to status
  277.         mode, not read nibble mode; therefore, all status bits are
  278.         available for reading. For more info, see the above
  279.         description of the Status Port.
  280.  
  281.             The following are simple state flow diagrams. Reading
  282.         from left to right, these diagrams show the various legal
  283.         states for writing commands or data, or just reading data.
  284.         The I/O to the data port and status ports are not shown.
  285.  
  286.  
  287.                 TO RESET THE AUDIO PORT:
  288.  
  289.            WrIdle__>___ WrReset2  __>________________________ WrIdle
  290.  
  291.  
  292.                 TO WRITE COMMANDS/DATA TO THE MICRO:
  293.  
  294.                       _ WrSndCmd  __>_____________________
  295.            WrIdle__>_/                                    \__ WrIdle
  296.                      \_ WrSndData __>_____________________/
  297.  
  298.  
  299.                 TO READ MICRO DATA:
  300.  
  301.            WrIdle__>_ RdIdle__>_ RdSndData__>_ RdIdle__>_____ WrIdle
  302.  
  303.  
  304.                 TO WRITE INDEX/DATA TO THE FM CHIP:
  305.  
  306.                                  _ WrFMAddr _
  307.            WrIdle__>_ WrFMIdle__/            \__ WrFMIdle__>_ WrIdle
  308.                                 \_ WrFMData _/
  309.  
  310.  
  311.                 TO READ FM STATUS:
  312.  
  313.            WrIdle__>_ RdFMIdle__>_ RdFMStat__>_ RdFMIdle__>__ WrIdle
  314.  
  315.  
  316.  
  317.         A typical sequence to send a PCM data byte would be:
  318.  
  319.                 mov     dx,[PortAddress]  ; get the base address.
  320.  
  321.                 add     dl,_CONTROL       ; move to the control port.
  322.                 mov     al,WrIdle         ; set to Write Idle mode.
  323.                 out     dx,al
  324.                 Idledly
  325.  
  326.                 sub     dl,_CONTROL       ; move to the data port.
  327.                 mov     al,[DataByte]     ; port, then send the
  328.                 out     dx,al             ; data byte.
  329.  
  330.                 add     dl,_CONTROL       ; move to the control port.
  331.                 mov     al,WrSndData      ; strobe the data out.
  332.                 out     dx,al
  333.  
  334.                 mov     al,WrIdle         ; complete the strobe by
  335.                 out     dx,al             ; returning to write idle.
  336.                 Idledly
  337.  
  338.  
  339.             Two things to note from the above example; to strobe
  340.         data out to the Audio Port, the Audio port must make state
  341.         transitions from Idle, to an active send, then back to idle.
  342.             The second thing to note, is the required I/O delay when
  343.         returning to idle mode. By IBM's design, the parallel port
  344.         hardware signal timings make transitions to active states
  345.         very quickly. When transitioning into idle modes, the
  346.         signals take almost twice as long. The above example shows
  347.         the use of a simple text macro called "Idledly". This macro
  348.         It could be defined as:
  349.  
  350.                 Idledly   equ   <out dx,al>
  351.  
  352.         All it does, is perform an addition I/O write instruction,
  353.         which on the IBM ISA bus, is guaranteed to take a minimum of
  354.         850ns of time.
  355.  
  356.             The other equates used in the above code segment have
  357.         the following values:
  358.  
  359.                 _DATA     equ   0
  360.                 _STATUS   equ   1
  361.                 _CONTROL  equ   2
  362.  
  363.  
  364.  
  365.  
  366.                   C O M M A N D / D A T A   H A N D S H A K I N G
  367.  
  368.  
  369.             When the PC clocks data to the Micro or FM, the APIC
  370.         latches the data, watches the signals, then sends the data
  371.         to the appropriate device. In order to help the PC know when
  372.         to send the index, commands, or data, a status bit in the
  373.         Status register is presented for the PC to poll. This status
  374.         bit, bit D7, is used for both the FM and Micro WAIT
  375.         status's. The Control register state, WrIdle or WrFMIdle,
  376.         determine which WAIT state is being presented for either
  377.         the FM or Micro.
  378.  
  379.             For sending index/data to the 3812 FM chip, Yamaha has
  380.         defined certain timing delays between the writes. Index
  381.         writes take a minimum of 5 micro seconds to complete. Data
  382.         writes take a minimum of 35 micro seconds to complete. The
  383.         APIC starts clocking the index/data out to the FM chip once
  384.         the PC finishes clocking out the data byte to the APIC.
  385.         During the time the APIC is clocking the index/data out to
  386.         the 3812, the WAIT bit will be held high. The APIC holds the
  387.         wait line high for the entire duration of both index and
  388.         data write times. This means the PC has to poll the wait
  389.         line before writing the index, but can write both the index,
  390.         then data byte with no intervening waits.
  391.  
  392.             For Micro reads and writes, the WAIT line is derived
  393.         from the micro. The APIC just passes this signal through
  394.         unaltered. During Write idle, the WAIT line indicates
  395.         whether the Micro can receive more commands or data. The
  396.         signal goes high (1) when WAIT is asserted.
  397.  
  398.             For queued DAC output, the WAIT line goes active (1)
  399.         when the queue cannot receive more data. For ADC input, the
  400.         WAIT line goes active (1) when the queue is emptied.
  401.  
  402.  
  403.  
  404.  
  405.                            DIGITAL AUDIO PROGRAMMING
  406.  
  407.             The Digial Audio section is controlled by both the APIC
  408.         and Microcontroller. All commands issued are processed by
  409.         the microcontroller. The APIC provides the clocking control,
  410.         and FIFO management. To issue commands to the micro, the
  411.         status port must be polled to check the WAIT bit. The Micro
  412.         WAIT is presented during WrIdle mode. When the bit is low
  413.         (0), commands or data may be written.
  414.  
  415.  
  416.      Micro Command Set:
  417.  
  418.      ┌────────────────┬──────────┬─────────┬─────────┬─────────┬─────────┐
  419.      │    Command     │D7-D4 Code│   D3    │   D2    │   D1    │   D0    │
  420.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  421.      │   reserved     │    0     │    .    │    .    │    .    │    .    │
  422.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  423.      │System Control  │    1     │    X    │    X    │    X    │    X    │
  424.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  425.      │8 Bit PCM Direct│    2     │Play/Rcd │AGC Kill │  Timer  │    0    │
  426.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  427.      │   reserved     │    3     │    .    │    .    │    .    │    .    │
  428.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  429.      │Play PCM  Queue │    4     │Compress │ 4/2 Bit │  Timer  │   Ref   │
  430.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  431.      │Rcd 8 Bit Queue │    5     │   VOX   │AGC Kill │  Timer  │    0    │
  432.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  433.      │Rcd 4 Bit Queue │    6     │   VOX   │AGC Kill │  Timer  │    1    │
  434.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  435.      │Rcd 2 Bit Queue │    7     │   VOX   │AGC Kill │  Timer  │    1    │
  436.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  437.      │   reserved     │    8     │    .    │    .    │    .    │    .    │
  438.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  439.      │   reserved     │    9     │    .    │    .    │    .    │    .    │
  440.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  441.      │   reserved     │    A     │    .    │    .    │    .    │    .    │
  442.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  443.      │   reserved     │    B     │    .    │    .    │    .    │    .    │
  444.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  445.      │   reserved     │    C     │    .    │    .    │    .    │    .    │
  446.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  447.      │   reserved     │    D     │    .    │    .    │    .    │    .    │
  448.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  449.      │   reserved     │    E     │    .    │    .    │    .    │    .    │
  450.      ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
  451.      │   reserved     │    F     │    .    │    .    │    .    │    .    │
  452.      └────────────────┴──────────┴─────────┴─────────┴─────────┴─────────┘
  453.  
  454.      System Control Commands - 0001xxxx
  455.  
  456.  
  457.              10h SYSCMDIDLE    - Terminate DAC/ADC modes, return to Idle.
  458.                                  This is guaranteed to return the Audio
  459.                                  Port Micro to an Idle state
  460.  
  461.                      Parameters: No Parameters
  462.                      Returns:    No Data Returned
  463.  
  464.              11h SYSCMDGETID   - Get ESP version
  465.  
  466.                      Parameters: No parameters
  467.                      Returns:    Returns 2 bytes
  468.  
  469.              13h SYSCMDENAPARR - Enable Parallel Input
  470.  
  471.                      Parameters: No Parameters
  472.                      Returns:    No Data Returned
  473.  
  474.              14h SYSCMDDISPARR - Disable Parallel Input
  475.  
  476.                      Parameters: No Parameters
  477.                      Returns:    No Data Returned
  478.  
  479.              15h SYSCMDTSTPARR - Test Parallel Input
  480.  
  481.                      Parameters: One data byte following (any value)
  482.  
  483.                      Returns:    Returns the same data byte
  484.                                    in parallel mode.
  485.  
  486.  
  487.      Direct DAC/ADC Control Commands - 0010xxxx
  488.  
  489.                 NOTE: The AGC kill bit disables the internal Auto Gain
  490.                 Control. This bit is normally set to 0, thus allowing
  491.                 the AGC to function. Setting this bit to a 1 turns
  492.                 off the AGC for the duration of the recording.
  493.  
  494.              20h SYSDIRPLAY    - 8 bit direct play.
  495.  
  496.                                  This places the Audio Port Micro into DAC
  497.                                  output mode. The queue is not enabled.
  498.  
  499.                      Parameters: Sound Data follows.
  500.                      Returns:    No Data Returned
  501.  
  502.              22h SYSDIRNA2     - 8 bit direct play w/time constant following.
  503.  
  504.                                  This places the Audio Port Micro into
  505.                                  DAC output mode. The queue is not enabled.
  506.  
  507.                      Parameters: One byte parameter follows. This is the
  508.                                  sample rate speed. The following function
  509.                                  calculates the sample rate:
  510.  
  511.                                    TimeConst = 256-(1000000/SampleRate)
  512.  
  513.                                  Sound Data follows.
  514.                      Returns:    No Data Returned
  515.  
  516.              28h SYSDIRRECD    - 8 bit direct record.
  517.  
  518.                                  Sampled data will be made available until
  519.                                  command 10H is issued.
  520.  
  521.                      Parameters: No Parameters
  522.  
  523.                      Returns:    Sampled data will be made available until
  524.                                  command 10H is issued.
  525.  
  526.              2Ah SYSDIRNAA     - 8 bit direct record w/time constant following.
  527.  
  528.                      Parameters: One byte parameter follows. This is the
  529.                                  sample rate speed. The following function
  530.                                  calculates the sample rate:
  531.  
  532.                                    TimeConst = 256-(1000000/SampleRate)
  533.  
  534.                      Returns:    Sampled data will be made available until
  535.                                  command 10H is issued.
  536.  
  537.  
  538.          FIFO DAC/ADC Commands - 0100xxxx
  539.  
  540.  
  541.  
  542.              40h SYSDIRQPLAY   - 8 bit FIFO DAC out.
  543.  
  544.                                  This function enables the 1k FIFO output
  545.                                  to the DAC. Watch the SRQ line to send out
  546.                                  256 byte blocks.
  547.  
  548.                      Parameters: Sound Data follows.
  549.  
  550.                      Returns:    No Data Returned
  551.  
  552.              42h SYSDIRQNA2    - 8 bit FIFO DAC out w/time constant following.
  553.  
  554.                                  This function enables the 1k FIFO output
  555.                                  to the DAC. Watch the SRQ line to send out
  556.                                  256 byte blocks.
  557.  
  558.                                  One byte parameter follows. This is the
  559.                                  sample rate speed. The following function
  560.                                  calculates the sample rate:
  561.  
  562.                                    TimeConst = 256-(1000000/SampleRate)
  563.  
  564.                      Parameters: Sound Data follows.
  565.  
  566.                      Returns:    No Data Returned
  567.  
  568.              48h SYSDIRQRECD   - 4 bit FIFO DAC out decompression
  569.  
  570.                                  This function enables the 1k FIFO output
  571.                                  to the DAC. Watch the SRQ line to send out
  572.                                  256 byte blocks.
  573.  
  574.                      Parameters: Sound Data follows.
  575.  
  576.                      Returns:    No Data Returned
  577.  
  578.              49h SYSDIRQRECD   - 4 bit FIFO DAC out decompression with
  579.                                  reference byte.
  580.  
  581.                                  This function enables the 1k FIFO output
  582.                                  to the DAC. Watch the SRQ line to send out
  583.                                  256 byte blocks.
  584.  
  585.                      Parameters: One 8 bit sample follows. This is the seed
  586.                                  value for decompression.
  587.  
  588.                                  Sound Data follows.
  589.  
  590.                      Returns:    No Data Returned
  591.  
  592.              4Ah SYSDIRQRECD   - 4 bit FIFO DAC out decompression with
  593.                                  time constant following.
  594.  
  595.                                  This function enables the 1k FIFO output
  596.                                  to the DAC. Watch the SRQ line to send out
  597.                                  256 byte blocks.
  598.  
  599.                      Parameters: One byte parameter follows. This is the
  600.                                  sample rate speed. The following function
  601.                                  calculates the sample rate:
  602.  
  603.                                    TimeConst = 256-(1000000/SampleRate)
  604.  
  605.                                  Sound Data follows.
  606.  
  607.                      Returns:    No Data Returned
  608.  
  609.              4Bh SYSDIRQRECD   - 4 bit FIFO DAC out decompression with
  610.                                  time constant following.
  611.  
  612.                                  This function enables the 1k FIFO output
  613.                                  to the DAC. Watch the SRQ line to send out
  614.                                  256 byte blocks.
  615.  
  616.                      Parameters: Two parameter bytes follows. The first is the
  617.                                  sample rate speed. The following function
  618.                                  calculates the sample rate:
  619.  
  620.                                    TimeConst = 256-(1000000/SampleRate)
  621.  
  622.                                  The second byte is the seed value for
  623.                                  decompression.
  624.  
  625.                                  Sound Data follows.
  626.  
  627.                      Returns:    No Data Returned
  628.  
  629.              4Ch SYSDIRQRECD   - 2 bit FIFO DAC out decompression.
  630.  
  631.                                  This function enables the 1k FIFO output
  632.                                  to the DAC. Watch the SRQ line to send out
  633.                                  256 byte blocks.
  634.  
  635.                      Parameters: Sound Data follows.
  636.  
  637.                      Returns:    No Data Returned
  638.  
  639.              4Dh SYSDIRQRECD   - 2 bit FIFO DAC out decompression with
  640.                                  reference byte.
  641.  
  642.                                  This function enables the 1k FIFO output
  643.                                  to the DAC. Watch the SRQ line to send out
  644.                                  256 byte blocks.
  645.  
  646.                      Parameters: One 8 bit sample follows. This is the seed
  647.                                  value for decompression.
  648.  
  649.                                  Sound Data follows.
  650.  
  651.                      Returns:    No Data Returned
  652.  
  653.              4Eh SYSDIRQRECD   - 2 bit FIFO DAC out decompression with
  654.                                  time constant following.
  655.  
  656.                                  This function enables the 1k FIFO output
  657.                                  to the DAC. Watch the SRQ line to send out
  658.                                  256 byte blocks.
  659.  
  660.                      Parameters: One byte parameter follows. This is the
  661.                                  sample rate speed. The following function
  662.                                  calculates the sample rate:
  663.  
  664.                                    TimeConst = 256-(1000000/SampleRate)
  665.  
  666.                                  Sound Data follows.
  667.  
  668.                      Returns:    No Data Returned
  669.  
  670.              4Fh SYSDIRQRECD   - 2 bit FIFO DAC out w/time constant following.
  671.  
  672.                                  This function enables the 1k FIFO output
  673.                                  to the DAC. Watch the SRQ line to send out
  674.                                  256 byte blocks.
  675.  
  676.                      Parameters: Two parameter bytes follows. The first is the
  677.                                  sample rate speed. The following function
  678.                                  calculates the sample rate:
  679.  
  680.                                    TimeConst = 256-(1000000/SampleRate)
  681.  
  682.                                  The second byte is the seed value for
  683.                                  decompression.
  684.  
  685.                                  Sound Data follows.
  686.  
  687.                      Returns:    No Data Returned
  688.  
  689.          FIFO 8 Bit Recording Commands - 0101xxxx
  690.  
  691.                 NOTE: The AGC kill bit disables the internal Auto Gain
  692.                 Control. This bit is normally set to 0, thus allowing
  693.                 the AGC to function. Setting this bit to a 1 turns
  694.                 off the AGC for the duration of the recording.
  695.                     The VOX bit allows voice activated recording. When
  696.                 this bit is set (1), the Audio Port will only begin
  697.                 recording when the mic signal reaches certain volumes.
  698.                 When in VOX mode, the Audio Port will stop recording
  699.                 1 to 2 seconds after the mic signal becomes quiet.
  700.  
  701.  
  702.              50h SYSDIRPLAY    - 8 bit FIFO record.
  703.                                  Sampled data will be made available until
  704.                                  command 10H is issued.
  705.  
  706.                      Parameters: No Parameters
  707.  
  708.                      Returns:    Sampled data will be made available until
  709.                                  command 10H is issued.
  710.  
  711.              52h SYSDIRNA2     - 8 bit FIFO w/time constant following.
  712.  
  713.                      Parameters: One byte parameter follows. This is the
  714.                                  sample rate speed. The following function
  715.                                  calculates the sample rate:
  716.  
  717.                                    TimeConst = 256-(1000000/SampleRate)
  718.  
  719.                      Returns:    Sampled data will be made available until
  720.                                  command 10H is issued.
  721.  
  722.  
  723.          FIFO 4 Bit Recording Commands - 0110xxxx
  724.  
  725.                 NOTE: The AGC kill bit disables the internal Auto Gain
  726.                 Control. This bit is normally set to 0, thus allowing
  727.                 the AGC to function. Setting this bit to a 1 turns
  728.                 off the AGC for the duration of the recording.
  729.                     The VOX bit allows voice activated recording. When
  730.                 this bit is set (1), the Audio Port will only begin
  731.                 recording when the mic signal reaches certain volumes.
  732.                 When in VOX mode, the Audio Port will stop recording
  733.                 1 to 2 seconds after the mic signal becomes quiet.
  734.  
  735.              60h SYSDIRPLAY    - 4 bit FIFO record compression.
  736.  
  737.                                  Sampled data will be made available until
  738.                                  command 10H is issued.
  739.  
  740.                      Parameters: No Parameters
  741.  
  742.                      Returns:    Sampled data will be made available until
  743.                                  command 10H is issued.
  744.  
  745.              63h SYSDIRNA2     - 4 bit FIFO w/time constant byte parameter.
  746.  
  747.                      Parameters: One byte parameter follows. This is the
  748.                                  sample rate speed. The following function
  749.                                  calculates the sample rate:
  750.  
  751.                                    TimeConst = 256-(1000000/SampleRate)
  752.  
  753.                      Returns:    Sampled data will be made available until
  754.                                  command 10H is issued. The first sample
  755.                                  returned is the full 8 bit sample used
  756.                                  as the reference byte.
  757.  
  758.  
  759.          FIFO 2 Bit Recording Commands - 0110xxxx
  760.  
  761.                 NOTE: The AGC kill bit disables the internal Auto Gain
  762.                 Control. This bit is normally set to 0, thus allowing
  763.                 the AGC to function. Setting this bit to a 1 turns
  764.                 off the AGC for the duration of the recording.
  765.                     The VOX bit allows voice activated recording. When
  766.                 this bit is set (1), the Audio Port will only begin
  767.                 recording when the mic signal reaches certain volumes.
  768.                 When in VOX mode, the Audio Port will stop recording
  769.                 1 to 2 seconds after the mic signal becomes quiet.
  770.  
  771.              70h SYSDIRPLAY    - 2 bit FIFO record.
  772.  
  773.                                  Sampled data will be made available until
  774.                                  command 10H is issued.
  775.  
  776.                      Parameters: No Parameters
  777.  
  778.                      Returns:    Sampled data will be made available until
  779.                                  command 10H is issued.
  780.  
  781.              73h SYSDIRNA2     - 2 bit FIFO w/time constant following.
  782.  
  783.                      Parameters: One byte parameter follows. This is the
  784.                                  sample rate speed. The following function
  785.                                  calculates the sample rate:
  786.  
  787.                                    TimeConst = 256-(1000000/SampleRate)
  788.  
  789.                      Returns:    Sampled data will be made available until
  790.                                  command 10H is issued. The first sample
  791.                                  returned is the full 8 bit sample used
  792.                                  as the reference byte.
  793.  
  794.  
  795.                            FM PROGRAMMING.
  796.  
  797.             For sending index/data to the 3812 FM chip, Yamaha has
  798.         defined certain timing delays between the writes. Index
  799.         writes take a minimum of 5 micro seconds to complete. Data
  800.         writes take a minimum of 35 micro seconds to complete. The
  801.         APIC starts clocking the index/data out to the FM chip once
  802.         the PC finishes clocking out the data byte to the APIC.
  803.         During the time the APIC is clocking the index/data out to
  804.         the 3812, the WAIT bit will be held high. The APIC holds the
  805.         wait line high for the entire duration of both index and
  806.         data write times plus delay times. This means the PC has to
  807.         poll the wait line before writing the index, but can write
  808.         both the index, then data byte with no intervening waits.
  809.  
  810.  
  811.                            INTERRUPT PROCESSING.
  812.  
  813.             The recommended approach for interrupt processing is to use
  814.         a fast system timer interrrupt. The system timer should be re-
  815.         programmed to generate an interrupt every 30 milliseconds to
  816.         check the SRQ line. If the SRQ is high, another 256 byte block
  817.         of PCM data can be read or written. At interrupt time, upon
  818.         completing the first 256 byte block, check SRQ again, and
  819.         repeat the process until the SRQ goes low. Once all blocks are
  820.         finished, the system timer can be reprogrammed to interrupt at
  821.         it's normal frequency of 18.2 times per second.
  822.  
  823.             On DAC output, The SRQ line goes high when the 1k buffer
  824.         has 256 bytes, or less remaining. It goes low when it has
  825.         768 bytes or more stored.
  826.  
  827.             On ADC input, the SRQ line goes high if the FIFO has
  828.         768 or more bytes. It goes low when it has 256 or fewer
  829.         bytes stored.
  830.  
  831.  
  832.  
  833.                         APPENDIX A - HARDWARE PORTS & STATES
  834.  
  835.  
  836.         NAME             LPT1  LPT2  MONO  DESCRIPTION
  837.                ┌───────────┬───┬─────┬─────┬─────┬─────────────────┐
  838.                │Data Output│ R │ 378 │ 278 │ 3BC │write to TP      │
  839.                ├───────────┼───┼─────┼─────┼─────┼─────────────────┤
  840.                │Status     │ R │ 379 │ 279 │ 3BD │read status/data │
  841.                ├───────────┼───┼─────┼─────┼─────┼─────────────────┤
  842.                │Control    │ W │ 37A │ 27A │ 3BE │set I/O control  │
  843.                └───────────┴───┴─────┴─────┴─────┴─────────────────┘
  844.  
  845.  
  846.             Base Address + 0 offset -  Data Register Definitions:
  847.  
  848.                       D7   D6   D5   D4   D3   D2   D1   D0
  849.             ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
  850.             │Data   │bit7│bit6│bit5│bit4│bit3│bit2│bit1│bit0│
  851.             └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
  852.                       |    |    |    |    |    |    |    |
  853.                       +----+----+----+----+----+----+----+-- Data lines
  854.  
  855.  
  856.             Base Address + 1 offset -  Status Register Definitions
  857.  
  858.                         D7   D6   D5   D4   D3   D2   D1   D0
  859.             ┌─────────┬────┬────┬────┬────┬────┬────┬────┬────┐
  860.             │Status   │ W  │IRQ │PAR │SRQ │ DA │ X  │ X  │ X  │
  861.             └─────────┴────┴────┴────┴────┴────┴────┴────┴────┘
  862.                         |    |    |    |    |    |    |    |
  863.                         |    |    |    |    |    +----+----+- unused
  864.                         |    |    |    |    +---------------- Data Available
  865.                         |    |    |    +---------------------  SRQ/D4/D0
  866.                         |    |    +--------------------------  PAR/D5/D1
  867.                         |    +-------------------------------  IRQ/D6/D2
  868.                         +------------------------------------ WAIT/D7/D3
  869.  
  870.  
  871.             Base Address + 2 offset -  Control Register Definitions
  872.  
  873.                            D7   D6   D5   D4   D3   D2   D1   D0
  874.             ┌─────────┬────┬────┬────┬────┬────┬────┬────┬────┐
  875.             │Control  │PAR │PAR │PAR │IRQ │ AS │MFM │ DS │ RW │
  876.             └─────────┴────┴────┴────┴────┴────┴────┴────┴────┘
  877.                         |    |    |    |    |    |    |    |
  878.                         |    |    |    |    |    |    |    +- Read(0)/Write(1)
  879.                         |    |    |    |    |    |    +------ Data Strobe
  880.                         |    |    |    |    |    +----------- Micro/FM select
  881.                         |    |    |    |    +---------------- Address Strobe
  882.                         |    |    |    +--------------------- IRQ Enable
  883.                         +----+----+-------------------------- Par. input select
  884.  
  885.  
  886.             Control Register Clock State:
  887.  
  888.                 00h     RdFMIdle     Read FM Idle
  889.                 01h     WrFMIdle     Write FM Idle
  890.                 02h     invalid      invalid state
  891.                 03h     WrFMData     Write FM Data
  892.                 04h     RdIdle       Read Sound Idle
  893.                 05h     WrIdle       Write Sound Idle
  894.                 06h     RdSndData    Read Sound Data
  895.                 07h     WrSndData    Write Sound Data
  896.                 08h     RdFMStat     Get FM Status
  897.                 09h     WrFMAddr     Write FM Address
  898.                 0Ah     invalid      invalid state
  899.                 0Bh     invalid      And another Reset
  900.                 0Ch     RdSndStat    Read Sound Status
  901.                 0Dh     WrSndCmd     Write Sound Command
  902.                 0Eh     invalid      invalid state
  903.                 0Fh     WrReset2     Write Reset
  904.  
  905.             Control Register Additional bit definitions
  906.  
  907.                 10h     Interrupt    Enable interrupt
  908.                 E0h     EnableInput  Enable Parallel Input
  909.  
  910.  
  911.  
  912.                          APPENDIX B - EXAMPLE ROUTINES
  913.  
  914.          The following code assumes the parallel port base I/O
  915.          address for the Audio Port is stored in the variable,
  916.          "PortAddress".
  917.  
  918.         The following macros and equates are used in the code
  919.         examples:
  920.  
  921.             Idledly   equ   <out dx,al>
  922.  
  923.             _DATA     equ   0      ; Parallel port data port offset
  924.             _STATUS   equ   1      ; Parallel port status port offset
  925.             _CONTROL  equ   2      ; Parallel port control port offset
  926.  
  927.             RdFMIdle  equ   00h    ; Read FM Idle
  928.             WrFMIdle  equ   01h    ; Write FM Idle
  929.             invalid   equ   02h    ; invalid state
  930.             WrFMData  equ   03h    ; Write FM Data
  931.             RdIdle    equ   04h    ; Read Sound Idle
  932.             WrIdle    equ   05h    ; Write Sound Idle
  933.             RdSndData equ   06h    ; Read Sound Data
  934.             WrSndData equ   07h    ; Write Sound Data
  935.             RdFMStat  equ   08h    ; Get FM Status
  936.             WrFMAddr  equ   09h    ; Write FM Address
  937.             invalid   equ   0Ah    ; invalid state
  938.             invalid   equ   0Bh    ; And another Reset
  939.             RdSndStat equ   0Ch    ; Read Sound Status
  940.             WrSndCmd  equ   0Dh    ; Write Sound Command
  941.             invalid   equ   0Eh    ; invalid state
  942.             WrReset2  equ   0Fh    ; Write Reset
  943.  
  944.  
  945.  
  946.  
  947.         ;
  948.         ;   /*\
  949.         ;---|*|----====< AP_ADC_input >====----
  950.         ;---|*|
  951.         ;---|*| Input 256 bytes from the AP FIFO. This routine
  952.         ;---|*| assumes that the AP is already in ADC input mode.
  953.         ;---|*|
  954.         ;---|*| Entry Conditions:
  955.         ;---|*|   ES:DI point to the buffer.
  956.         ;---|*|   CX holds a count of 1 to 256
  957.         ;---|*|
  958.         ;---|*| Exit Conditions:
  959.         ;---|*|   ES:DI is updated. CX is zero
  960.         ;---|*|   AX,BX,CX,DX,ES:DI modified
  961.         ;---|*|
  962.         ;   \*/
  963.         ;
  964.                 public  AP_ADC_input
  965.         AP_ADC_input    proc    near
  966.         ;
  967.         ; load the FIFO quarter size for use with the SRQ handshaking.
  968.         ;
  969.                 mov     dx,[PortAddress]        ; get the port address
  970.                 add     dl,_CONTROL
  971.                 cld                             ; STOSBs are used
  972.             ;
  973.             apadc05:
  974.  
  975.                 mov     al,RdIdle               ; go into Read Idle to pick up the nibble
  976.                 out     dx,al                   ; Idle w/o interrupts
  977.                 Idledly
  978.  
  979.                 dec     dx                      ; move to STATUS
  980.                 in      al,dx
  981.                 mov     ah,al                   ; save the high nibble
  982.                 inc     dx
  983.  
  984.                 mov     al,RdSndData            ; ah = RdIdle, al = RdSndData
  985.                 out     dx,al                   ; this delivers the second nibble
  986.                 Idledly
  987.  
  988.                 dec     dx
  989.                 in      al,dx                   ; fetch it
  990.  
  991.                 shr     ah,4                    ; merge the nibbles
  992.                 shr     ax,4
  993.  
  994.                 stosb                           ; save the byte
  995.                 or      di,di                   ; segment wrap?
  996.                 jz      apadcsegwrap            ; yes, go adjust...
  997.             ;
  998.             apadc10:
  999.                 inc     dx                      ; place the board into idle mode again
  1000.                 loop    apadc05                 ; do all 256 or less bytes
  1001.  
  1002.                 mov     al,WrIdle               ; return back to write idle
  1003.                 out     dx,al
  1004.                 Idledly
  1005.  
  1006.                 ret                             ; all done recording this block!
  1007.         ;
  1008.         apadcsegwrap:
  1009.                 mov     di,es                   ; wrap the segment for huge model
  1010.                 add     di,1000h                ; support.
  1011.                 mov     es,di
  1012.                 sub     di,di
  1013.                 jmp     short  apadc10
  1014.  
  1015.         AP_ADC_input    endp
  1016.  
  1017.  
  1018.  
  1019.         ;
  1020.         ;   /*\
  1021.         ;---|*|----====< AP_DAC_output >====----
  1022.         ;---|*|
  1023.         ;---|*| Output 256 bytes to the AP FIFO. This routine
  1024.         ;---|*| assumes that the AP is already in DAC output mode.
  1025.         ;---|*|
  1026.         ;---|*| Entry Conditions:
  1027.         ;---|*|   ES:DI point to the buffer.
  1028.         ;---|*|   CX holds a count of 1 to 256
  1029.         ;---|*|
  1030.         ;---|*| Exit Conditions:
  1031.         ;---|*|   ES:DI is updated. CX is zero
  1032.         ;---|*|   AX,CX,DX,ES:DI modified
  1033.         ;---|*|
  1034.         ;   \*/
  1035.         ;
  1036.                 public  AP_DAC_output
  1037.         AP_DAC_output   proc    near
  1038.         ;
  1039.         ; make sure the port is in write idle mode...
  1040.         ;
  1041.                 mov     dx,[PortAddress]        ; get the port address
  1042.                 add     dl,_CONTROL
  1043.                 mov     al,WrIdle               ; make sure its idle
  1044.                 out     dx,al
  1045.                 sub     dl,_CONTROL             ; move back to the data port
  1046.         ;
  1047.         apdac05:
  1048.         ;
  1049.         ; send 256 bytes of data out to the FIFO
  1050.         ;
  1051.                 mov     al,es:[di]              ; fetch the byte
  1052.                 inc     di
  1053.                 jz      apdacsegwrap            ; odd case jumps out...
  1054.             ;
  1055.             apdac10:
  1056.  
  1057.                 out     dx,al                   ; write it to the audio port
  1058.  
  1059.                 add     dl,_CONTROL
  1060.  
  1061.                 mov     al,WrSndData            ; start the strobe...
  1062.                 out     dx,al
  1063.  
  1064.                 mov     al,WrIdle               ; end the strobe....
  1065.                 out     dx,al
  1066.                 Idledly
  1067.  
  1068.                 sub     dl,_CONTROL
  1069.                 loop    apdac05                 ; do all 256 or less bytes
  1070.  
  1071.                 ret
  1072.         ;
  1073.         apdacsegwrap:
  1074.                 mov     di,es                   ; move to the next segment
  1075.                 add     di,1000h
  1076.                 mov     es,di
  1077.                 sub     di,di
  1078.                 jmp     short apdac10           ; then get back into the playback
  1079.  
  1080.         AP_DAC_output   endp
  1081.  
  1082.  
  1083.  
  1084.  
  1085.         /*\
  1086.         |*|----====< AP_Reset >====----
  1087.         |*|
  1088.         |*| Reset the Audio Port
  1089.         |*|
  1090.         |*| Entry Conditions:
  1091.         |*|   None.
  1092.         |*|
  1093.         |*| Exit Conditions:
  1094.         |*|   AL holds the reset byte - 05A if successful
  1095.         |*|   AX,BX,CX,DX modified
  1096.         |*|
  1097.         \*/
  1098.                 public  AP_Reset
  1099.         AP_Reset proc
  1100.  
  1101.                 mov     dx,[PortAddress]
  1102.                 mov     al,-1           ; load FF into the data port to drive the
  1103.                 out     dx,al           ; data lines.
  1104.  
  1105.                 add     dl,_CONTROL
  1106.                 mov     cx,16
  1107.                 mov     al,WrReset2     ; output reset mode
  1108.         ;
  1109.         @@:
  1110.                 out     dx,al
  1111.                 loop    @B
  1112.  
  1113.                 mov     cx,16
  1114.         ;
  1115.         @@:
  1116.                 mov     al,WrIdle       ; clear reset
  1117.                 out     dx,al
  1118.                 loop    @B
  1119.  
  1120.                 mov     al,RdIdle       ; get sound data read status
  1121.                 out     dx,al
  1122.                 Idledly
  1123.  
  1124.                 dec     dx              ; move back to the status port
  1125.                 sub     cx,cx
  1126.         ;
  1127.         aprst05:
  1128.                 in      al,dx
  1129.                 test    al,stIDav       ; wait for data to become available
  1130.                 loopz   aprst05
  1131.                 jz      aprstbad
  1132.  
  1133.                 mov     ah,al           ; save the result (should not be 0xFF)
  1134.  
  1135.                 inc     dx              ; move to the control port
  1136.                 mov     al,RdSndData    ; Clock in the data
  1137.                 out     dx,al
  1138.  
  1139.                 dec     dx
  1140.                 in      al,dx
  1141.                 mov     bx,ax
  1142.  
  1143.                 inc     dx
  1144.                 mov     al,RdIdle       ; go back to idle
  1145.                 out     dx,al
  1146.                 Idledly
  1147.  
  1148.                 mov     al,WrIdle       ; go back to idle
  1149.                 out     dx,al
  1150.                 Idledly
  1151.  
  1152.                 mov     cl,4            ; build the reset byte.
  1153.                 shr     bh,cl
  1154.                 shr     bx,cl
  1155.  
  1156.                 mov     al,bl
  1157.                 ret
  1158.             ;
  1159.             aprstbad:
  1160.                 mov     al,-1
  1161.                 ret
  1162.  
  1163.         AP_reset endp
  1164.  
  1165.  
  1166.  
  1167.         /*\
  1168.         |*|----====< AP_MDR_stat >====----
  1169.         |*|
  1170.         |*| Returns the status of data available
  1171.         |*|
  1172.         |*| Entry Conditions:
  1173.         |*|   None.
  1174.         |*|
  1175.         |*| Exit Conditions:
  1176.         |*|   Carry clear & AX = 0,  no data available
  1177.         |*|   Carry set   & AX = -1, data available
  1178.         |*|   DX,AX modified
  1179.         |*|
  1180.         \*/
  1181.  
  1182.                 public  AP_MDR_stat
  1183.         AP_MDR_stat     proc
  1184.                 mov     dx,[PortAddress]
  1185.                 add     dl,_CONTROL
  1186.  
  1187.                 mov     al,RdIdle       ; Micro read idle
  1188.                 out     dx,al
  1189.                 Idledly
  1190.  
  1191.                 dec     dx              ; mov to the status port
  1192.  
  1193.                 in      al,dx           ; data rdy is high for data available
  1194.                 mov     ah,stIDav
  1195.                 and     ah,al           ; save the status bit
  1196.  
  1197.                 mov     al,WrIdle       ; send the port back to
  1198.                 out     dx,al           ; idle mode
  1199.                 Idledly
  1200.  
  1201.                 neg     ah              ; set carry if non-zero
  1202.                 sbb     ax,ax           ; if data is available, return -1 & Cy
  1203.                 ret                     ; else return 0 & NC
  1204.  
  1205.         AP_MDR_stat     endp
  1206.  
  1207.  
  1208.  
  1209.         /*\
  1210.         |*|----====< AP_MDR_wait >====----
  1211.         |*|
  1212.         |*| Wait for Micro Data Read to be ready.
  1213.         |*|
  1214.         |*| Entry Conditions:
  1215.         |*|   None.
  1216.         |*|
  1217.         |*| Exit Conditions:
  1218.         |*|   Carry clear & AX = 0,  no data available
  1219.         |*|   Carry set   & AX = -1, data available
  1220.         |*|   DX,AX modified
  1221.         |*|
  1222.         \*/
  1223.  
  1224.                 public  AP_MDR_wait
  1225.         AP_MDR_wait     proc
  1226.                 push    cx
  1227.  
  1228.                 sub     cx,cx
  1229.         ;
  1230.         @@:
  1231.                 call    AP_MDR_stat
  1232.                 or      ax,ax
  1233.                 loopz   @B
  1234.  
  1235.                 pop     cx
  1236.                 ret
  1237.  
  1238.         AP_MDR_wait     endp
  1239.  
  1240.  
  1241.  
  1242.         /*\
  1243.         |*|----====< AP_MCW >====----
  1244.         |*|
  1245.         |*| Send a command byte out to the Micro.
  1246.         |*|
  1247.         |*| Entry Conditions:
  1248.         |*|    AL holds the command
  1249.         |*|
  1250.         |*| Exit Conditions:
  1251.         |*|    AX = -1 if data is available, or 0
  1252.         |*|    DX,AX modified
  1253.         |*|
  1254.         \*/
  1255.                 public  AP_MCW
  1256.         AP_MCW  proc
  1257.                 push    cx
  1258.  
  1259.                 mov     ah,al           ; save the command/data
  1260.  
  1261.         ;
  1262.         apmcw_00:
  1263.                 mov     dx,[PortAddress]
  1264.                 add     dl,_CONTROL
  1265.                 mov     al,WrIdle
  1266.                 out     dx,al
  1267.                 Idledly
  1268.  
  1269.                 mov     al,ah           ; get the byte and write it out
  1270.                 sub     dl,_CONTROL     ; move to the data port
  1271.                 out     dx,al           ; load the data
  1272.  
  1273.                 inc     dx              ; move to the status port
  1274.                 sub     cx,cx
  1275.         ;
  1276.         apmcw_05:
  1277.                 in      al,dx           ; wait=1 when cmd/data cannot be sent
  1278.                 test    al,stWait
  1279.                 loopnz  apmcw_05
  1280.                 jz      apmcw_10        ; its available
  1281.  
  1282.                 push    ax              ; The device is probably powered off, so
  1283.                 call    AP_reset        ; we just have to kick it...
  1284.                 pop     ax              ; AH holds the command/data byte
  1285.                 jmp     short apmcw_00
  1286.         ;
  1287.         apmcw_10:
  1288.                 inc     dx              ; move to the control port
  1289.  
  1290.                 mov     al,WrSndCmd     ; start the strobe
  1291.                 out     dx,al
  1292.  
  1293.                 mov     al,WrIdle       ; end the strobe
  1294.                 out     dx,al
  1295.                 Idledly
  1296.  
  1297.                 pop     cx
  1298.                 ret
  1299.  
  1300.         AP_MCW  endp
  1301.  
  1302.  
  1303.  
  1304.         /*\
  1305.         |*|----====< AP_MDR >====----
  1306.         |*|
  1307.         |*| Read a data byte from the Micro of FIFO
  1308.         |*|
  1309.         |*| Entry Conditions:
  1310.         |*|    Data Available must have been checked before calling
  1311.         |*|    this routine. It is assumed to be high.
  1312.         |*|
  1313.         |*| Exit Conditions:
  1314.         |*|    AL holds something...
  1315.         |*|    DX,AX modified
  1316.         |*|
  1317.         \*/
  1318.  
  1319.         AP_MDR  proc
  1320.                 push    cx
  1321.  
  1322.                 mov     dx,[PortAddress]
  1323.                 add     dl,_CONTROL
  1324.  
  1325.                 mov     al,RdIdle       ; go to read IDLE
  1326.                 out     dx,al
  1327.                 Idledly
  1328.  
  1329.                 mov     al,RdSndData    ; read the high nibble
  1330.                 out     dx,al           ; start the strobe
  1331.  
  1332.                 dec     dx              ; grab one nibble
  1333.                 in      al,dx           ; from the status port
  1334.                 mov     ah,al           ; save in AH!
  1335.  
  1336.                 inc     dx
  1337.                 mov     al,RdIdle       ; swap nibbles
  1338.                 out     dx,al           ; end the strobe
  1339.                 Idledly
  1340.  
  1341.                 dec     dx
  1342.                 in      al,dx           ; read the next nibble
  1343.  
  1344.                 mov     cl,WrIdle
  1345.                 xchg    ax,cx           ; save the bytes, load WrIdle
  1346.  
  1347.                 inc     dx              ; send H/W into write idle mode
  1348.                 out     dx,al
  1349.  
  1350.                 xchg    ax,cx           ; get the bytes
  1351.  
  1352.                 mov     cl,4
  1353.                 shr     ah,cl           ; this order makes for a
  1354.                 shr     ax,cl           ; fast conversion
  1355.  
  1356.                 pop     cx
  1357.                 ret
  1358.  
  1359.         AP_MDR  endp
  1360.  
  1361.  
  1362.  
  1363.         /*\
  1364.         |*|----====< AP_MDW >====----
  1365.         |*|
  1366.         |*| Send a data byte out to the FIFO.
  1367.         |*|
  1368.         |*| Entry Conditions:
  1369.         |*|    AL holds the data
  1370.         |*|
  1371.         |*| Exit Conditions:
  1372.         |*|    AX = -1 if data is available, or 0
  1373.         |*|    DX,AX modified
  1374.         |*|
  1375.         \*/
  1376.                 public  AP_MDW
  1377.         AP_MDW  proc
  1378.                 push    cx
  1379.  
  1380.                 mov     ah,al           ; save the command/data
  1381.         ;
  1382.         apmdw_00:
  1383.                 mov     dx,[PortAddress]
  1384.                 add     dl,_CONTROL
  1385.  
  1386.                 mov     al,WrIdle       ; make sure its' idle
  1387.                 out     dx,al
  1388.                 Idledly
  1389.  
  1390.                 mov     al,ah           ; get the byte and write it out
  1391.                 sub     dl,_CONTROL     ; move to the data port
  1392.                 out     dx,al           ; load the data
  1393.  
  1394.                 inc     dx              ; move to the status port
  1395.                 sub     cx,cx
  1396.         ;
  1397.         apmdw_05:
  1398.                 in      al,dx           ; wait=1 when cmd/data cannot be sent
  1399.                 test    al,stWait
  1400.                 loopnz  apmdw_05
  1401.                 jz      apmdw_10        ; its available
  1402.  
  1403.                 push    ax              ; The device is probably powered off, so
  1404.                 call    AP_reset        ; we just have to kick it...
  1405.                 pop     ax              ; AH holds the command/data byte
  1406.                 jmp     short apmdw_00
  1407.         ;
  1408.         apmdw_10:
  1409.                 inc     dx              ; move to the control port
  1410.  
  1411.                 mov     al,WrSndData    ; start the strobe
  1412.                 out     dx,al
  1413.  
  1414.                 mov     al,WrIdle       ; end the strobe
  1415.                 out     dx,al
  1416.                 Idledly
  1417.  
  1418.                 pop     cx
  1419.                 ret
  1420.  
  1421.         AP_MDW  endp
  1422.  
  1423.  
  1424.  
  1425.  
  1426.         /*\
  1427.         |*|----====< AP_SRQ_stat >====----
  1428.         |*|
  1429.         |*| Returns the status of Service Request
  1430.         |*|
  1431.         |*| Entry Conditions:
  1432.         |*|   None.
  1433.         |*|
  1434.         |*| Exit Conditions:
  1435.         |*|   Carry clear & AX = 0,  wait
  1436.         |*|   Carry set   & AX = -1, service request is posted
  1437.         |*|   DX,AX modified
  1438.         \*/
  1439.  
  1440.                 public  AP_SRQ_stat
  1441.         AP_SRQ_stat     proc
  1442.                 mov     dx,[PortAddress]
  1443.                 add     dl,_CONTROL
  1444.  
  1445.                 mov     al,WrIdle       ; Write Idle mode...
  1446.                 out     dx,al
  1447.                 Idledly
  1448.  
  1449.                 dec     dx              ; mov to the status port
  1450.  
  1451.                 in      al,dx           ; data rdy is high for data available
  1452.                 and     al,stSRQ
  1453.  
  1454.                 neg     al              ; set carry if non-zero
  1455.                 sbb     ax,ax           ; if data is available, return -1 & Cy
  1456.                 ret                     ; else return 0 & NC
  1457.  
  1458.         AP_SRQ_stat     endp
  1459.  
  1460.  
  1461.  
  1462.         /*\
  1463.         |*|----====< AP_FM_out >====----
  1464.         |*|
  1465.         |*| Send index/data out to the parallel FM chip
  1466.         |*|
  1467.         |*| Entry Conditions:
  1468.         |*|    AL holds the index
  1469.         |*|    AH holds the data
  1470.         |*|
  1471.         |*| Exit Conditions:
  1472.         |*|    None
  1473.         |*|    DX,AX modified
  1474.         \*/
  1475.  
  1476.                 public  AP_FM_out
  1477.         AP_FM_out       proc
  1478.                 push    cx
  1479.                 push    ax              ; save the index/data
  1480.         ;
  1481.         apfmo00:
  1482.                 mov     dx,[PortAddress]
  1483.                 add     dl,_CONTROL     ; move to the status port
  1484.  
  1485.                 mov     al,WrFMIdle     ; go into FM Mode
  1486.                 out     dx,al
  1487.                 Idledly
  1488.  
  1489.                 dec     dx              ; move back to status
  1490.                 sub     cx,cx           ; loop control
  1491.         ;
  1492.         apfmo05:
  1493.                 in      al,dx
  1494.                 test    al,stWait       ; FM wait high?
  1495.                 loopnz  apfmo05         ; yes, dont write it
  1496.                 jz      apfmo10         ; its available
  1497.  
  1498.                 call    AP_reset        ; The device is probably powered off, so
  1499.                 jmp     short apfmo00   ; we just have to kick it...
  1500.         ;
  1501.         apfmo10:
  1502.  
  1503.                 pop     ax              ; get the index and data
  1504.                 jnz     apfmobad        ; bomb out if we cant do it
  1505.  
  1506.                 dec     dx              ; move to the data port
  1507.                 out     dx,al           ; load the data port
  1508.  
  1509.                 inc     dx              ; move to the control register
  1510.                 inc     dx
  1511.  
  1512.                 mov     al,WrFMAddr
  1513.                 out     dx,al           ; start the strobe
  1514.  
  1515.                 mov     al,WrFMIdle
  1516.                 out     dx,al           ; end the strobe
  1517.                 Idledly
  1518.  
  1519.                 mov     al,ah
  1520.                 sub     dl,_CONTROL     ; move to the data port
  1521.                 out     dx,al           ; load the data port
  1522.  
  1523.                 add     dl,_CONTROL
  1524.                 mov     al,WrFMData
  1525.                 out     dx,al           ; start the strobe
  1526.  
  1527.                 mov     al,WrFMIdle
  1528.                 out     dx,al           ; end the strobe
  1529.                 Idledly
  1530.  
  1531.                 mov     al,WrIdle
  1532.                 out     dx,al           ; back to write idle...
  1533.  
  1534.         ;
  1535.         apfmobad:
  1536.                 pop     cx
  1537.                 ret
  1538.  
  1539.         AP_FM_out       endp
  1540.  
  1541.  
  1542.  
  1543.         /*\
  1544.         |*|----====< AP_FM_in >====----
  1545.         |*|
  1546.         |*| Read the FM status register
  1547.         |*|
  1548.         |*| Entry Conditions:
  1549.         |*|    None
  1550.         |*|
  1551.         |*| Exit Conditions:
  1552.         |*|    AL holds the status byte
  1553.         |*|    DX,AX modified
  1554.         \*/
  1555.  
  1556.         AP_FM_in        proc
  1557.                 mov     dx,[PortAddress]
  1558.                 add     dl,_CONTROL     ; point to control port
  1559.  
  1560.                 mov     al,WrIdle       ; make sure we're idle
  1561.                 out     dx,al
  1562.                 Idledly
  1563.  
  1564.                 mov     al,RdFMIdle     ; go into FM Mode
  1565.                 out     dx,al
  1566.                 Idledly
  1567.  
  1568.                 mov     al,RdFMStat     ; clock in the data
  1569.                 out     dx,al
  1570.  
  1571.                 dec     dx              ; move to the status port
  1572.                 in      al,dx
  1573.                 mov     bl,al           ; save the high nibble
  1574.  
  1575.                 inc     dx
  1576.                 mov     al,RdFMIdle     ; all set
  1577.                 out     dx,al           ; strobe address
  1578.                 Idledly
  1579.  
  1580.                 dec     dx
  1581.                 in      al,dx           ; clock in the data
  1582.                 mov     bh,al
  1583.  
  1584.                 inc     dx
  1585.                 mov     al,WrIdle       ; go back to idle mode
  1586.                 out     dx,al
  1587.                 Idledly
  1588.  
  1589.                 mov     cl,4
  1590.                 shr     bh,cl
  1591.                 shr     bx,cl
  1592.  
  1593.                 mov     al,bl
  1594.  
  1595.                 ret
  1596.  
  1597.         AP_FM_in        endp
  1598.  
  1599.  
  1600.  
  1601.  
  1602.