home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-05-12 | 60.5 KB | 1,602 lines |
-
-
-
-
-
- ----==================================----
- ----====< Audio Port Programming >====----
- ----==================================----
-
-
-
- TABLE OF CONTENTS
-
-
-
- 1. Audio Port overview
-
-
- 2. Programming Considerations
-
- A. Hardware I/O Addresses
- B. Audio Port Interface Controller
- C. Command/Data Handshaking
-
-
- 3. Digital Audio programming
-
- A. Sending Micro Commands/Data
- B. Reading Micro Data
- C. Reading FIFO data
- D. Writing FIFO data
- E. Micro Commands
-
-
- 4. FM programming.
-
-
- 5. Interrupt processing.
-
-
- Appendix A - Hardware Ports & States
-
-
- Appendix B - Example routines
-
-
-
-
- AUDIO PORT OVERVIEW
-
-
- The Audio Port is a portable audio device designed for
- use with laptop or desktop computers. This device, which
- attaches to the standard IBM PC parallel port, can record
- and playback 22khz mono digital audio. Included with the
- Audio Port is a built-in FM synthesis chip, the Yamaha 3812.
-
- The Audio Port supports ADPCM hardware compression, and
- decompression, in real-time, at rates up to 22khz. Speci-
- fically, the device support 2-to-1 and 4-to-1 compression
- ratios.
-
- The programming interface is based upon the standard
- parallel port I/O scheme, with a few bits redefined. The
- parallel port on the IBM PC uses 3 I/O addresses; one output
- data, one input status, and one output control. On certain
- IBM AT compatible machines, the data port has been made into
- a bi-directional data path for use with network adapters,
- and other peripherals. The Audio Port supports this
- bi-directional 8 bit data path.
-
- The Audio Port interfaces the FM and microcontroller
- chip to the PC via the Audio Port Interface Controller; aka,
- the APIC. The following diagram illustrates the data/control
- path.
-
-
-
- ┌──────┐ ┌─┐/│
- │ │ ┌────────────────────────┐ │ │ │
- │ ├─┐ ┴┌───────┐ ┌─────┐ │ ┌───┤ │ │
- │ │p├─────┤ ╞════╡ FM ├──┐ │ │ │ │ │
- │ IBM │a├─────┤ │ └─────┘ │ │ │ └─┘\│
- │ │r├─────┤Audio │ ┌───────┐│ ┴ │
- │ PC/ │a├─────┤Port ╞════╡DAC/ ├┴───┘
- │ │l├─────┤Interfc│ │ADC ├────┐
- │ AT │l├─────┤Ctlr │ └──┬────┘ ┬ │ ┌─┐
- │ │e├─────┤ │ ┌──┴──┐ │ │┌────┤░│
- │ │l├─────┤ ╞════╡Micro│ │ └┤ │░│
- │ ├─┘ ┬└───────┘ └─────┘ │ └────┤░│
- │ │ └────────────────────────┘ └─┘
- └──────┘
-
-
-
- The APIC handles the actual clocking of data, and
- determines the target device, either FM or the micro-
- controller. In certain DAC/ADC modes, the APIC will drive
- the DAC/ADC without intervention from the microcontroller
- through the use of an internal 1k FIFO.
-
- Data sent to the different devices require some
- handshaking to guarantee that commands and data do not
- overrun. This control is a single bit that is multiplexed
- between the FM and Micro.
-
-
-
-
-
- ----====< PROGRAMMING CONSIDERATIONS >====----
-
-
- H A R D W A R E I / O A D D R E S S E S
-
-
- On the IBM PC/AT, three parallel ports can be found at
- several addresess. For each of the parallel port there are
- three I/O ports for communications to the external parallel
- devices. The following map defines the three I/O ports,
- across the three ranges of addresses.
-
-
- NAME LPT1 LPT2 MONO DESCRIPTION
- ┌───────────┬───┬─────┬─────┬─────┬──────────────────┐
- │Data Output│R/W│ 378 │ 278 │ 3BC │ write output data│
- ├───────────┼───┼─────┼─────┼─────┼──────────────────┤
- │Status │ R │ 379 │ 279 │ 3BD │ read status/data │
- ├───────────┼───┼─────┼─────┼─────┼──────────────────┤
- │Control │ W │ 37A │ 27A │ 3BE │ control lines │
- └───────────┴───┴─────┴─────┴─────┴──────────────────┘
-
-
- The following illustrations show the actual bit definitions
- of the three parallel port I/O addresses:
-
-
- Data Register Definitions:
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Data │bit7│bit6│bit5│bit4│bit3│bit2│bit1│bit0│
- └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- +----+----+----+----+----+----+----+-- Data lines
-
-
- Status Register Definitions:
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Status │ W │IRQ │PAR │SRQ │ DA │ X │ X │ X │
- └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- | | | | | +----+----+-- unused
- | | | | +----------------- Data Available
- | | | +---------------------- SRQ/D4/D0
- | | +--------------------------- PAR/D5/D1
- | +-------------------------------- IRQ/D6/D2
- +------------------------------------- WAIT/D7/D3
-
- D7 - Wait status bit. It presents the
- command/data register full for either
- the FM or Micro registers, depending
- on the control register state.
-
- D6 - IRQ is pending bit. Same as the
- parallel port definition.
-
- D5 - Input Data Enabled.
-
- D4 - Service ReQuest. This bit is used
- by the digital audio FIFO to indicate
- if the FIFO can take more data.
-
- D3 - Data is available from the Micro or
- FIFO. FM never sends data to the PC.
-
- When the control register is in a read
- state, D4-D7 become input lines presenting
- each nibble of the 8 bit byte. During the
- control port read idle state, the low nibble
- is presented. During a read data state, the
- high nibble is presented.
-
-
- Control Register Definitions:
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Control│PAR │PAR │PAR │IRQ │ AS │MFM │ DS │ RW │
- └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- | | | | | | | +-- Read(0)/Write(1)
- | | | | | | +------- Data Strobe
- | | | | | +------------ Micro/FM select
- | | | | +----------------- Address Strobe
- | | | +---------------------- IRQ Enable
- +----+----+--------------------------- Parallel Input
-
- D0-D3. These lines control the clocking to
- the API . It is best to view these
- four lines as control words with 16
- possible states. A list of the control
- states follows.
-
- D4 When this bit is set to 1, interrupts
- are allowed to be pass to the 8259
- interrupt controller on the mother-
- board. Using interrupts from the
- parallel port is never advised. It is
- best to a faster system timer to
- perform interrupt duties.
-
- D5-D7 With these bits high, some bi-
- directional parallel ports become
- active, that is, allow for 8 bit data
- to be read from the data port.
-
-
- The DATA port is used for sending data/commands to the
- Audio Port. In cases where the computer supports bi-
- directional data transfers, data can be read from the Audio
- Port via this register. IBM did not design the parallel port
- to be bi-directional, so in most cases, this feature will
- not be used.
-
-
-
- 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
-
-
- It is important to understand the concepts of talking to
- the APIC. This device is the front-end to the separate
- pieces of the Audio Port. The PC software is responsible for
- creating the proper handshaking with the APIC. As implied by
- it's name, there are specific hardware states for driving
- either FM, or digital audio. The following is a list of all
- the possible states for the Audio Port:
-
- Value State Name Function
-
- 00h RdFMIdle Read FM Idle
- 01h WrFMIdle Write FM Idle
- 02h invalid invalid state
- 03h WrFMData Write FM Data
- 04h RdIdle Read Sound Idle
- 05h WrIdle Write Sound Idle
- 06h RdSndData Read Sound Data
- 07h WrSndData Write Sound Data
- 08h RdFMStat Get FM Status
- 09h WrFMAddr Write FM Address
- 0Ah invalid invalid state
- 0Bh invalid And another Reset
- 0Ch RdSndStat Read Sound Status
- 0Dh WrSndCmd Write Sound Command
- 0Eh invalid invalid state
- 0Fh WrReset2 Write Reset
-
- The four low order bits in the Control register
- determine the state of the interface. Notice that some of
- the states are invalid. Never assume that setting an invalid
- state is harmless! An invalid state may present certain
- clocking signals that may, for instance, load PCM data into
- the FM index register. Other transitions from or to an
- invalid state may have undetermined effects on the Audio
- Port.
-
- The actual APIC logic requires the PC to program the
- Audio Port in a concise manner. Transitions from idle to
- active, then back to idle states, must be strictly adhered
- to, or unpredictable results may occur. The basic programm-
- ing convention is to leave the control port in Write Idle
- mode when idle. This way, another state can be transistioned
- in and out. Another benefit of leaving the control port in
- Write Idle is that the status register is switched to status
- mode, not read nibble mode; therefore, all status bits are
- available for reading. For more info, see the above
- description of the Status Port.
-
- The following are simple state flow diagrams. Reading
- from left to right, these diagrams show the various legal
- states for writing commands or data, or just reading data.
- The I/O to the data port and status ports are not shown.
-
-
- TO RESET THE AUDIO PORT:
-
- WrIdle__>___ WrReset2 __>________________________ WrIdle
-
-
- TO WRITE COMMANDS/DATA TO THE MICRO:
-
- _ WrSndCmd __>_____________________
- WrIdle__>_/ \__ WrIdle
- \_ WrSndData __>_____________________/
-
-
- TO READ MICRO DATA:
-
- WrIdle__>_ RdIdle__>_ RdSndData__>_ RdIdle__>_____ WrIdle
-
-
- TO WRITE INDEX/DATA TO THE FM CHIP:
-
- _ WrFMAddr _
- WrIdle__>_ WrFMIdle__/ \__ WrFMIdle__>_ WrIdle
- \_ WrFMData _/
-
-
- TO READ FM STATUS:
-
- WrIdle__>_ RdFMIdle__>_ RdFMStat__>_ RdFMIdle__>__ WrIdle
-
-
-
- A typical sequence to send a PCM data byte would be:
-
- mov dx,[PortAddress] ; get the base address.
-
- add dl,_CONTROL ; move to the control port.
- mov al,WrIdle ; set to Write Idle mode.
- out dx,al
- Idledly
-
- sub dl,_CONTROL ; move to the data port.
- mov al,[DataByte] ; port, then send the
- out dx,al ; data byte.
-
- add dl,_CONTROL ; move to the control port.
- mov al,WrSndData ; strobe the data out.
- out dx,al
-
- mov al,WrIdle ; complete the strobe by
- out dx,al ; returning to write idle.
- Idledly
-
-
- Two things to note from the above example; to strobe
- data out to the Audio Port, the Audio port must make state
- transitions from Idle, to an active send, then back to idle.
- The second thing to note, is the required I/O delay when
- returning to idle mode. By IBM's design, the parallel port
- hardware signal timings make transitions to active states
- very quickly. When transitioning into idle modes, the
- signals take almost twice as long. The above example shows
- the use of a simple text macro called "Idledly". This macro
- It could be defined as:
-
- Idledly equ <out dx,al>
-
- All it does, is perform an addition I/O write instruction,
- which on the IBM ISA bus, is guaranteed to take a minimum of
- 850ns of time.
-
- The other equates used in the above code segment have
- the following values:
-
- _DATA equ 0
- _STATUS equ 1
- _CONTROL equ 2
-
-
-
-
- C O M M A N D / D A T A H A N D S H A K I N G
-
-
- When the PC clocks data to the Micro or FM, the APIC
- latches the data, watches the signals, then sends the data
- to the appropriate device. In order to help the PC know when
- to send the index, commands, or data, a status bit in the
- Status register is presented for the PC to poll. This status
- bit, bit D7, is used for both the FM and Micro WAIT
- status's. The Control register state, WrIdle or WrFMIdle,
- determine which WAIT state is being presented for either
- the FM or Micro.
-
- For sending index/data to the 3812 FM chip, Yamaha has
- defined certain timing delays between the writes. Index
- writes take a minimum of 5 micro seconds to complete. Data
- writes take a minimum of 35 micro seconds to complete. The
- APIC starts clocking the index/data out to the FM chip once
- the PC finishes clocking out the data byte to the APIC.
- During the time the APIC is clocking the index/data out to
- the 3812, the WAIT bit will be held high. The APIC holds the
- wait line high for the entire duration of both index and
- data write times. This means the PC has to poll the wait
- line before writing the index, but can write both the index,
- then data byte with no intervening waits.
-
- For Micro reads and writes, the WAIT line is derived
- from the micro. The APIC just passes this signal through
- unaltered. During Write idle, the WAIT line indicates
- whether the Micro can receive more commands or data. The
- signal goes high (1) when WAIT is asserted.
-
- For queued DAC output, the WAIT line goes active (1)
- when the queue cannot receive more data. For ADC input, the
- WAIT line goes active (1) when the queue is emptied.
-
-
-
-
- DIGITAL AUDIO PROGRAMMING
-
- The Digial Audio section is controlled by both the APIC
- and Microcontroller. All commands issued are processed by
- the microcontroller. The APIC provides the clocking control,
- and FIFO management. To issue commands to the micro, the
- status port must be polled to check the WAIT bit. The Micro
- WAIT is presented during WrIdle mode. When the bit is low
- (0), commands or data may be written.
-
-
- Micro Command Set:
-
- ┌────────────────┬──────────┬─────────┬─────────┬─────────┬─────────┐
- │ Command │D7-D4 Code│ D3 │ D2 │ D1 │ D0 │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ 0 │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │System Control │ 1 │ X │ X │ X │ X │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │8 Bit PCM Direct│ 2 │Play/Rcd │AGC Kill │ Timer │ 0 │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ 3 │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │Play PCM Queue │ 4 │Compress │ 4/2 Bit │ Timer │ Ref │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │Rcd 8 Bit Queue │ 5 │ VOX │AGC Kill │ Timer │ 0 │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │Rcd 4 Bit Queue │ 6 │ VOX │AGC Kill │ Timer │ 1 │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │Rcd 2 Bit Queue │ 7 │ VOX │AGC Kill │ Timer │ 1 │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ 8 │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ 9 │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ A │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ B │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ C │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ D │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ E │ . │ . │ . │ . │
- ├────────────────┼──────────┼─────────┼─────────┼─────────┼─────────┤
- │ reserved │ F │ . │ . │ . │ . │
- └────────────────┴──────────┴─────────┴─────────┴─────────┴─────────┘
-
- System Control Commands - 0001xxxx
-
-
- 10h SYSCMDIDLE - Terminate DAC/ADC modes, return to Idle.
- This is guaranteed to return the Audio
- Port Micro to an Idle state
-
- Parameters: No Parameters
- Returns: No Data Returned
-
- 11h SYSCMDGETID - Get ESP version
-
- Parameters: No parameters
- Returns: Returns 2 bytes
-
- 13h SYSCMDENAPARR - Enable Parallel Input
-
- Parameters: No Parameters
- Returns: No Data Returned
-
- 14h SYSCMDDISPARR - Disable Parallel Input
-
- Parameters: No Parameters
- Returns: No Data Returned
-
- 15h SYSCMDTSTPARR - Test Parallel Input
-
- Parameters: One data byte following (any value)
-
- Returns: Returns the same data byte
- in parallel mode.
-
-
- Direct DAC/ADC Control Commands - 0010xxxx
-
- NOTE: The AGC kill bit disables the internal Auto Gain
- Control. This bit is normally set to 0, thus allowing
- the AGC to function. Setting this bit to a 1 turns
- off the AGC for the duration of the recording.
-
- 20h SYSDIRPLAY - 8 bit direct play.
-
- This places the Audio Port Micro into DAC
- output mode. The queue is not enabled.
-
- Parameters: Sound Data follows.
- Returns: No Data Returned
-
- 22h SYSDIRNA2 - 8 bit direct play w/time constant following.
-
- This places the Audio Port Micro into
- DAC output mode. The queue is not enabled.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Sound Data follows.
- Returns: No Data Returned
-
- 28h SYSDIRRECD - 8 bit direct record.
-
- Sampled data will be made available until
- command 10H is issued.
-
- Parameters: No Parameters
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
- 2Ah SYSDIRNAA - 8 bit direct record w/time constant following.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
-
- FIFO DAC/ADC Commands - 0100xxxx
-
-
-
- 40h SYSDIRQPLAY - 8 bit FIFO DAC out.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: Sound Data follows.
-
- Returns: No Data Returned
-
- 42h SYSDIRQNA2 - 8 bit FIFO DAC out w/time constant following.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Parameters: Sound Data follows.
-
- Returns: No Data Returned
-
- 48h SYSDIRQRECD - 4 bit FIFO DAC out decompression
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: Sound Data follows.
-
- Returns: No Data Returned
-
- 49h SYSDIRQRECD - 4 bit FIFO DAC out decompression with
- reference byte.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: One 8 bit sample follows. This is the seed
- value for decompression.
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- 4Ah SYSDIRQRECD - 4 bit FIFO DAC out decompression with
- time constant following.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- 4Bh SYSDIRQRECD - 4 bit FIFO DAC out decompression with
- time constant following.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: Two parameter bytes follows. The first is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- The second byte is the seed value for
- decompression.
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- 4Ch SYSDIRQRECD - 2 bit FIFO DAC out decompression.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: Sound Data follows.
-
- Returns: No Data Returned
-
- 4Dh SYSDIRQRECD - 2 bit FIFO DAC out decompression with
- reference byte.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: One 8 bit sample follows. This is the seed
- value for decompression.
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- 4Eh SYSDIRQRECD - 2 bit FIFO DAC out decompression with
- time constant following.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- 4Fh SYSDIRQRECD - 2 bit FIFO DAC out w/time constant following.
-
- This function enables the 1k FIFO output
- to the DAC. Watch the SRQ line to send out
- 256 byte blocks.
-
- Parameters: Two parameter bytes follows. The first is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- The second byte is the seed value for
- decompression.
-
- Sound Data follows.
-
- Returns: No Data Returned
-
- FIFO 8 Bit Recording Commands - 0101xxxx
-
- NOTE: The AGC kill bit disables the internal Auto Gain
- Control. This bit is normally set to 0, thus allowing
- the AGC to function. Setting this bit to a 1 turns
- off the AGC for the duration of the recording.
- The VOX bit allows voice activated recording. When
- this bit is set (1), the Audio Port will only begin
- recording when the mic signal reaches certain volumes.
- When in VOX mode, the Audio Port will stop recording
- 1 to 2 seconds after the mic signal becomes quiet.
-
-
- 50h SYSDIRPLAY - 8 bit FIFO record.
- Sampled data will be made available until
- command 10H is issued.
-
- Parameters: No Parameters
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
- 52h SYSDIRNA2 - 8 bit FIFO w/time constant following.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
-
- FIFO 4 Bit Recording Commands - 0110xxxx
-
- NOTE: The AGC kill bit disables the internal Auto Gain
- Control. This bit is normally set to 0, thus allowing
- the AGC to function. Setting this bit to a 1 turns
- off the AGC for the duration of the recording.
- The VOX bit allows voice activated recording. When
- this bit is set (1), the Audio Port will only begin
- recording when the mic signal reaches certain volumes.
- When in VOX mode, the Audio Port will stop recording
- 1 to 2 seconds after the mic signal becomes quiet.
-
- 60h SYSDIRPLAY - 4 bit FIFO record compression.
-
- Sampled data will be made available until
- command 10H is issued.
-
- Parameters: No Parameters
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
- 63h SYSDIRNA2 - 4 bit FIFO w/time constant byte parameter.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Returns: Sampled data will be made available until
- command 10H is issued. The first sample
- returned is the full 8 bit sample used
- as the reference byte.
-
-
- FIFO 2 Bit Recording Commands - 0110xxxx
-
- NOTE: The AGC kill bit disables the internal Auto Gain
- Control. This bit is normally set to 0, thus allowing
- the AGC to function. Setting this bit to a 1 turns
- off the AGC for the duration of the recording.
- The VOX bit allows voice activated recording. When
- this bit is set (1), the Audio Port will only begin
- recording when the mic signal reaches certain volumes.
- When in VOX mode, the Audio Port will stop recording
- 1 to 2 seconds after the mic signal becomes quiet.
-
- 70h SYSDIRPLAY - 2 bit FIFO record.
-
- Sampled data will be made available until
- command 10H is issued.
-
- Parameters: No Parameters
-
- Returns: Sampled data will be made available until
- command 10H is issued.
-
- 73h SYSDIRNA2 - 2 bit FIFO w/time constant following.
-
- Parameters: One byte parameter follows. This is the
- sample rate speed. The following function
- calculates the sample rate:
-
- TimeConst = 256-(1000000/SampleRate)
-
- Returns: Sampled data will be made available until
- command 10H is issued. The first sample
- returned is the full 8 bit sample used
- as the reference byte.
-
-
- FM PROGRAMMING.
-
- For sending index/data to the 3812 FM chip, Yamaha has
- defined certain timing delays between the writes. Index
- writes take a minimum of 5 micro seconds to complete. Data
- writes take a minimum of 35 micro seconds to complete. The
- APIC starts clocking the index/data out to the FM chip once
- the PC finishes clocking out the data byte to the APIC.
- During the time the APIC is clocking the index/data out to
- the 3812, the WAIT bit will be held high. The APIC holds the
- wait line high for the entire duration of both index and
- data write times plus delay times. This means the PC has to
- poll the wait line before writing the index, but can write
- both the index, then data byte with no intervening waits.
-
-
- INTERRUPT PROCESSING.
-
- The recommended approach for interrupt processing is to use
- a fast system timer interrrupt. The system timer should be re-
- programmed to generate an interrupt every 30 milliseconds to
- check the SRQ line. If the SRQ is high, another 256 byte block
- of PCM data can be read or written. At interrupt time, upon
- completing the first 256 byte block, check SRQ again, and
- repeat the process until the SRQ goes low. Once all blocks are
- finished, the system timer can be reprogrammed to interrupt at
- it's normal frequency of 18.2 times per second.
-
- On DAC output, The SRQ line goes high when the 1k buffer
- has 256 bytes, or less remaining. It goes low when it has
- 768 bytes or more stored.
-
- On ADC input, the SRQ line goes high if the FIFO has
- 768 or more bytes. It goes low when it has 256 or fewer
- bytes stored.
-
-
-
- APPENDIX A - HARDWARE PORTS & STATES
-
-
- NAME LPT1 LPT2 MONO DESCRIPTION
- ┌───────────┬───┬─────┬─────┬─────┬─────────────────┐
- │Data Output│ R │ 378 │ 278 │ 3BC │write to TP │
- ├───────────┼───┼─────┼─────┼─────┼─────────────────┤
- │Status │ R │ 379 │ 279 │ 3BD │read status/data │
- ├───────────┼───┼─────┼─────┼─────┼─────────────────┤
- │Control │ W │ 37A │ 27A │ 3BE │set I/O control │
- └───────────┴───┴─────┴─────┴─────┴─────────────────┘
-
-
- Base Address + 0 offset - Data Register Definitions:
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌───────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Data │bit7│bit6│bit5│bit4│bit3│bit2│bit1│bit0│
- └───────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- +----+----+----+----+----+----+----+-- Data lines
-
-
- Base Address + 1 offset - Status Register Definitions
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌─────────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Status │ W │IRQ │PAR │SRQ │ DA │ X │ X │ X │
- └─────────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- | | | | | +----+----+- unused
- | | | | +---------------- Data Available
- | | | +--------------------- SRQ/D4/D0
- | | +-------------------------- PAR/D5/D1
- | +------------------------------- IRQ/D6/D2
- +------------------------------------ WAIT/D7/D3
-
-
- Base Address + 2 offset - Control Register Definitions
-
- D7 D6 D5 D4 D3 D2 D1 D0
- ┌─────────┬────┬────┬────┬────┬────┬────┬────┬────┐
- │Control │PAR │PAR │PAR │IRQ │ AS │MFM │ DS │ RW │
- └─────────┴────┴────┴────┴────┴────┴────┴────┴────┘
- | | | | | | | |
- | | | | | | | +- Read(0)/Write(1)
- | | | | | | +------ Data Strobe
- | | | | | +----------- Micro/FM select
- | | | | +---------------- Address Strobe
- | | | +--------------------- IRQ Enable
- +----+----+-------------------------- Par. input select
-
-
- Control Register Clock State:
-
- 00h RdFMIdle Read FM Idle
- 01h WrFMIdle Write FM Idle
- 02h invalid invalid state
- 03h WrFMData Write FM Data
- 04h RdIdle Read Sound Idle
- 05h WrIdle Write Sound Idle
- 06h RdSndData Read Sound Data
- 07h WrSndData Write Sound Data
- 08h RdFMStat Get FM Status
- 09h WrFMAddr Write FM Address
- 0Ah invalid invalid state
- 0Bh invalid And another Reset
- 0Ch RdSndStat Read Sound Status
- 0Dh WrSndCmd Write Sound Command
- 0Eh invalid invalid state
- 0Fh WrReset2 Write Reset
-
- Control Register Additional bit definitions
-
- 10h Interrupt Enable interrupt
- E0h EnableInput Enable Parallel Input
-
-
-
- APPENDIX B - EXAMPLE ROUTINES
-
- The following code assumes the parallel port base I/O
- address for the Audio Port is stored in the variable,
- "PortAddress".
-
- The following macros and equates are used in the code
- examples:
-
- Idledly equ <out dx,al>
-
- _DATA equ 0 ; Parallel port data port offset
- _STATUS equ 1 ; Parallel port status port offset
- _CONTROL equ 2 ; Parallel port control port offset
-
- RdFMIdle equ 00h ; Read FM Idle
- WrFMIdle equ 01h ; Write FM Idle
- invalid equ 02h ; invalid state
- WrFMData equ 03h ; Write FM Data
- RdIdle equ 04h ; Read Sound Idle
- WrIdle equ 05h ; Write Sound Idle
- RdSndData equ 06h ; Read Sound Data
- WrSndData equ 07h ; Write Sound Data
- RdFMStat equ 08h ; Get FM Status
- WrFMAddr equ 09h ; Write FM Address
- invalid equ 0Ah ; invalid state
- invalid equ 0Bh ; And another Reset
- RdSndStat equ 0Ch ; Read Sound Status
- WrSndCmd equ 0Dh ; Write Sound Command
- invalid equ 0Eh ; invalid state
- WrReset2 equ 0Fh ; Write Reset
-
-
-
-
- ;
- ; /*\
- ;---|*|----====< AP_ADC_input >====----
- ;---|*|
- ;---|*| Input 256 bytes from the AP FIFO. This routine
- ;---|*| assumes that the AP is already in ADC input mode.
- ;---|*|
- ;---|*| Entry Conditions:
- ;---|*| ES:DI point to the buffer.
- ;---|*| CX holds a count of 1 to 256
- ;---|*|
- ;---|*| Exit Conditions:
- ;---|*| ES:DI is updated. CX is zero
- ;---|*| AX,BX,CX,DX,ES:DI modified
- ;---|*|
- ; \*/
- ;
- public AP_ADC_input
- AP_ADC_input proc near
- ;
- ; load the FIFO quarter size for use with the SRQ handshaking.
- ;
- mov dx,[PortAddress] ; get the port address
- add dl,_CONTROL
- cld ; STOSBs are used
- ;
- apadc05:
-
- mov al,RdIdle ; go into Read Idle to pick up the nibble
- out dx,al ; Idle w/o interrupts
- Idledly
-
- dec dx ; move to STATUS
- in al,dx
- mov ah,al ; save the high nibble
- inc dx
-
- mov al,RdSndData ; ah = RdIdle, al = RdSndData
- out dx,al ; this delivers the second nibble
- Idledly
-
- dec dx
- in al,dx ; fetch it
-
- shr ah,4 ; merge the nibbles
- shr ax,4
-
- stosb ; save the byte
- or di,di ; segment wrap?
- jz apadcsegwrap ; yes, go adjust...
- ;
- apadc10:
- inc dx ; place the board into idle mode again
- loop apadc05 ; do all 256 or less bytes
-
- mov al,WrIdle ; return back to write idle
- out dx,al
- Idledly
-
- ret ; all done recording this block!
- ;
- apadcsegwrap:
- mov di,es ; wrap the segment for huge model
- add di,1000h ; support.
- mov es,di
- sub di,di
- jmp short apadc10
-
- AP_ADC_input endp
-
-
-
- ;
- ; /*\
- ;---|*|----====< AP_DAC_output >====----
- ;---|*|
- ;---|*| Output 256 bytes to the AP FIFO. This routine
- ;---|*| assumes that the AP is already in DAC output mode.
- ;---|*|
- ;---|*| Entry Conditions:
- ;---|*| ES:DI point to the buffer.
- ;---|*| CX holds a count of 1 to 256
- ;---|*|
- ;---|*| Exit Conditions:
- ;---|*| ES:DI is updated. CX is zero
- ;---|*| AX,CX,DX,ES:DI modified
- ;---|*|
- ; \*/
- ;
- public AP_DAC_output
- AP_DAC_output proc near
- ;
- ; make sure the port is in write idle mode...
- ;
- mov dx,[PortAddress] ; get the port address
- add dl,_CONTROL
- mov al,WrIdle ; make sure its idle
- out dx,al
- sub dl,_CONTROL ; move back to the data port
- ;
- apdac05:
- ;
- ; send 256 bytes of data out to the FIFO
- ;
- mov al,es:[di] ; fetch the byte
- inc di
- jz apdacsegwrap ; odd case jumps out...
- ;
- apdac10:
-
- out dx,al ; write it to the audio port
-
- add dl,_CONTROL
-
- mov al,WrSndData ; start the strobe...
- out dx,al
-
- mov al,WrIdle ; end the strobe....
- out dx,al
- Idledly
-
- sub dl,_CONTROL
- loop apdac05 ; do all 256 or less bytes
-
- ret
- ;
- apdacsegwrap:
- mov di,es ; move to the next segment
- add di,1000h
- mov es,di
- sub di,di
- jmp short apdac10 ; then get back into the playback
-
- AP_DAC_output endp
-
-
-
-
- /*\
- |*|----====< AP_Reset >====----
- |*|
- |*| Reset the Audio Port
- |*|
- |*| Entry Conditions:
- |*| None.
- |*|
- |*| Exit Conditions:
- |*| AL holds the reset byte - 05A if successful
- |*| AX,BX,CX,DX modified
- |*|
- \*/
- public AP_Reset
- AP_Reset proc
-
- mov dx,[PortAddress]
- mov al,-1 ; load FF into the data port to drive the
- out dx,al ; data lines.
-
- add dl,_CONTROL
- mov cx,16
- mov al,WrReset2 ; output reset mode
- ;
- @@:
- out dx,al
- loop @B
-
- mov cx,16
- ;
- @@:
- mov al,WrIdle ; clear reset
- out dx,al
- loop @B
-
- mov al,RdIdle ; get sound data read status
- out dx,al
- Idledly
-
- dec dx ; move back to the status port
- sub cx,cx
- ;
- aprst05:
- in al,dx
- test al,stIDav ; wait for data to become available
- loopz aprst05
- jz aprstbad
-
- mov ah,al ; save the result (should not be 0xFF)
-
- inc dx ; move to the control port
- mov al,RdSndData ; Clock in the data
- out dx,al
-
- dec dx
- in al,dx
- mov bx,ax
-
- inc dx
- mov al,RdIdle ; go back to idle
- out dx,al
- Idledly
-
- mov al,WrIdle ; go back to idle
- out dx,al
- Idledly
-
- mov cl,4 ; build the reset byte.
- shr bh,cl
- shr bx,cl
-
- mov al,bl
- ret
- ;
- aprstbad:
- mov al,-1
- ret
-
- AP_reset endp
-
-
-
- /*\
- |*|----====< AP_MDR_stat >====----
- |*|
- |*| Returns the status of data available
- |*|
- |*| Entry Conditions:
- |*| None.
- |*|
- |*| Exit Conditions:
- |*| Carry clear & AX = 0, no data available
- |*| Carry set & AX = -1, data available
- |*| DX,AX modified
- |*|
- \*/
-
- public AP_MDR_stat
- AP_MDR_stat proc
- mov dx,[PortAddress]
- add dl,_CONTROL
-
- mov al,RdIdle ; Micro read idle
- out dx,al
- Idledly
-
- dec dx ; mov to the status port
-
- in al,dx ; data rdy is high for data available
- mov ah,stIDav
- and ah,al ; save the status bit
-
- mov al,WrIdle ; send the port back to
- out dx,al ; idle mode
- Idledly
-
- neg ah ; set carry if non-zero
- sbb ax,ax ; if data is available, return -1 & Cy
- ret ; else return 0 & NC
-
- AP_MDR_stat endp
-
-
-
- /*\
- |*|----====< AP_MDR_wait >====----
- |*|
- |*| Wait for Micro Data Read to be ready.
- |*|
- |*| Entry Conditions:
- |*| None.
- |*|
- |*| Exit Conditions:
- |*| Carry clear & AX = 0, no data available
- |*| Carry set & AX = -1, data available
- |*| DX,AX modified
- |*|
- \*/
-
- public AP_MDR_wait
- AP_MDR_wait proc
- push cx
-
- sub cx,cx
- ;
- @@:
- call AP_MDR_stat
- or ax,ax
- loopz @B
-
- pop cx
- ret
-
- AP_MDR_wait endp
-
-
-
- /*\
- |*|----====< AP_MCW >====----
- |*|
- |*| Send a command byte out to the Micro.
- |*|
- |*| Entry Conditions:
- |*| AL holds the command
- |*|
- |*| Exit Conditions:
- |*| AX = -1 if data is available, or 0
- |*| DX,AX modified
- |*|
- \*/
- public AP_MCW
- AP_MCW proc
- push cx
-
- mov ah,al ; save the command/data
-
- ;
- apmcw_00:
- mov dx,[PortAddress]
- add dl,_CONTROL
- mov al,WrIdle
- out dx,al
- Idledly
-
- mov al,ah ; get the byte and write it out
- sub dl,_CONTROL ; move to the data port
- out dx,al ; load the data
-
- inc dx ; move to the status port
- sub cx,cx
- ;
- apmcw_05:
- in al,dx ; wait=1 when cmd/data cannot be sent
- test al,stWait
- loopnz apmcw_05
- jz apmcw_10 ; its available
-
- push ax ; The device is probably powered off, so
- call AP_reset ; we just have to kick it...
- pop ax ; AH holds the command/data byte
- jmp short apmcw_00
- ;
- apmcw_10:
- inc dx ; move to the control port
-
- mov al,WrSndCmd ; start the strobe
- out dx,al
-
- mov al,WrIdle ; end the strobe
- out dx,al
- Idledly
-
- pop cx
- ret
-
- AP_MCW endp
-
-
-
- /*\
- |*|----====< AP_MDR >====----
- |*|
- |*| Read a data byte from the Micro of FIFO
- |*|
- |*| Entry Conditions:
- |*| Data Available must have been checked before calling
- |*| this routine. It is assumed to be high.
- |*|
- |*| Exit Conditions:
- |*| AL holds something...
- |*| DX,AX modified
- |*|
- \*/
-
- AP_MDR proc
- push cx
-
- mov dx,[PortAddress]
- add dl,_CONTROL
-
- mov al,RdIdle ; go to read IDLE
- out dx,al
- Idledly
-
- mov al,RdSndData ; read the high nibble
- out dx,al ; start the strobe
-
- dec dx ; grab one nibble
- in al,dx ; from the status port
- mov ah,al ; save in AH!
-
- inc dx
- mov al,RdIdle ; swap nibbles
- out dx,al ; end the strobe
- Idledly
-
- dec dx
- in al,dx ; read the next nibble
-
- mov cl,WrIdle
- xchg ax,cx ; save the bytes, load WrIdle
-
- inc dx ; send H/W into write idle mode
- out dx,al
-
- xchg ax,cx ; get the bytes
-
- mov cl,4
- shr ah,cl ; this order makes for a
- shr ax,cl ; fast conversion
-
- pop cx
- ret
-
- AP_MDR endp
-
-
-
- /*\
- |*|----====< AP_MDW >====----
- |*|
- |*| Send a data byte out to the FIFO.
- |*|
- |*| Entry Conditions:
- |*| AL holds the data
- |*|
- |*| Exit Conditions:
- |*| AX = -1 if data is available, or 0
- |*| DX,AX modified
- |*|
- \*/
- public AP_MDW
- AP_MDW proc
- push cx
-
- mov ah,al ; save the command/data
- ;
- apmdw_00:
- mov dx,[PortAddress]
- add dl,_CONTROL
-
- mov al,WrIdle ; make sure its' idle
- out dx,al
- Idledly
-
- mov al,ah ; get the byte and write it out
- sub dl,_CONTROL ; move to the data port
- out dx,al ; load the data
-
- inc dx ; move to the status port
- sub cx,cx
- ;
- apmdw_05:
- in al,dx ; wait=1 when cmd/data cannot be sent
- test al,stWait
- loopnz apmdw_05
- jz apmdw_10 ; its available
-
- push ax ; The device is probably powered off, so
- call AP_reset ; we just have to kick it...
- pop ax ; AH holds the command/data byte
- jmp short apmdw_00
- ;
- apmdw_10:
- inc dx ; move to the control port
-
- mov al,WrSndData ; start the strobe
- out dx,al
-
- mov al,WrIdle ; end the strobe
- out dx,al
- Idledly
-
- pop cx
- ret
-
- AP_MDW endp
-
-
-
-
- /*\
- |*|----====< AP_SRQ_stat >====----
- |*|
- |*| Returns the status of Service Request
- |*|
- |*| Entry Conditions:
- |*| None.
- |*|
- |*| Exit Conditions:
- |*| Carry clear & AX = 0, wait
- |*| Carry set & AX = -1, service request is posted
- |*| DX,AX modified
- \*/
-
- public AP_SRQ_stat
- AP_SRQ_stat proc
- mov dx,[PortAddress]
- add dl,_CONTROL
-
- mov al,WrIdle ; Write Idle mode...
- out dx,al
- Idledly
-
- dec dx ; mov to the status port
-
- in al,dx ; data rdy is high for data available
- and al,stSRQ
-
- neg al ; set carry if non-zero
- sbb ax,ax ; if data is available, return -1 & Cy
- ret ; else return 0 & NC
-
- AP_SRQ_stat endp
-
-
-
- /*\
- |*|----====< AP_FM_out >====----
- |*|
- |*| Send index/data out to the parallel FM chip
- |*|
- |*| Entry Conditions:
- |*| AL holds the index
- |*| AH holds the data
- |*|
- |*| Exit Conditions:
- |*| None
- |*| DX,AX modified
- \*/
-
- public AP_FM_out
- AP_FM_out proc
- push cx
- push ax ; save the index/data
- ;
- apfmo00:
- mov dx,[PortAddress]
- add dl,_CONTROL ; move to the status port
-
- mov al,WrFMIdle ; go into FM Mode
- out dx,al
- Idledly
-
- dec dx ; move back to status
- sub cx,cx ; loop control
- ;
- apfmo05:
- in al,dx
- test al,stWait ; FM wait high?
- loopnz apfmo05 ; yes, dont write it
- jz apfmo10 ; its available
-
- call AP_reset ; The device is probably powered off, so
- jmp short apfmo00 ; we just have to kick it...
- ;
- apfmo10:
-
- pop ax ; get the index and data
- jnz apfmobad ; bomb out if we cant do it
-
- dec dx ; move to the data port
- out dx,al ; load the data port
-
- inc dx ; move to the control register
- inc dx
-
- mov al,WrFMAddr
- out dx,al ; start the strobe
-
- mov al,WrFMIdle
- out dx,al ; end the strobe
- Idledly
-
- mov al,ah
- sub dl,_CONTROL ; move to the data port
- out dx,al ; load the data port
-
- add dl,_CONTROL
- mov al,WrFMData
- out dx,al ; start the strobe
-
- mov al,WrFMIdle
- out dx,al ; end the strobe
- Idledly
-
- mov al,WrIdle
- out dx,al ; back to write idle...
-
- ;
- apfmobad:
- pop cx
- ret
-
- AP_FM_out endp
-
-
-
- /*\
- |*|----====< AP_FM_in >====----
- |*|
- |*| Read the FM status register
- |*|
- |*| Entry Conditions:
- |*| None
- |*|
- |*| Exit Conditions:
- |*| AL holds the status byte
- |*| DX,AX modified
- \*/
-
- AP_FM_in proc
- mov dx,[PortAddress]
- add dl,_CONTROL ; point to control port
-
- mov al,WrIdle ; make sure we're idle
- out dx,al
- Idledly
-
- mov al,RdFMIdle ; go into FM Mode
- out dx,al
- Idledly
-
- mov al,RdFMStat ; clock in the data
- out dx,al
-
- dec dx ; move to the status port
- in al,dx
- mov bl,al ; save the high nibble
-
- inc dx
- mov al,RdFMIdle ; all set
- out dx,al ; strobe address
- Idledly
-
- dec dx
- in al,dx ; clock in the data
- mov bh,al
-
- inc dx
- mov al,WrIdle ; go back to idle mode
- out dx,al
- Idledly
-
- mov cl,4
- shr bh,cl
- shr bx,cl
-
- mov al,bl
-
- ret
-
- AP_FM_in endp
-
-
-
-
-