ADSP - Interfacing DSP To AD1819
ADSP - Interfacing DSP To AD1819
Version 2.4A
John Tomarakos
ADI DSP Applications
10/12/99
AD1819
MIC1 0 dB/
MIC2 20 dB
16-bit
LINE PGA Σ∆ A/D
SYNTH Converter
Selector
CD
VID 16-bit
PGA Σ∆ A/D RESET#
PHONE_IN Converter
SYNC
AC LINK
BIT_CLK
G G G G G G
∑ A A A A A A SDATA_OUT
MV
HP_OUT_L M M M M M M
G 16-bit SDATA_IN
Tone Fat
L_OUT MV
Control
∑ ∑
Stereo
∑ ∑ ∑ ∑ ∑ A Σ∆ D/A
M Converter
MONO_OUT MV ∑
G 16-bit
Tone Fat
R_OUT MV
Control
∑ ∑
Stereo
∑ ∑ ∑ ∑ ∑ A Σ∆ D/A
M Converter
HP_OUT_R MV
A G=Gain
M A=Attenuate
M=Mute
PC_BEEP Oscillators
MV=Master Volume
XTALO
0. Introduction XTALI
The AD1819x (AD1819, AD1819A and AD1819B) SoundPort Codec is a fully compliant AC’97 Analog Front End that can be
used for processing or playback of analog signals in personal computers. Audio Codec '97 codecs are used on PC soundcards
and PC motherboard's to interface with an AC-97 digital controller/accelerator, or directly to the PC motherboard's 64-bit
microprocessor for 'native signal processing' support. With extended codec features that have been added to the baseline
AC'97 specification, the AD1819x can also be easily interfaced to an Analog Devices ADSP-21xx and ADSP-21xxx DSP, thus
providing additional flexibility of using the codec in an embedded low-cost audio application. The AD1819x can also provide a
V.34 compatible modem analog front-end by supporting modem sample rates and filtering.
This application note will describe the how to interface the low-cost 32-bit SHARC DSP, the ADSP-21065L, to up to three daisy
chained AD1819As per SPORT for use in an audio system. The DSP programming recommendations are also applicable to code
compatible SHARC processors such as the ADSP-21061/61L, ADSP-21062/62L ADSP-21060/60L and the ADSP-21160. Using
multiple AD1819s gives the DSP system designer more flexibility for capture and playback of 'CD-Quality' audio by providing 6
inputs channel and 6 output channels per SPORT for processing of multiple audio signals concurrently. No additional
hardware glue-logic is required for daisy-chaining, and the programming of multiple AD1819s is easily accomplished through a
simple register command scheme. Single and multiple AD1819x driver source code examples are provided in the application note
for reference purposes. This source code was tested using the 21065L EZ-LAB Development Platform, which includes an
AD1819A as the analog interface. Triple-codec source was tested and verified using the SHARC EZ-LAB with the Triple
AD1819 MAFE board. Single codec drivers can serve as a basis for a dual or triple AD1819x codec interface requiring very little
modification of the driver to enable a multi-codec interface, due to the ability to broadcast similar commands to all AD1819s
through shared codec register address & register data timeslots. The latest revision of the AD1819 is the AD1819B. All
references to the AD1819 or AD1819x in this document refer to the AD1819A and AD1819B as well. The programming
recommendations in this document are also applicable to the AD1881, AD1881A, AD1882 and AD1885 (AC-97 rev 2.1
compliant codecs).
0.1 What The AD1819x Offers Above The Baseline AC-97 1.03 Specification
The AD1819 exceeds all AC'97 Version 1.03 Specifications and offers additional features that are useful for DSP interfacing.
Some of these include:
• Slot-16 DSP Serial Mode for DSP Serial Port Multichannel Mode (TDM) Compatibility.
This mode ensures that all serial port time-slots are 16 bits, allowing a much easier interface to 16-bit/32-bit DSPs that
support a TDM (time division multiplexed) interface. Slot-16 mode is useful since the TAG is always 16-bits and equal
length 16-bit slots eases to use of serial port 'autobuffering' of data, or 'DMA chaining', along with the SPORT's
Multichannel Mode TDM operation.
• Variable Sampling Rate Support On Both The Stereo Sigma-Delta ADCs and DACs
Variable sample rate allows you to 'record' and 'play back' audio signals at any sample rate from 7KHz to 48Khz in 1Hhz
increments with the use of two sample rate generator registers. The AD1819A can record and transmit ADC samples at
one rate and play back received DAC samples at another rate. The left ADC and DAC channels can also be programmed to
run at different rates as the right ADC and DAC channels. In addition to the 1Hz resolution the AD1819A also has a
method for running at irrational modem rates by use of the 8/7 and 10/7 bits. To go with these modem sample rates the
AD1819A has modem filters on the left channel. Please refer to our EE-Note #54 titled "How To Use AD1819A Variable
Sample Rate Support" for additional information (located at Analog's web site: www.analog.com).
a
a
SPORT1
ADSP-
AD1819A
21065L
Stereo
Line Out
Left/Right
Speakers
Stereo
1. AD1819x / ADSP-2106x SHARC DSP Serial Interface Overview
The AD1819x (AD1819, AD1819A, AD1819B) Serial Port functionality is very similar other Analog Devices SoundPort Codecs
like the AD1843 and AD1847. It’s interface can communicates with an AC’97 controller, DSP or ASIC in a time-division
multiplexed (TDM) mode, where codec register command/status information DAC/ADC data are received and transmitted in
different timeslots in a TDM frame. The AD1819 communicates with the AC’97 controller via a digital serial link, which is
referred to as the "AC-link."
The AD1819x incorporates a 5 pin digital serial interface that links it to the AC’97 controller. The pins assigned to the AD1819x
are: SDATA_IN, SDATA_OUT, SYNC, BIT_CLK and RESET#. All digital audio data and command/status information is
communicated over this point to point serial interconnection to the DSP. A breakout of the signals connecting the two is shown
in Figure 1. For a detailed description of the AC-link serial protocol between the DSP and the codec, the reader can refer to the
next section.
The AC-97 component specification defines digital serial connection known as an AC-Link, which is a bi-directional, fixed rate,
serial PCM digital stream. An AC'97-compatible codec handles multiple input and output audio streams, as well as command
register accesses employing a time-division-multiplexed (TDM) scheme. The baseline AC-link architecture divides each audio
frame into 12 outgoing and 12 incoming data streams, each with 20-bit sample resolution. The AD1819 also includes an
additional mode of operation, considered to be an Enhanced AC-link Protocol Extension, also referred to as SLOT-16 Mode.
This extension is very similar such that it also is also is a bi-directional, fixed rate, serial PCM digital stream. This Modified AC-
link divides each audio frame into 16 outgoing and incoming data streams, each 16-bits per slot. This allows low DSP software
overhead to transmit and receive data and thus enables a more simplified interface to an ADSP-21xx or ADSP-21xxx DSP. To
achieve this, the AD1819's SLOT-16 Mode of Operation will place all DAC/ADC and command/status Timeslots to 16-bits to
allow proper 16-bit TDM alignment for the DSP's serial port.
The AC-97 protocol could also be implemented with 18-bit or 20-bit DAC/ADC resolution with larger data word processors,
given the headroom that the AC-link architecture provides. This application note will only assume 16-bit data by placing the
AD1819x in SLOT-16 mode. As of this time, there is no performance benefit for using 18-bit or 20-bit words, since the use of the
larger 20-bit timeslots will not necessarily improve the dynamic range and SNR. Also, the tag phase is always 16-bits, so all
other larger word slots would be skewed relative to the DSP timeslot alignment. This would then require the DSP programmer to
use shift/extract/deposit instructions on all data coming after the 1st 16-bit slot so that proper memory and register alignment
occurs for all timeslot data. It is still possible to write a DSP driver that assumes 20-bit slots, although the DSP programmer
would have to use additional instructions to ensure that data is packed and sent out properly. A 16-bit DSP cannot easily
handle the additional headroom for 20-bit words, while a 32-bit DSP would have the overhead of packing and unpacking 20-bit
data after the initial 16-bit timeslot. Again, since there is no SNR benefit of using larger data word timeslot sizes, the use of the
AD1819 while not in SLOT-16 mode is not recommended for interfacing to a DSP TDM serial port as found in ADI's ADSP-21xx
and ADSP-2106x DSPs.
1.1 AD1819x (AD1819/A/B) "AC-Link" Serial Port Clocks And Frame Sync Rates
To keep clock jitter to a minimum, the AD1819x derives its clock internally from an externally attached 24.576 MHz crystal (as
required by the AC-97 specification), and drives a buffered and divided down (1/2) clock to the ADSP-2106x over AC-link under
the signal name BIT_CLK. The crystal frequency can be different, but it would no longer be AC-97 compliant since it also
affects actual value of the selected sample rate. Meeting AC-97 compliance is not necessary for embedded DSP designs (for
tips on using a different crystal frequency, refer to EE-Note #53 up on the Analog Devices Web Site: www.analog.com). Clock
jitter at the AD1819x DACs and ADCs is a fundamental impediment to high quality output, and the internally generated clock
provided the AD1819x with a clean clock that is independent of the physical proximity of the ADSP-2106x processor. BIT_CLK,
fixed at 12.288 MHz, provides the necessary clocking granularity to support 16, 16-bit outgoing and incoming time slots (12, 20-
bit outgoing and incoming time slots in normal AC-97 mode). AC-link serial data is transitioned on each rising edge of
BIT_CLK. The receiver of AC-link data, AD1819x for outgoing data and the ADSP-2106x for incoming data, samples each serial
bit on the falling edges of BIT_CLK. The AD1819x drives the serial bit clock at 12.288 MHz, which the ADSP-2106x then
qualifies with a synchronization signal to construct audio frames.
The beginning of all audio sample packets, or “Audio Frames”, transferred over the AC-Link is synchronized to the rising edge
of the SYNC signal. The SYNC pin is used for the serial interface frame synchronization and must be generated by the ADSP-
2106x AC-97 Controller. Synchronization of all AC-link data transactions is signaled by the ADSP-2106x via the RFSx signal.
SYNC, fixed at 48 kHz, is derived by dividing down the serial bit clock (BIT_CLK). The ADSP-2106x SHARC takes BIT_CLK (or
RCLKx/TCLKx in SHARC DSP equivalent terms) as an input and generates SYNC (RFSx) by dividing BIT_CLK by 256. This
yields a 48kHz SYNC signal whose period defines an audio frame, which is required to meet the AC-97 audio frame rate
requirement. The SYNC (RFSx) pulse is driven by the ADSP-2106x processor by programming the RFSDIV register in the DSP.
To generate a 48 kHz frame sync with an externally generated 12.288 MHz SCLK, the DSP must set a value of 255 (0x00FF) in the
RFSDIV control register.
The SDATA_IN and SDATA_OUT pins handle the serial data input and output of the AD1819x. Both the AD1819x’s
SDATA_IN and SDATA_OUT pins transmit or receive data on 12 different timeslots (in addition to the Tag Phase) per frame in
normal AC-97 mode, 16 different timeslots (1 Tag + 15 Data slots) in SLOT-16 mode. The AD1819x transmits data on every
rising edge of BIT_CLK (RCLKx/TCLKx) and it samples received data on the falling edge of BIT_CLK (RCLKx/TCLKx).
When the 48 kHz audio frame rate is not equivalent to the selected sample rate, then Valid Data Slot bits in the Tag Phase
timeslot as well as the DAC request bits in the AD1819's Serial Configuration Register are used to control the sample data
flow between the codec and the DSP. When the 48 kHz frame rate is equivalent to the converter sample rate, valid and request
bits can be ignored since they will always be 1s.
2. AD1819x/ADSP2106x “AC-Link” Digital Serial Interface Protocol
The AC-link protocol described by the AC’97 specification provides for a special 16-bit time slot (Slot 0, often called the 'TAG
Phase') wherein each bit conveys a valid tag for its corresponding time slot within the current audio frame. A “1” in a given bit
position of slot 0 indicates that the corresponding time slot within the current audio frame has been assigned to a data stream,
and contains valid data. If a slot is “tagged” invalid, it is the responsibility of the source of the data, (AD1819x for the input
stream, ADSP-2106x for the output stream), to stuff all bit positions with 0’s during that slot’s active time. In the source code
example in Appendix A, the ADSP-2106x processor ensures than invalid slots are stuffed with 0's.
SYNC can remain high for a total duration of 16 BIT_CLKs at the beginning of each audio frame, although for DSP interfacing,
the ADI DSP usually pulses a frame sync for approximately 1 BIT_CLK, which is also acceptable for the AD1819x. The first
timeslot portion of the audio frame is defined as the “Tag Phase”. The remainder of the audio frame is defined as the "Data
Phase."
Slot # 0 1 2 3 4 5 6 7 8 9 10 11 12
SYNC (RFSx)
Slot # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SYNC (RFSx)
OUTGOING TAG
CMD CMD PCM PCM PCM PCM PCM PCM RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD
ADR DATA LEFT RIGHT LEFT RIGHT LEFT RIGHT
STREAMS
INCOMING STATUS STATUS PCM PCM PCM PCM PCM PCM RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD
TAG LEFT RIGHT LEFT RIGHT
STREAMS ADR DATA LEFT RIGHT
Data Phase
Tag Phase
Figure 3. Modified AD1819x 'AC-97' Bi-directional Audio Frame Configured In SLOT-16 Mode
2.1 ADSP2106x / AD1819x Audio Output Frame (DTx to SDATA_OUT)
The audio output frame data streams correspond to the multiplexed bundles of all digital output data targeting the AD1819x
DAC inputs, and control registers. Each audio output frame can support up to 16, 16-bit outgoing data time slots (by default, it
is actually 12, 20-bit outgoing timeslots after the 16-bit slot 0 - the DSP must put the AD1819x into Slot-16 mode for SPORT
compatibility). Slot 0 is a special reserved time slot containing 16 bits, which are used for AC-link protocol infrastructure.
Within slot 0 the first bit is a global bit (SDATA_OUT slot 0, bit 15) which flags the validity for the entire audio frame. If the
“Valid Frame” bit is a 1, this indicates that the current audio frame contains at least one slot time of valid data. The next 12 bit
positions sampled by the AD1819 indicate which of the corresponding 12 time slots contain valid data. Note that in Slot-16
mode, bit positions 13, 14 and 15 are always assumed to be zero. In this way data streams of differing sample rates can be
transmitted across AC-link at its fixed 48 kHz audio frame rate. The timing diagram in Figure 4 illustrates the time slot based AC-
link protocol in Slot-16 Mode. Serial timings in Figure 4 can assume either the SHARC's SPORT0 or SPORT1 pins. For SPORT0
we use RFS0 as the frame sync, TCLK0 as the serial clock, and DT0/DT0A as the data transmit pin. These timings also apply to
SPORT1's RFS1 and DT1/DT1A pins, while the serial clock would correspond to TCLK1.
BIT_CLK(TCLKx)
Figure 4. AD1819x Audio Output Frame in SLOT-16 Mode - ADSP-2106x to AD1819x Data Path **
**Note: The timing in figure 4 differs from the standard AC-97 timing of 12 slots, 20 bits in length for the data phase portion of the audio frame. The timeslots are
set to 16 bits in length (SLOT16 Mode) by the ADSP-2106x during initial enabling of the DSP SPORT so that proper data alignment of TDM slots to occur. Also,
the frame sync generated by the DSP is not set for the duration of the Tag Phase, as described in the AC-97 spec and AD1819 data sheet. The DSP generates a
frame sync for approximately 1 serial clock cycle. However this does not affect the codec operation, since the codec samples the frame sync only for the first
cycle prior to transmission of the MSB of the Tag Phase timeslot. Setup and hold times on the AD1819 are relaxed enough to meet the SHARC RFSx external
generation timings listed in the ADSP-2106x data sheet.
A new audio output frame, shown in Figure 5, begins with a low to high transition of SYNC. SYNC is synchronous to the rising
edge of BIT_CLK. On the immediately following falling edge of BIT_CLK, the AD1819x samples the assertion of SYNC. This
falling edge marks the time when both sides of AC-link are aware of the start of a new audio frame. On the next rising of
BIT_CLK, the ADSP-2106x transitions SDATA_OUT into the first bit position of slot 0 (Valid Frame bit). Each new bit position
is presented to AC-link on a rising edge of BIT_CLK, and subsequently sampled by AD1819x on the following falling edge of
BIT_CLK. This sequence ensures that data transitions and subsequent sample points for both incoming and outgoing data
streams are time aligned.
AD1819 samples SYNC assertion here
SYNC RFSx
ADSP-2106x samples
first SDATA_OUT bit of
frame here
BIT_CLK TCLKx
SDATA_OUT Valid
Frame
slot(1) slot(2) DTx
End of previous
Audio Frame
SDATA_OUT’s composite stream is MSB justified (MSB first) with all non-valid slots’ bit positions stuffed with 0’s by the
ADSP-2106x. The DSP software can initialize the transmit DMA buffer to 0x0000s in the SPORT ISR. (Note that this is done in
the SPORT1 transmit and received interrupt service routines shown in Appendix A)
In the event that there are less than 16 valid bits within an assigned and valid time slot, the ADSP-2106x should always stuff all
trailing non-valid bit positions of the 16-bit slot with 0’s.
When mono audio sample streams are output from the ADSP-2106x, it is necessary that BOTH left and right sample stream time
slots be filled with the same data.
BIT_CLK (RCLKx)
Figure 6. Modified AC-link Audio Input Frame - AD1819x to ADSP-2106x Data Path **
**Note: The timing in figure 6 differs from the standard AC-97 timing of 12 slots, 20 bits in length for the data phase portion of the audio frame. The timeslots are
set to 16 bits in length (SLOT16 Mode) by the ADSP-2106x during initial enabling of the DSP SPORT so that proper data alignment of TDM slots to occur. Also,
the frame sync generated by the DSP is not set for the duration of the Tag Phase, as described in the AC-97 spec and AD1819 data sheet. The DSP generates a
frame sync for approximately 1 serial clock cycle. However this does not affect the codec operation, since the codec samples the frame sync only for the first
cycle prior to transmission of the MSB of the Tag Phase timeslot. Setup and hold times on the AD1819 are relaxed enough to meet the SHARC RFSx external
generation timings listed in the ADSP-2106x data sheet.
The audio input frame, shown in Figure 7, (data samples sent to the DSP from the AD1819x) begins with a low to high transition
of SYNC/RFSx. SYNC is synchronous to the rising edge of BIT_CLK/RCLKx. On the immediately following falling edge of
BIT_CLK, the AD1819x samples the assertion of SYNC. This falling edge marks the time when both sides of serial link are aware
of the start of a new audio frame. On the next rising of BIT_CLK, the AD1819x transitions SDATA_IN into the first bit position
of slot 0 (“Codec Ready” bit). Each new bit position is presented to AC-link on a rising edge of BIT_CLK, and subsequently
sampled by the ADSP-2106x on the following falling edge of BIT_CLK. This sequence ensures that data transitions, and
subsequent sample points for both incoming and outgoing data streams are time-aligned. The SDATA_IN’s composite stream
is MSB justified (MSB first) with all non-valid bit positions (for assigned and/or unassigned time slots) stuffed with 0’s by the
AD1819x. SDATA_IN data is sampled on the falling edges of BIT_CLK .
AD1819 samples SYNC assertion here
SYNC RFSx
BIT_CLK RCLKx
Codec
SDATA_IN Ready slot(1) slot(2) DRx
End of previous
Audio Frame
Prior to any attempts at putting the codec into operation the ADSP-2106x should poll the first bit in the audio input frame
(SDATA_IN slot 0, bit 15) for an indication that the AD1819x has gone “Codec Ready”. Below is example ADSP-2106x
Assembly Language Instructions to accomplish the 'Poll Codec Ready' task:
Once the AD1819x is sampled “Codec Ready” then the next 15 bit positions (in Slot-16) sampled by the ADSP-2106x indicate
which of the corresponding 15 time slots are assigned to input data streams, and that they contain valid data. There are several
sub-functions within AD1819x that can independently go busy/ready. The global “Codec Ready” bit indicates that at least one
of these sub-functions is available. It is the responsibility of the DSP to probe more deeply into the AD1819x register file to
determine which AD1819x subsections are actually ready.
In addition to polling the "Codec Ready" indicator bit, the Power-Down Control/Status Register is useful for monitoring
subsystem readiness. The DSP programmer can choose to poll the Power-Down Control/Status Register to wait for Reference
Voltage, Analog Mixer, DAC & ADC Section Stabilization after polling the Codec Ready Bit. This step would ensure that the
DSP will not modify codec registers until the conversion resources and analog circuitry have stabilized. This step is
recommended by the AC-97 1.03 specification, although the source code example in Appendix A does not perform this step,
since it was found the successful programming of the AD1819x was achieved after simply polling the "Codec Ready" indicator
bit.
3. Configuring The ADSP-21065L Serial Port MCM Interface
When interfacing the AD1819A codec to an ADSP-21065L SHARC processor, the interconnection between the 2 devices can be
through either SPORT0 or SPORT1. In the application code section of this document, SPORT1 is used in the example drivers
since the 21065L EZ-LAB makes use of SPORT1 for the codec interface.
Both the DSP and codec serial port shift data MSB first, and the AD1819A’s BIT_CLK frequency of 12.288 Mhz is less than the
SCLK maximum of 40 MHz for the 2106x. Therefore, the DSP’s CLKOUT frequency must be greater than 12.288 Mhz.
a
RX0a TX0a
RX0b TX0b
RFS0
RCK0
ADSP TFS0
TCK0
21065
RX1a TX1a
RX1b TX1b
RFS1 TFS1
RCK1 TCK1
SPORT0 SPORT1
Function A Chn B Chn A Chn B Chn
The ADSP-21065L Serial Ports have two transmit and receive data pins for both the transmit side and the receive side.
RFS1 SYNC
ADSP-21062 RCLK1 BIT_CLK
TX1 TCLK1
RX1
DR1 SDATA_IN AD1819
DT1 SDATA_OUT
SPORT DMA
Transfers 10 - 20K
• A 10-K to 20-K Ohm pull-down resister is recommended on the ADSP-2106x’s DTx (DT0 /
DT0A / DT1 / DT1A) line. The DTx lines on ADI's SHARC DSPs have a 50K internal pull-up,
which can cause the AD1819A to enter a test mode, referred to in the AC'97 spec. as ‘ATE
Factory Test Mode’. The pull-down is required to ensure proper codec serial operation.
• Since BIT_CLK is the master serial clock, the DSP's RCLKx and TCLKx signals are set up
for external generation, since they are slave (input) signals. To synchronize shifting of data
channels, the RCLKx and TCLKx pins are tied together to BIT_CLK.
• For 3.3 Volt Interfaces, the AD1819x output signals connected as inputs to the DSP must be
level-converted down from 5.0 Volts to 3.3 Volts (See Next Section 3.1).
3.1 ADSP-21065L - 3.3 V Level Shifting Considerations
The ADSP-21065L is a new derivative of the SHARC family that is targeted for low-cost/high-performance consumer oriented
applications. Since it is a 3.3 Volt part, the 5 Volt AC-link signals that the AD1819A provides will damage the driver pins on the
21065L serial port. Level-shifting of all input signals is recommended. All SPORT output signals that are inputs to the AD1819
do not need to be level shifted since the AD1819A will recognize 3.3 volts as a valid TTL high level. Also, all other 3.3 V
SHARC processors like the ADSP-21060L, ADSP-21062L and ADSP-21061L should level shift all input serial port signals.
Figure 10 below shows the interface between the AD1819A and the ADSP-21065L. ADI's new code and pin compatible AC-97
rev 2.01 parts, The AD1881/AD1881A/AD1882/AD1885, include 3.3 V digital I/O, removing the need for level shifting.
ADSP-21065L AD1819A
74LV125
DT0A SDATA_OUT
RFS0 SYNC
Note: The Second Generation pin-for-pin compatible AC-97 codecs, the AD188x series, have
3.3 Volt I/O capability on the digital portion of the chip, thus level shifting is not required
In order to facilitate serial communications with the AD1819A, the SPORT1 pin connections are configured as shown in Table 1
and Figure 9:
Table 1.
ADSP-21065L Pin: AD1819A Pin: Driven By:
RCLK1, TCLK1 BIT_CLK codec
RFS1 SYNC DSP
TFS1 ( unconnected ) ---------- ----------
DR1A SDATA_IN codec
DT1A STATA_OUT DSP
3.2 Figure 11. Block Diagram Of A 5V ADSP-2106x Serial Interface To 3 AD1819 Codecs
/RESET FLG2
SDATA_OUT DT0
SPORT0
SDATA_IN DR0
SYNC TFS0
BIT_CLK RFS0
AD1819 RCLK0
CS0
TCLK0 ADSP-2106x
MASTER CS1 DVDD
CHAIN_IN
CLOCK_OUT AC97 CONTROLLER
XTAL_OUT
XTAL_IN
Timeslots 3 & 4
24.576MHz
22pF NP0 22pF NP0
/RESET
SDATA_OUT
SDATA_IN
SYNC
BIT_CLK
AD1819
SLAVE 1 CS0
CS1
CHAIN_IN
CHAIN_CLK
XTAL_OUT
XTAL_IN
Timeslots 5 & 6
/RESET
SDATA_OUT
SDATA_IN
SYNC
BIT_CLK
AD1819
DVDD
SLAVE 2 CS0
CS1
CHAIN_IN
CHAIN_CLK
XTAL_OUT
XTAL_IN
Timeslots 7& 8
Slot # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
SYNC (RFS0)
OUTGOING TAG CMD CMD PCM PCM PCM PCM PCM PCM RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD RSRVD
ADR DATA LEFT RIGHT LEFT RIGHT LEFT RIGHT
STREAMS
Data Phase
Tag Phase
Figure 12. Timeslot Allocation For Multiple AD1819 Bi-directional TDM Audio Frame
3.3 SPORT DMA Channels And Interrupt Vectors
There are 8 dedicated DMA channels for both SPORT0 and SPORT1 on the ADSP-21065L. The IOP addresses for the DMA
registers are shown in the table below for each corresponding channel and SPORT data buffer. In multichannel mode, only
channels 0, 2, 4 and 6 are active, because the channel B pins are disabled in Multichannel Mode.
Each serial port has a transmit DMA interrupt and a receive DMA interrupt (shown in Table 7 below). With serial port DMA
disabled, interrupts occur on a word by word basis, when one word is transmitted or received. Table 7 also shows the interrupt
priority, because of their relative location to one another in the interrupt vector table. The lower the interrupt vector address, the
higher priority the interrupt. Note that channels A and B for the transmit and receive side of each SPORT share the same
interrupt location. Thus, data for both DMA buffers is processed at the same time, or on a conditional basis depending on the
state of the buffer status bits in the SPORT control registers.
Priority
Interrupt 1 Function
1
Interrupt names are defined in the def21065.h include file supplied
with the ADSP-21000 Family Visual DSP Development Software.
3.4 Serial Port Related IOP Registers
This section briefly highlights the list of available SPORT-related IOP registers that will need to be programmed when
configuring the SPORTs for Multichannel Mode. To program these registers, write to the appropriate address in memory using
the symbolic macro definitions supplied in the def21065l.h file (included with the Visual DSP tools in the /INCLUDE/
directory). External devices such as another 21065L, or a host processor, can write and read the SPORT control registers to set
up a serial port DMA operation or to enable a particular SPORT. These registers are shown in the table below. The SPORT
DMA IOP registers are covered in section 4.8. As we will see in the next section, many of the available registers shown below
need to be programmed to set up Multichannel Mode. These registers are highlighted in bold text.
In Multichannel Mode, the available SPORT data buffers that are active are the channel A registers (which are highlighted
below). It is these registers that are actually used to transfer data between the AD1819A and the DMA controller on the ADSP-
21065L. The DMA controller is used to transfer data to and from internal memory without any intervention from the core.
Program_SPORT1_Registers:
/* program sport0 receive control register */
R0 = 0x0F0C40F0; /* 16 chans, int rfs, ext rclk, slen = 15, sden&schen enabled*/
dm(SRCTL1) = R0; /* sport 0 receive control register */
/* sport1 transmit control register */
R0 = 0x001C00F0; /* 1 cyc mfd, data depend, slen = 15, sden & schen enabled */
dm(STCTL1) = R0; /* sport 0 transmit control register */
• The ADSP-21065L provides an internally generated 48 kHz frame sync (RFS1). It must be a 48 kHz frame rate since the
AC97 specified frame rate of the AD1819A is 48 kHz. Since the AD1819A serial clock is 12.288 MHz, a divide factor or 256
will produce a 48 kHz internally generated frame sync.
• No companding.
• Multichannel Mode - Length = 5 multichannel words enabled. This allows 1 AD1819A audio frame per ADSP-21065L
multichannel frame.
The chain pointer register (CPxxx) is used to point to the next set of TX and RX buffer DMA chaining parameters stored in
memory. SPORT DMA transfers for the AD1819A are initiated by writing the DMA buffer's memory address to the CPR1A
register for SPORT1 receive and CPT1A register for SPORT1 transmit. The transmit and receive SCHEN_A and SCHEN_B bits
in the SPORTx Control registers enable DMA chaining.
To auto-initialize repetitive DMA-chained transfers, the programmer needs to set up a buffer in memory called a Transfer
Control Block (TCB) that will be used to initialize and further continue the chained DMA process. Transfer Control Blocks are
locations in Internal Memory that store DMA register information in a specified order. For example, Figure 13 below
demonstrates defined TCBs in internal memory for SPORT1 Channel A. The Chain Pointer Register (CPR1A and CPT1A)
stores the location of the next set of TCB parameters to be automatically be downloaded by the DMA controller at the
completion of the DMA transfer, which in this case it points back to itself to repeat the same ‘
CR1A
DM(rcv1a_tcb + 5) DM(xmit1a_tcb + CT1A
The TCBs for both the transmit and receive buffers are can be defined in the variable declaration section of the DSP assembly or
C code. In the AD1819A initialization code shown in appendix A, the TCBs for SPORT1 channel A are defined as follows:
To setup and initiate a chain of SPORT DMA operations at runtime, the 21065L program can follow this sequence:
1. Set up SPORT transmit and Receive TCBs (transfer control blocks). The TCBs are defined in the data variable declaration
section of your code. Before setting up the values in the TCB and kicking off the DMA process, make sure the SPORT
registers are programmed along with the appropriate chaining bits required in step 2.
2. Write to the SPORT0 transmit and receive control registers (STCTL0 and STCRL0), setting the SDEN_A enable bit to 1 and
the SCHEN_A chaining enable bit to a 1.
3. Write the internal memory index address register (IIxxx) of the first TCB to the CPxxx register to start the chain. The order
should be as follows:
a) write the starting address of the SPORT DMA buffer to the TCBs internal index register IIxxx location (TCB
buffer base address + 7). You need to get the starting address of the defined DMA buffer at runtime and copy it
into this location in the TCB.
b) write the DMA internal modify register value IMxxx to the TCB (TCB buffer base address + 6). Note that this
step may be skipped if it the location in the buffer was initialized in the variable declaration section of your code.
c) write the DMA count register Cxxx value to the TCB (TCB buffer base address + 5). Also note that this step may
be skipped if it the location in the buffer was initialized in the variable declaration section of your code.
d) get the IIxxx value of the TCB buffer that was previously stored in step (a), set the PCI bit with a that internal
address value, and write the modified value to the chain pointer location in the TCB (TCB buffer base offset + 4).
e) write the same ‘PCI-bit-set’ internal address value from step (d) manually into that DMA channel’s chain pointer
register (CPxxx). At this moment the DMA chaining begins.
The DMA interrupt request occurs whenever the Count Register decrements to zero.
SPORT DMA chaining occurs independently for the transmit and receive channels of the serial port. After the SPORT1 receive
buffer (rx_buf) is filled with new data, a SPORT1 receive interrupt is generated, and the data placed in the receive buffer is
available for processing. The DMA controller will autoinitialize itself with the parameters set in the TCB buffer and begin to refill
the receive DMA buffer with new data in the next audio frame. The processed data is then placed in the SPORT transmit buffer,
where it will then be DMA’ed out from memory to the SPORT DT1A pin. After the entire buffer is transmitted from internal
memory to the SPORT circuitry, the DMA controller will autoinitialize itself with the stored TCB parameters to perform another
DMA transfer of new data that will be placed in the same transmit buffer (tx_buf).
Below are example assembly instructions used to set up the receive and transmit DMA buffers and Transfer Control Blocks for
SPORT1 Channel A, which is shown in the 21065L EZ-LAB example shown in appendix A. These values are reloaded from
internal memory to the DMA controller after the entire SPORT DMA buffer has been received or transmitted.
/* transmit buffer */
.var tx_buf[5] = ENABLE_VFbit_SLOT1_SLOT2, /* set valid bits for slot 0, 1, and 2 */
SERIAL_CONFIGURATION, /* serial configuration register address */
0xFF80, /* set to slot-16 mode for ADI SPORT compatibility */
0x0000, /* stuff other slots with zeros for now */
0x0000;
.endseg;
.segment /pm pm_code;
/*-------------------------------------------------------------------------*/
/* DMA Controller Programming For SPORT1 MCM Tx and Rx */
/* */
/* Setup SPORT1 for DMA Chaining: */
/*-------------------------------------------------------------------------*/
Program_DMA_Controller:
r1 = 0x0001FFFF; /* cpx register mask */
/* sport1 dma control tx chain pointer register */
r0 = tx_buf;
dm(xmit_tcb + 7) = r0; /* internal dma address used for chaining */
r0 = 1;
dm(xmit_tcb + 6) = r0; /* DMA internal memory DMA modifier */
r0 = 5;
dm(xmit_tcb + 5) = r0; /* DMA internal memory buffer count */
r0 = xmit_tcb + 7; /* get DMA chain intn mem pointer containing tx_buf address */
r0 = r1 AND r0; /* mask the pointer */
r0 = BSET r0 BY 17; /* set the pci bit */
dm(xmit_tcb + 4) = r0; /* write DMA transmit block chain pointer to TCB buffer */
dm(CPT1A) = r0; /* transmit block chain pointer, initiate tx0 DMA transfers */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* - Note: Tshift0 & TX0 will be automatically loaded with the first 2 values in the -*/
/* - Tx buffer. The Tx buffer pointer ( IIT1A ) will increment twice by the modify -*/
/* - modify value specified in ( IMT1A ). -*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
.endseg;
3.8 AD1819A TDM Serial Port Time Slot Assignments, DMA Buffer Relationships
The DSP SPORT Multichannel Mode Time Slot Map for AD1819A communication in SLOT16 Mode is as follows:
• Operate the AC-link in SLOT-16 mode, all slots are 16-bits in length. This mode should be set as soon as the
codecs are fully functional.
• Set Codec Register Mask Bits for the Master Codec, Slave 1 Codec, or Slave 2 codec, thus allowing the DSP to
communicate to 1 codec at a time for setting/reading registers. Setting all 3 Mask bits will allow the DSP to program all
3 codecs at the same time.
• Set an enable bit that will force the Status Address and Data Slots (Slots 1 and 2) to display the contents of the
serial configuration by default. This will allow the host processor to read the DAC request bits to see if the codecs
are requesting data, which is required if the DACs are running at a slower rate or different rate than the ADCs.
74h Serial SLOT1 REGM2 REGM REGM0 DRQEN DLRQ DLRQ1 DLRQ0 X X X X X DRRQ2 DRRQ1 DRRQ0 X
Configuratio 6 1 2
n
If your system uses only a single AD1819, you can ignore the register mask and the slave 1/slave 2 request bits. If you write to
this register, write ones to all of the register mask bits. The DxRQx bits are read-only.
and stuffs DAC requests into LSB of output address slot (AC-Link Slot 1).
If you set the DRQEN bit, then the AD1819 will fill all otherwise- unused AC-link status address & data slots with the contents
of register 74h. That makes it somewhat simpler to access the information, because you don’t need to continually issue
Aclink read commands to get the register contents. Also, the DAC requests are reflected in Slot 1, bits (11….6).
The codec asserts the DxRQx bit when the corresponding DAC channel can accept data in the next frame. These bits are
snapshots of the codec state taken when the current frame began (effectively, on the rising edge of SYNC), but they also take
notice of DAC samples in the current frame.
4.1 Configuring The AD1819A Serial Link To SLOT-16 Mode For ADI SPORT Compatibility
Slot 16-Mode allows an efficient communication interface between DSPs and the AD1819A. Slot-16 mode is useful since the
TAG is always 16-bits and equal length slots eases to use of serial port autobuffering or DMA chaining. DSPs that support a
TDM interface usually do not provide the capability to program different slots to different word lengths. This mode ensures
that all 16 slots are 16-bits, allowing a much easier interface to 16-bit/32-bit DSPs. The DSP will generate a frame sync every 256
serial clock cycles, so instead of having 1 16 bit Tag Phase slot with 12, 20-bit slots, the AD1819A will generate 16, 16-bit slots in
256 serial clock cycles:
16 bit Tag Phase + (12 x 20-bit timeslots)= 256 bit clock cycles
now becomes,
16 bit Tag Phase + (15 x 16-bit timeslots) = 256 bit clock cycles
Note that the DSP will generate a frame sync every 256 serial clock cycles. With an SCLK running at 12.288 MHz, the DSP will
then produce the 48KHz frame sync in SLOT-16 mode.
To initially configure the AD1819A to conform to DSP TDM schemes, the DSP should initially program the AD1819s for 16-bit
slots as soon as the codec (or multiple codecs) are operational. A successful technique that is has been used by ADI's DSP
Applications Group is to initially fill up the SPORT transmit buffer with the register information to set the codecs in SLOT-16
mode. As soon as the DSP serial port operation is enabled and the codecs are reset and fully operational, the codecs will
respond to the DSP's repeated request to set up the AC-link to SLOT-16 mode. For example, the 21065L DSP codec driver
(shown in Appendix A) initially fills the tx_buf with the correct tag phase info, serial configuration address, and data to set the
codecs to SLOT-16 mode with all 3 codec register mask bits set. The buffer initialization is shown below:
Figure 14. Enabling SLOT16 Mode Immediately After DSP Sport TDM Operation Begins
Tag Phase Data Phase
Slot # 0 1 2 3 4 5 6 7 8 9 10 11 12
SYNC (RFS0)
SDATA_OUT (DT0) E000 7400F F8000
PCM PCM PCM
LEFT
PCM
RIGHT
PCM
LEFT
PCM
RIGHT
RSRVD RSRVD RSRVD RSRVD
LEFT RIGHT
CMD CMD
TAG
ADR DATA
74h Serial SLOT1 REGM2 REGM REGM0 DRQEN DLRQ DLRQ1 DLRQ0 X X X X X DRRQ2 DRRQ1 DRRQ0 X
Configuratio 6 1 2
n
Index 74h, Bit D12 (REGM0) enables Master AD1819 indexed address reads/writes
Index 74h, Bit D13 (REGM1) enables Slave 1 AD1819 indexed address reads/writes
Index 74h, Bit D14 (REGM2) enables Slave 2 AD1819 indexed address reads/writes
The table below shows the Mask bit selection label names used in the 2106x codec driver example. These labels can be used to
set the Serial Configuration Register for accessing registers on any of the 3 codecs. Whenever command register writes are sent
to address 0x74, the DSP can use 'SET BIT' instructions using these labels to set codec data bits D12, D13 and D14.
Note: The 21062/Triple AD1819A MAFE EZ-LAB Codec Driver assumes that all REGMx bits are set to enable broadcast
data writes to all codec indexed addresses. For the 21065L EZ-LAB Single AD1819A driver, only the Master REGM0 bit is
set.
Thus a write to a codec indexed command register will broadcast register data writes to all 3 codecs. Reading codec registers
will result in a logical OR'ing of the index register of all masked codecs. For example, with 3 codec mask bits set, reading any
given register address will result in data in all 3 registers being logically OR'ed together. When attempting a read of multiple
registers at the same time, the codec higher up in the chain will take precedence. For example, when reading a register from all 3
codecs, the value of the Master's requested register contents will be transmitted on the serial bus.
4.3 The AD1819A Serial Configuration Register Master And Slave DAC Request Bits
The Serial Configuration Register (Address 0x74), a Vendor Defined register by Analog Devices, includes support for
transmitting data to the DACs at different sample rates than the ADCs. For Variable Sample Rate support, Analog Devices
added DAC request bits to the AD1819A's Serial Configuration Register. This feature allows sample rate conversion to be done
in the AD1819A/DSP TDM interface itself, removing the burden from the DSP to have to include DSP interpolation or
decimation routines to change from one sample rate to another. AD1819A Variable Sample Rate Support is defined as follows:
The AD1819A is capable of sampling analog signals or converting digital signals from 7 kHz to 48 kHz in 1 Hz increments on
either the left and right ADCs and left and right DACs. Two sample rate generator registers are included in the AD1819A, and
either the left or right ADC and DAC channels can be assigned to either sample rate generated to sample or convert signals at a
desired sample rate. The normal AC-97 TDM protocol specifies a fixed 48 kHz sample rate, in which a valid sample is transmitted
or received every audio frame. Since the AD1819A can run at slower sample rates, there will not always be a valid sample in
every 48 kHz audio frame. If the application requires sample rate conversion, the DSP would need to know when a valid DAC
sample is requested from the AD1819A. For example, if the ADC sample rate is different than the DAC sample rate, the DSP
would need to know when to transmit DAC data only when the AD1819A needs a new DAC sample. To accomplish this, the
AD1819A's Serial Conversion Register Includes Left and Right DAC request bits (for the Master, Slave1 and Slave2 AD1819s)
so that it will notify the AC-97 host processor that it needs a new DAC sample in the next audio frame (based on it's modified 1-
Hz increment sample rate).
74h Serial SLOT1 REGM2 REGM REGM0 DRQEN DLRQ DLRQ1 DLRQ0 X X X X X DRRQ2 DRRQ1 DRRQ0 X
Configuratio 6 1 2
n
To activate the DAC request bit support (which by reset default is not in operation), the DSP driver must write to bit D11, the
DRQEN bit, in the Serial Configuration Register. Once enabled, the idle Status Address Timeslot (AC-Link Timeslot 1) will
always transmit the DAC requests into the Least Significant Bits of the Address Timeslot. The previously idle Status Data
Timeslot (AC-Link Timeslot 2) now will always contain the contents of the Serial Configuration Register 0x74. This makes it
much easier to access the DAC request bit information, because the DSP will not have to continually issue AC-link read
commands to get the DAC request bit contents from register 0x74. The DAC request bits for a single codec AD1819A system
should be inspected by looking at the DLRQ0 bit (bit D8, the Master codec DAC left request - Slot 3) for left channel sample
requests and the DRRQ0 (bit D0, the Master codec DAC right request bit - Slot 4) for right channel DAC sample requests.
The AD1819A asserts the DxRQx bit when the corresponding DAC channel can accept data in the next frame. These bits are
snapshots of the codec state taken when the current frame began (effectively, on the rising edge of SYNC), but they also take
notice of DAC samples in the current frame. If you choose to poll DAC requests in the Status Data Slot, these request bits are
ACTIVE HIGH. If you choose to poll DAC request in the Status Address Slot (Timeslot 1) while in SLOT-16 mode with
DRQEN enabled, these bits are ACTIVE LOW and should be inspected in the following locations in bits D7 - D2 (not D11 - D6,
which is true if we are in AC-97 mode). The bit ordering of the DAC request bits is as follows:
Status Address Slot Bit Assingments with DRQEN enabled (in any given audio frame, 0 = Request, 1=No Request):
Bit D15 Reserved (Stuffed with 0)
Bit D14 - D8 Control Register Index (when no codec commands in prior frame.. this always shows 0x74)
Bit D7 DLRQ0 - DAC Request Slot 3 - Master Codec Left
Bit D6 DLRQ0 - DAC Request Slot 4 - Master Codec Right
Bit D5 DLRQ1 - DAC Request Slot 5 - Slave1 Codec Left
Bit D4 DLRQ1 - DAC Request Slot 6 - Slave1 Codec Right
Bit D3 DLRQ2 - DAC Request Slot 7 - Slave2 Codec Left
Bit D2 DLRQ2 - DAC Request Slot 8 - Slave2 Codec Right
Bit D1 -D0 Reserved (Stuffed with 0s)
5. DSP Programming Of The AD1819A Indexed Control Registers
Addr. Index Register Name #define label in 2106x program Defined State Set By DSP?
0x00 Reset REGS_RESET 0x0400 N
0x02 Master Volume MASTER_VOLUME 0x0000 Y
0x04 Reserved RESERVED_REG_1 0xXXXX N
0x06 Master Volume Mono MASTER_VOLUME_MONO 0x8000 Y
0x08 Reserved RESERVED_REG_2 0xXXXX N
0x0A PC_BEEP Volume PC_BEEP_VOLUME 0x8000 Y
0x0C Phone Volume PHONE_VOLUME 0x8008 Y
0x0E Microphone Volume MIC_VOLUME 0x8008 Y
0x10 Line In Volume LINE_IN_VOLUME 0x8808 Y
0x12 CD Volume CD_VOLUME 0x8808 Y
0x14 Video Volume VIDEO_VOLUME 0x8808 Y
0x16 Aux Volume AUX_VOLUME 0x8808 Y
0x18 PCM Out Vol PCM_OUT_VOLUME 0x8808 Y
0x1A Record Select RECORD_SELECT 0x0404 Y
0x1C Record Gain RECORD_GAIN 0x0F0F Y
0x1E Reserved RESERVED_REG_3 0xXXXX N
0x20 General Purpose GENERAL_PURPOSE 0x8000 Y
0x22 3D Control THREE_D_CONTROL_REG 0x0000 Y
0x24 Reserved RESERVED_REG_4 0xXXXX N
0x26 Power-Down Control/Status POWER_DOWN_CNTL_STAT 0x000X N
0x28 Reserved RESERVED_REG_5 0xXXXX N
0x74 Serial Configuration SERIAL_CONFIGURATION 0xFF80 Y
0x76 Miscellaneous Control Bits MISC_CONTROL_BITS 0x0000 Y
0x78 Sample Rate 0 SAMPLE_RATE_GENERATE_0 0xBB80 Y
0x7A Sample Rate 1 SAMPLE_RATE_GENERATE_1 0xBB80 Y
0x7C Vendor ID1 VENDOR_ID1 0x4144 N
0x7E Vendor ID2 VENDOR_ID2 0x5300 N
** Registers highlighted in bold have been altered from their default states by the 21065L for the talkthru example. Other registers set by the DSP
that are not highlighted but marked with a Y are set to their default reset state and are user configurable. All other registers marked with a N are
not set by the DSP.
All indexed control registers that are used are initially set by the ADSP-21065L using a DSP memory buffer, where all register
addresses stored on even number memory buffer locations, and their corresponding register data stored at adjacent odd
numbered memory locations in the buffer. In our ADSP-21065L example, 17 registers are programmed during codec initialization.
An example assembly language buffer initialization is shown below:
.var Init_Codec_Registers[34] =
MASTER_VOLUME, 0x0000,
MASTER_VOLUME_MONO, 0x8000,
PC_BEEP_Volume, 0x8000,
PHONE_Volume, 0x8008,
MIC_Volume, 0x8008,
LINE_IN_Volume, 0x0000,
CD_Volume, 0x8808,
VIDEO_Volume, 0x8808,
AUX_Volume, 0x8808,
PCM_OUT_Volume, 0x0808,
RECORD_SELECT, 0x0404,
RECORD_GAIN, 0x0F0F,
GENERAL_PURPOSE, 0x8000,
THREE_D_CONTROL_REG, 0x0000,
MISC_CONTROL_BITS, 0x0000,
SAMPLE_RATE_GENERATE_0, 0xBB80,
SAMPLE_RATE_GENERATE_1, 0xBB80;
5.1 Programming AD1819A Registers Using A Zero Overhead Loop Construct
The following assembly language hardware DO LOOP shows how the values in the Init_Codec_Registers[ ] buffer are sent to
the appropriate slots on the Serial Port TDM bus:
Initialize_1819_Registers:
I4 = Init_Codec_Registers; /* pointer to codec initialization commands */
r15 = ENABLE_Vfbit_SLOT1_SLOT2; /* enable valid frame bit,and slots 1&2 val data bits */
• Slot 0 ( TAG Phase) is set up to enable the valid frame bit, slot 1 valid bit and slot 2 valid bit by writing a value of 0xE000 in
DM(tx_buf + 0)
• The Loop Counter Register LCNTR is set to the number of registers to be programmed. In this case 17 registers in all three
codecs will be set to the same value. For multiple codecs programmed to the same configuration, by initially filling tx_buf
with initialized Serial Configuration Register Data, we set up the codecs for SLOT16 mode with all three Codec Register
Mask bits set. So all three codecs will then respond to command register address and data writes.
• Memory writes to DM(tx_buf + 2) will send the register write data for the codec address specified in the previous timeslot.
• The IDLE instruction will allow you to do nothing but wait for a SPORT0 transmit interrupt after data has be placed in the
appropriate locations in the SPORT DMA buffer tx_buf. Waiting for the SPORT interrupt will guarantee that all data in the
transmit buffer has been shifted out on the TDM bus, thus telling us it is safe to go the next codec command register
address and register data value in the initialization buffer and transfer those contents in the 'transmit buffer' queue.
5.2 Readback Of AD1819A Registers For Verification And Debugging Using A Zero-
Overhead DO LOOP
There may be instances during the debugging stage of driver code, the DSP programmer may want to verify the desired values
of the AD1819A's internal registers. One easy way to do this is to set up an output buffer where all read requests of registers
can be stored after codec initialization. The readback and status of codec registers can also be done using a hardware loop.
The following assembly language instructions shown below are used to initiate codec read requests of registers shown in the
Init_Codec_Registers[ ] buffer, which is the name of the buffer used on our AD1819a driver. The results of the read requests
are then placed in an output buffer called Codec_Init_Results[ ], in which even DSP memory addresses contain the AD1819A
register address, and the DSP's odd address in the buffer contains the register data for the AD1819A address. On the 21065L
EZ-LAB, the AD1819A registers can then be verified with JTAG emulator or the VDSP RS232 debug monitor by setting a
breakpoint after this section of code and opening up the memory window that shows the values stored in the memory buffer.
After successful debugging of custom code these instructions can then be removed.
#define ENABLE_Vfbit_SLOT1 0xC000
#define TAG_PHASE 0
#define COMMAND_ADDRESS_SLOT 1
#define STATUS_ADDRESS_SLOT 1
#define STATUS_DATA_SLOT 2
/* Verify integrity of AD1819a indexed control register states to see if communication was
successful */
verify_reg_writes:
I4 = Init_Codec_Registers;
m4 = 2;
I5 = Codec_Init_Results;
r15 = ENABLE_Vfbit_SLOT1; /* enable valid frame bit, and slots 1 data bits */
• Slot 0 ( TAG Phase) is set up to enable the valid frame bit and slot 1 valid bit by writing a value of 0xC000 in DM(tx_buf + 0)
• The Loop Counter Register LCNTR is set to the number of registers to be read from the AD1819A. In this case 17 registers
in all 3 codecs will be set to the same value.
• Memory writes from DM(tx_buf + 1) will set a read request for the codec register address specified in the
Init_Codec_Registers[ ] buffer. Since we are modifying by two, we are only reading AD1819A register addresses from
thins input buffer, OR'ing in the read request bit #15 (the MSB) and transmitting the read request of the address in the TX
address timeslot.
• Two IDLE instructions are required to correctly readback the codec, since 1 TX audio frame is required to send the
readback request, and 1 rx audio frame is then required to send the contents of the register requested in the next audio
frame.
• Memory reads from DM(rx_buf + 1) will fetch the register read address
• Memory reads from DM(rx_buf + 2) will fetch the register read data for the codec address specified in the previous timeslot.
• The pointer I5 copies the register address and data in the Codec_Init_Results[ ] buffer for every read request. The
resulting buffer contents alternates with the codec addresses on even DSP addresses, and codec data for the
corresponding codec register address on odd DSP memory locations. This configuration is similar to that of the input
Init_Codec_Registers[ ] buffer, so the user can than easily compare the codec programming buffer to the codec read
results buffer.
6. Processing AD1819A Audio Samples via the SPORT Tx or Rx ISR
The 21065L’s SPORT1 Interrupt Vectors and Interrupt Service Routines can be used to process incoming information from the
up to 3 AD1819As through one serial port. As was described earlier in section 3.4, the information sent from the AD1819A is
DMA-Chained (i.e., the SPORT receives the entire block of AD1819A frame data before a SPORT interrupt occurs, and the DMA
settings are automatically reloaded to repeat the transfer of codec data) into the rx_buf[ ] buffer and an interrupt is generated
when the buffer is filled with new data. Therefore, when a RX interrupt routine is being serviced the data from all active receive
timeslots has been filled into the receive DMA buffer. When a TX interrupt routine is being services, the data from the DMA
buffer has been transferred out to the serial port. Output left and right samples, codec commands, and valid tag information are
filled into the transmit DMA buffer tx_buf[ ] for transmission out of SPORT. The programmer has the option of executing the
DSP algorithm from either the transmit DMA interrupt or the receive DMA interrupt.
Figure 15 below shows a high level logical view of the audio streams that can be processed when interfacing up to 3 AD1819s to
the SHARC DSP. With stereo ADCs and DACs on each codec, each SHARC serial port is capable of processing 6 input audio
channels and send DSP output audio streams to 6 output channels. This type of multiple codec configuration can find
applications in low-cost audio designs, such as implementation of a 6 x 2 channel digital mixing console, or provide a low-cost
solution for running surround algorithms requiring 6 channels for audio playback. With the use or both SPORT0 and SPORT1,
the ADSP-21065L can interface to up to 6 AD1819s, resulting in an audio system with 12 audio input and output channels.
Channel 1 ADSP-2106x
1 Channel 2
Daisy-Chained
Channel 3
AD1819
DSP
Analog Front Processing
End Channel 4
2
Channel 5
3 Channel 6
Using a DSP SPORT interrupt routine, the processor can detect if it has valid data from the codecs. The DSP's interrupt routine
can then send audio data from a given input channel to that channels processing algorithm and places results back to the
output channel stream (in the SPORT DMA buffer) for conversion by that AD1819A DAC. In this section we will investigate
methods for processing data from either the SHARC's SPORTx receive interrupt vector or transmit interrupt vector.
With AD1819A variable sample rate capabilities, it is possible to sample signals at one rate and playback the samples at another
sampling rate. The example codec driver in Appendix A shows how the DSP can test to see if valid data is coming the current
frame. For sampling rates less than 48 kHz, there will not always be valid data, so the DSP's SPORT audio processing ISR must
allow for early return from interrupt with no processing if no valid data is detected in the current frame. For example, running at a
8 kHz sampling rate would result in valid data coming in once every 6 frames (48KHz Frame Rate / 8 kHz sampling rate = 6), so
calls to DSP processing routines would be made every 1 out of 6 SPORT ISR calls.
For variable sample rate applications where there is not always a valid sample per audio frame, slot0 rx and tx valid TAG slot
bits and left/right channel data slot synchronization becomes more crucial and cannot be ignored by the programmer, due to
SPORT MCM & DMA timing relationships . For instance, the DSP TX interrupt routine may try to poll the L/R ADC valid bits
in the rx buffer while the valid left and right data has not yet been DMA'ed into the receive buffer. Another problem occurs
when processing audio in the SPORT's RX interrupt with only 5 slots/DMA words enabled. The DSP may try to set new tx valid
slot tag bits in the transmit DMA buffer for transmission, but the slot 0 data has already been DMA'ed to the SPORT TX
registers. So the tag slot information, instead of getting shifted out in the next audio frame, will remain in the tx DMA buffer and
will not be transmitted until the following frame. Since it will have been too late to write tx tag data to the to the transmit DMA
buffer because of these TDM, DMA and interrupt timing differences, the AD1819A will miss converting processed samples,
resulting in minor or severe audible distortion. However, there are a few tricks we will discuss in this section that will enable the
programmer to successfully write a variable sample rate codec driver. After extended testing and experimenting in search of the
most efficient driver implementations, we found using the SPORT TX interrupts to process data, when setting the codec to a
sample rate less than the default 48 kHz., resulted in the lowest the DSP's IOP bus bandwidth utilization. However, rx-based
processing with 16-word TX DMA buffers and 16 active TX TDM slots removes the restriction of having to read and write valid
tag information early in the SPORT receive interrupt service routine.
An example AD1819A audio service routine data flow sequence (this is the procedure actually used in our reference ADSP-
21065L codec drivers) for processing audio data in the SPORT1 transmit or receive ISR is shown below in Figure 16. This
diagram shows the flow of audio samples from the serial port registers, to the DMA buffers, and from there, the audio samples
are copied into temporary memory locations for a simple loopback, or to be used as inputs for the audio processing routines.
The output data is then copied from the output queue into the transmit DMA buffer, where it is then transferred to the SPORT
transmit data register for shifting out of the serial port. Again, the codec processing instructions can be serviced and executed
from either the transmit or receive interrupt vector. If we assume the ADCs/DACs run at the 48-kHz default sampling rate, there
is never a concern for TAG bit, ADC valid bit, and DAC request bit alignment. If all codecs are set to run at 48 kHz, then the
DSP SPORT1 receive ISR can skip testing of audio data since valid bits in the TAG for ADC data should always be 1's.
For SPORT TX and RX DMA chaining in TDM mode, the DMA interrupts are always at least two timeslots apart (See
Figure 17 below). This is because after the Transmit TCB is downloaded from memory and the reactivated SPORT transmit
DMA channel prepares for data transmission, the DMA controller initially places the first two words from the SPORT transmit
DMA buffer into the two SPORT1 TX buffer FIFO registers. This automatically decrements the Transmit DMA Count Register
by two. After the assertion of the TX chained-DMA interrupt, we would need to wait until the active RX chained-DMA transfer
brings in data for channels 3 and 4 for the current frame in which the rx ADC valid bits and DAC request bits are set, because
the Receive DMA Count Register is always delayed behind the Transmit DMA Count Register by a value of two.
So, before timeslot 0 even begins transmit/receive activity, the RX DMA Count = 5 while the TX DMA Count = 3 (assuming we
have declared 5-word TX and RX DMA buffers with 5 active rx and tx timeslots enabled on the serial port). The transmit
interrupt occurs when the TX DMA Count = 0, and this interrupt request occurs on the second DSP clock cycle immediately
after the LSB of timeslot 2 is received. While this transmit interrupt is generated, the transmit data for the left channel DAC
timeslot is currently shifting out of the SPORT's TX-shift register in slot 2, while the AD1819 right channel TX DAC data for
timeslot 4 is in the TX1A register queue, waiting to be transmitted after timeslot 2 data is finished shifting out of the SPORT. By
the time both the transmit and receive interrupts are latched in the current frame (after timeslot 4), the rx and tx TCBs will be
reloaded, but no DMA internal memory transfers will occur until the next frame sync, which would occur 11 time-slots later (with
the exception of the 1st two words in the TX buffer, which reload into the TX SPORT shift register and data buffer TX1A as the
previous channel 3 and 4 data shift out of the TX-shift register). After each reloading of the Transmit DMA TCB parameters,
the first two values from the TX DMA buffer are automatically reloaded into the tx-shift register and the TX data buffer after the
previous timeslots 3 & 4 data are shifted out of the SPORT TX-Shift register, but remain in the 'tx-queue' until the DSP generates
the next 48 kHz frame sync within 11 16-bit timeslots.
Figure 17. AD1819/SPORT Timeslot, DMA Count and RX & TX Interrupt Timing Relationships
__ __
RFS1 ___| |________________________________________________________________________| |_
DR1_A < SLOT0 >< SLOT1 >< SLOT2 >< SLOT3 >< SLOT4 > ----------//---------------
No activity on Slots 5 - 15
DT1_A < SLOT0 >< SLOT1 >< SLOT2 >< SLOT3 >< SLOT4 > ----------//---------------
No activity on Slots 5 - 15
CT1A 3 2 1 0 ß TX Interrupt Here
(DMA TX Count Reg) TX queue reloaded with 1 st two tx_buf values
as slots 3 and 4 are shifted out of SPORT1
One method for guaranteeing new left/right rx data in slots 3 and 4 will be available when entering the SPORT TX interrupt and
detecting corresponding ADC tag bits to be valid, is to implement a delay loop to simply wait for the data. This method is only
applicable if we have declared a SPORT1 TX DMA buffer size of 5 along with 5 active TDM channels enabled in the SPORT TX
multichannel enable register, equivalent in size to the SPORT1 RX DMA buffer and enabled rx channels. Immediately before
fetching the left and right ADC data a delay loop can be added to wait for the data. This can be coded as follows:
This delay loop is only required if the user needs to run at sample rates < 48 kHz with a 48 kHz frame rate and when processing
data from the TX interrupt while only declaring a TX DMA buffer size of 5 along with 5 TX TDM channels enabled.
It is estimated that while waiting for the left channel in slot 3, it takes 79 DSP Cycles at 60 MIPs. While waiting for the right
channel data in slot 4, it takes approximately 157 DSP cycles.
Because of the interrupt latency and previous instructions to this point, it was found using the 21065L EZ-LAB that a Loop
counter value of 126 guarantees enough time for the right channel data to be received.
This approach is probably not acceptable for most designs, but has been found to work for smaller audio applications. This is
definitely true if the programmer needs to include other background processing or interrupt routines that need to be executed
during this time. Thus this method is not the preferable method because of the loss in MIPs bandwidth (about 12% loss in
bandwidth utilization). The programmer can should instead try steps 2 and 3. The loss in bandwidth is estimated as follows:
(60 MIPs / 48 kHz AC-97 Audio Frame Rate) = 1250 DSP cycles to process data
DSP cycles - 150 = 1100 DSP cycles, or about 12% loss in available MIPs
An efficient implementation is to extend the TX DMA buffer size to 7 in length and enable 7 active TX TDM channels. This will
guarantee that by the time the DSP generates a TX DMA interrupt, the RX left and right data for the current frame have been
received in time before reading the samples. Slots 5 and 6 are dummy slots and never used. However, the advantage to this
implementation is that the DSP core is not held up waiting for the RX left and right channels to be DMA'ed into RX_BUF. (In
order to implement this method with the 21065L EZ-LAB RS232 Debugger, the programmer is required to run a SPORT1 register
clear routine to reset SPORT1 MCM and DMA activity… refer to Appendix A for an example SPORT1 register-clear routine)
Using this method, set the TX DMA buffer size and active MCM channels to 5, and then use both the SPORT1 tx and rx
interrupts to send/receive AD1819a audio data. Refer to alternate AD1819 reference code for this solution. ADC Valid Bits or
DAC Request Bits information can be passed from the SPORT receive ISR to the SPORT transmit ISR through a register or
variable stored in memory.
Recommended DSP Driver Settings:
.var rcv_tcb[8] = 0, 0, 0, 0, 0, 5, 1, 0; /* receive tcb */
.var xmit_tcb[8] = 0, 0, 0, 0, 0, 5, 1, 0; /* transmit tcb */
When using the TX ISR for audio processing or for transmitting output audio data to the AD1819A (using either methods 1, 2
or 3), the DSP programmer has approximately 75 DSP cycles (assuming 60 Mhz operation) upon entering the SPORT TX
ISR to write new tag information to the DM(TX_BUF + 0), which is the TX TAG phase slot, in order that our left and right
transmit data slots go out within the same audio frame as the TAG slot. If not done in time, the DSP would send data out in the
current frame, but the tag bits would get sent in the following frame. The DSP would then risk the dropping of samples, and
severe audible distortion results. The timing requirement for writing to the TX TAG location is estimated as follows:
Therefore, when processing data at slower sample rates < 48 kHz, it is recommended to use the SPORT TX interrupt to process
audio or transmit DAC data … but this is only required whenever you are using 5 or 7 word TX DMA buffer sizes. This reason
for using the TX ISR instead of the RX ISR in this situation is as follows: If we were to use the RX ISR for processing,
whenever the RX DMA interrupt occurs, the Tx TAG slot data in the top of the TX DMA buffer has already been loaded into
the TX1A register waiting for the next frame sync. Thus it would be too late to try to write to the TAG DMA buffer offset
because it has already been transferred by the DMA controller to the SPORT circuitry. This transfer would have occurred
approximately 1 timeslot, or 16 BIT_CLK cycles prior to entering the RX Interrupt Service Routine.
For fixed 48 kHz sample rate applications, the RX interrupt can still be used to process codec data and run a selected DSP
algorithm, since the RX and TX TAG bits and valid left/right data occur in every frame and will always be set. The programmer
therefore would not be concerned with polling ADC valid bits or DAC request bits. A ' one-audio-frame delay' would result in
the transmitting of the processed data, but in realtime the latency would be negligible. The DSP actually would be transmitting
left or right data that would correspond to the TAG bits set in the previous audio frame and ISR, which does not adhere to the
AC-97 specification. However, since the ADC valid bits and DAC valid bits are set, the programmer no longer is concerned with
carefully setting them at the appropriate time since these bits will always be set.
4. Use the RX Interrupt for Audio Processing
5-word RX DMA Buffer & 5 RX slots (0 - 4) enabled
16-word TX DMA Buffer & 16 TX Slots (0 - 15) enabled
This method will allow the DSP programmer to use the RX interrupt for audio processing, without having to install a TX ISR
jump or call routine at the SPORT TX interrupt vector after programming the AD1819A. Another benefit is that by processing
the data from the RX interrupt is that we guarantee that data has left and right TAG information and left and right data has been
received in a newly filled buffer, after the generation of the RX interrupt after the 5th slot (SLOT 4), while at the same time the TX
interrupt will continue to send dummy 'zero's in timeslots 5 - 15. This will ensure that there is plenty of time to write to the TX
TAG slot location DM(TX_BUF + 0) at any time in the DSP’s RX ISR audio processing routine, as long as it is done before the
completion of the transmission of SLOT14 TX data. After SLOT14 is transmitted, the ADSP-21065L will DMA the new TX TAG
data into the SPORT's TX1A register, while SLOT 15 begins to be shifted out of the SPORT T-shift register for SLOT15
transmission.
With this approach the DSP programmer can safely wait for a duration of 10 x 16-bit timeslots in the RX ISR before writing a new
value to DM(TX_BUF + 0), which will be transmitted in the following frame.
Therefore, the programmer has 778 DSP Instruction Cycles (assuming 60 MHz operation) within the 21065L SPORT RX Interrupt
Service Routine for which the DSP is required to write the new transmit TAG slot information into DM(TX_BUF + 0) so that it
correctly gets transmitted in the next audio frame. The advantage to this method is that the programmer is not restricted to
having to write to the TX Tag location in the beginning of the ISR. The drawback is that DSP requires more memory for the TX
DMA buffer, and DMA transfer overhead is increased from 5 or 7 transfers to 16 on the 21065L's IOP bus.
6.3 Using The 'Rx ADC Valid Bits' Method Or The 'DAC Request Bits' Method To Transmit
Processed Audio Data To The AD1819A DACs (For Variable Sample Rates < 48 kHz)
When processing the audio data in the SPORT's transmit or receive interrupt service routine, the programmer has the option to
either poll the ADC valid bits of the incoming data or the DAC request bits (in the Serial Configuration address 0x74) to
determine when to transmit processed audio data to the AD1819A DACs in the next audio frame. To prepare DAC data to
transmit in the next audio frame, the DSP's SPORT ISR instructions should simply include DM data transfers the appropriate
locations in the SPORT transmit DMA buffer, which in turn is transferred out of the serial port on the next TDM frame sync
assertion. The DSP's SPORT interrupt routine's codec-specific instructions either would poll the rx-ADC valid bits in the TAG
slot (slot 0), or poll the DAC request bits in either Slot1 or Slot2. If either the ADC valid bits are set or DAC requests are made,
the DSP then executes instructions to ensure that the tx TAG bits (slot 0) for the left and right DAC channels are set, since it will
place processed data in the left channel slot (slot 3) and the right channel slot (slot4). We will look at both methods and offer
advantages and disadvantages to using either method.
Figure 18 on the following page visually shows the 21065L SPORT transmit and receive DMA buffers at the point when the DSP
vectors off to the SPORT interrupt to process data. Typically, you would see this sort of display in the 65L RS232 VDSP
monitor debugger or JTAG VDSP EZ-ICE's 'two-column memory window'. Inspecting the contents of the SPORT receive DMA
buffer 'rx_buf' will give an indication if we have new ADC data. If these valid bits are set, then we ensure that corresponding
DAC channel data will be available in the SPORT transmit buffer for transmission in the following audio frame.
The newly-filled SPORT receive DMA buffer contains new data from previous audio frame. We see that the ADC valid bits for
slots 4 and 5 in the slot 0 Tag (or DM(rx_buf + 0)) are set as well as the Codec Ready bit D15, and valid data exists in slots 4,
DM(rx_buf +3), and 5, DM(rx_buf + 4). Slots 1 and 2 are 'Don't Care' conditions and ignored in this case. It will usually
contain the status of the last codec read, or if the DRQEN bit is set, these slots will display the contents of address 0x74, the
serial configuration register.
When the DSP ISR detects that there is valid data, it then calls the user's processing routine, or sets a flag to notify the
background task that there is new data to process. Thus, for slower sample rates less than 48 kHz, we will only execute our DSP
routine when the DSP detects valid data, and as a result, the DSP will only transmit DAC data when ADC data for that channel
was valid for the previous frame and current SPORT ISR. Now, in examining the contents of the Transmit DMA buffer in the
figure below, we see that new data is copied into the buffer and is transmitted on the next frame sync assertion as a result of
detecting valid data in the previous frame. Since there is valid ADC data in rx_buf[ ], the DSP ensures that the DAC valid Tag
bits for slots 3 and 4, as well as the ‘Valid Frame’ bit D15, are set in DM(tx_buf +0). The interrupt routine also places any
processed audio samples in Slots 3 and 4 for the Left and Right DAC channels. Unused slots are filled with zeros.
Figure 18. 'ADC Valid Bits' Method For Transmitting DAC Data In The Next Audio Frame
We will now examine some example 21065L Assembly Language Instructions incorporated in our 21065L SPORT Interrupt
Service Routine (listed in Appendix A), that show how to detect ADC valid bits and then set up the DAC slot tag bits for the
transmission of DAC data in the next audio frame if the ADC valid bits are set.
1) These instructions check if we have new ADC data from the TAG slot 0 by reading from DM(rx_buf + 0). Masking out that
value with 0x1800 tests the bit positions corresponding to slots 3 and 4:
check_ADCs_for_valid_data:
r0 = dm(rx_buf + TAG_PHASE); /* Get ADC valid bits from tag phase slot*/
r1 = 0x1800; /* Inspect for valid L/R ADC data */
r2 = r0 and r1; /* Mask other bits in tag */
dm(ADC_valid_bits) = r2;
2) We then quickly set the tx TAG bits for slots 3 and 4. This will either set the tx TAG bits for the left and right channel to zero
if no valid data, or we will set the DAC tag bits if the ADC valid bits were set, and thus we will be filling up the tx DMA buffer
locations 3 and 4 with new left and right channel DAC data:
set_tx_slot_valid_bits:
r1 = dm(tx_buf + TAG_PHASE); /* set tx valid bits based on ADC valid bits info */
r3 = r2 or r1; /* set left/right channel bits in tag, if required */
dm(tx_buf + TAG_PHASE) = r3; /* Write tag to tx-buf ASAP before it's shifted out
SPORT! */
3) Now that we set up the TX TAG bits, we save our current left and right channel data for processing. We will only save our
data whenever we detect that we have valid data. This is done by using the SHARC's shifter 'Bit Test' instruction, then testing
to see if the shifter result was zero. If it is zero, we have no valid data, so we move on. If the result was a '1', then we save our
newly detected sample. This is done as follows:
check_AD1819_ADC_left:
BTST r2 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
check_AD1819_ADC_right:
BTST r2 by M_Right_ADC; /* Check Master right ADC valid bit */
If sz rti; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
4) We then call our DSP algorithm. This can be conditionally called only if we have detected new audio data:
user_applic:
call DSP_Audio_Routine;
/* ---- DSP processing is finished, now playback results to AD1819 ---- */
5) After processing our ADC data, we now re-test the ADC valid bits to determine if we needed to send our results in the next
audio frame. If these bits are set to a '1', we copy our results to the left and right DAC channels to slots 3 and 4 in the SPORT1
transmit DMA buffer, where it will await transmission to the AD1819A DACs through the AC-link.
Playback_audio_data:
/* Transmit Left and Right Valid Data every time there the ADCs have valid data */
r2 = dm(ADC_valid_bits);
tx_AD1819_DAC_left:
BTST r2 by M_Left_ADC; /* Check to see if we need to send DAC right sample */
IF sz JUMP tx_AD1819_DAC_right; /* If valid data then transmit DAC sample */
r15 = dm(Left_Channel_Out);/ /* get channel 1 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + LEFT) = r15; /* output right result to AD1819a Slot 3 */
tx_AD1819_DAC_right:
BTST r2 by M_Right_ADC; /* Check to see if we need to send DAC right sample */
If sz jump tx_done; /* If valid data then transmit DAC sample */
r15 = dm(Right_Channel_Out); /* get channel 2 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + RIGHT) = r15; /* output right result to AD1819a Slot 4 */
Thus, the 'ADC Valid Bits' Method provides an easy and predictable way to transmit DAC data in the next audio frame. This
method usually yields clean audio without any Tag/Data/DMA timing issues that can cause distortion for sample rate values
less than 48 kHz. Ring buffers are not required for fractional sample rate ratios. There are limitations to using this method to
process audio data. The ADC and DAC channels (LADC/LDAC and RADC/RDAC) can only run at the same sample rates. You
cannot run both the ADCs and DACs at different rates unless the AD1819A's DAC request bits are polled. We will cover this
method in detail in the following section.
Figure 19 shown above visually shows the 21065L SPORT transmit and receive DMA buffers at the point when the DSP vectors
off to the SPORT interrupt to process data. As stated before, you would see this sort of display in the 65L RS232 VDSP
debugger or JTAG VDSP ICE's 'two-column memory window'. Inspecting the contents of the SPORT receive DMA buffer
'rx_buf' will give an indication if we have new ADC data, and if the AD1819A DACs are requesting data via the DAC request
bits. If these DAC request bits are set, then we ensure that corresponding DAC channel data will be available in the SPORT
transmit buffer for transmission in the following audio frame.
The newly-filled SPORT receive DMA buffer contains new data from previous audio frame. We see that the ADC valid bits for
slots 3 and 4 in the slot 0 Tag (or DM(rx_buf + 0)) are set as well as the Codec Ready bit D15, and valid data exists in slots 3,
DM(rx_buf +3), and 4, DM(rx_buf + 4). Slots 1 and 2 contain information on the DAC request bits through the automatic
display of the Serial Configuration Register (Codec address 0x74). This data is automatically displayed when the DRQEN bit is
set in this register.
When the DSP detects that there is valid ADC data (or when it detects the DAC request bits are set), it can call the user's
processing routine, or set a flag to notify the background task that there is new data to process. So the DSP programmer can
process data when either the ADC valid bits or DAC request bits are set in the current audio frame. Thus, for slower sample
rates less than 48 kHz, the DSP will only execute the DSP filter routine it detects valid data (or DAC requests), and as a result, it
will only transmit DAC data when ADC data for that channel was valid for the current audio frame SPORT ISR. Now, in
examining the contents of the Transmit DMA buffer in the figure above, we see that new data is copied into the buffer and is
transmitted on the next frame sync assertion as a result of detecting valid data in the previous frame. Since there is new valid
DAC requests for both the left and right channels in rx_buf[ ], the DSP will ensure that the DAC valid Tag bits for slots 3 and 4,
as well as the ‘Valid Frame’ bit D15, are set in DM(tx_buf +0). The interrupt services routine also places any processed audio
samples in Slots 3 and 4 for the Left and Right DAC channels. Unused slots are filled with zeros.
We will now examine some example 21065L Assembly Language Instructions incorporated in our SPORT Interrupt Service
Routine (listed in Appendix A) that show how to detect active DAC Request Bits, and then set up the transmit DAC data tag
slot bits for the transmission in the next audio frame:
1) These instructions are used to poll the "Active Low" L/R DAC Request bits via the Status Address Slot 1. We shift these
up by 5 bits, invert the values, so we can then used them to set the tx TAG bits for the left and right DAC timeslots 3 & 4.
Check_DAC_request_bits:
r1 = dm(rx_buf + STATUS_ADDRESS_SLOT); /* Get ADC request bits from address slot */
r2 = r1 and r0; /* Mask out the AD1819 Master DRRQ0 and DLRQ0 bits */
r2 = r2 xor r0; /* Set active low DAC request bits to active hi */
r2 = lshift r2 by 5; /* shift up so output tag info is bits 12 and 11 */
2) We then copy the shifted DAC request information to notify the AD1819 if slots 3 and 4 will contain valid data. If the bits
are set, then we will copy DAC data in the current ISR. This gets copied into the Tx Tag Phase Slot 0.
Set_TX_slot_valid_bits:
r0 = 0x8000; /* Write tag to tx-buf ASAP before it's shifted out! */
r2 = r2 or r0; /* set tx valid bits based on received DAC request info
*/
dm(tx_buf + TAG_PHASE) = r2; /* Set Valid Frame & Valid Slot bits in slot 0 tag phase
*/
3) We then poll the Rx Tag Slot 0 to see if we have new L/R ADC data and save the data if valid.
R0 = dm(rx_buf + TAG_PHASE); /* get tag information to inspect for valid L/R ADC data */
4) As we saw before with the 'ADC Valid Bits Method', if we detect valid data (bit value is a '1') we save our current left and/or
right channel data for processing. The bit validity is tested with the SHARC's barrel shifter:
check_AD1819_ADC_left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
check_AD1819_ADC_right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz jump user_applic; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
5) We then call our DSP algorithm. This can be conditionally called only if we have detected new audio data:
user_applic:
call (pc, DSP_Audio_Routine);
/* ---- DSP processing is finished, now playback results to AD1819 ---- */
6) After processing our ADC data, we now test the DAC Request bits to determine if we needed to send our results in the next
audio frame. If these bits are set, we copy our results to the left and right DAC channels to slots 3 and 4 in the SPORT1
transmit DMA buffer, where it will await transmission to the AD1819A DACs through the AC-link.
Playback_audio_data:
/* Transmit Left and Right Valid Data if Requested */
r2=DAC_Req_Left; /* Check to see if Left DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_left; /* if it is 1, it means we have no request, so move on*/
r15 = dm(Left_Channel_Out); /* get channel 1 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + LEFT) = r15; /* output right result to AD1819a Slot 3 */
bypass_left:
r2=DAC_Req_Right; /* Check to see if Right DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_right; /* if it is 1, it means we have no request, so move on*/
r15 = dm(Right_Channel_Out); /* get channel 2 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + RIGHT) = r15; /* output right result to AD1819a Slot 4 */
6.3.3 Single (Master) AD1819A ADC Valid / DAC Request Reference Charts
The Tables below can be used as a reference for inspecting ADC Valid Bits, DAC Request Bits and audio data during
debugging of a Single (Master) AD1819A Codec System:
Note: for single codec systems, the DAC request bits are zero'ed out for both the Slave1 and Slave2 bit locations. The AD1819A Master Codec
stuffs zeros in these bit locations. In the cases below (which were observed with the Target65L RS232 VDSP Debugger), Slot16 mode was enabled,
and all RegMx bits are set, even though there is only one master. Status Address Slot DAC Request Bits are 'Active Low'. Status Data Slot DAC
Request Bits are 'Active High'
Status Address Slot #1 for Single Codec System with L & R DAC requests, inactive '0' bits for slaves 1 & 2
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
0 1 1 1 0 1 0 0 0 0 X X X X 0 0
Dreq Dreq
Slot3 Slot4
'0' '0' '0' '0'
Status Data Slot #2 for Single Codec System with Left and Right DAC requests, inactive bits for slaves 1 & 2
D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0
1 X X 1 1 X X 1 X X X X X X X 1
Slot16 REGM2 REGM1 REGM0 DRQEN DLRQ0 DRRQ0
'0' '0' '0' '0' '0' '0' '0' '0' '0'
ADC Valid DAC Request Left Channel Right Channel è Tx Tag Slot 0 Left DAC Right DAC
Tag Bits Bits Timeslot 3 Timeslot 4 Timeslot 3 Timeslot 4
0x9800 0xXXXX Valid Data Valid Data 0x9800 Valid Data Valid Data
0x8800 0xXXXX Valid Data No Data 0x8800 Valid Data Zero Fill
0x9000 0xXXXX No Data Valid Data 0x9000 Zero Fill Valid Data
0x8000 0xXXXX No Data No Data 0x8000 Zero Fill Zero Fill
Rx Valid DAC Request Bits Left Channel Right Channel è Tx Tag Left DAC Right DAC
Tag Bits (slots 1 & 2 ) Timeslot 3 Timeslot 4 Timeslot 0 Timeslot 3 Timeslot 4
0xF800 [1] 0x7400 [2] 0xF901 Valid Data Valid Data 0x9800 Valid Data Valid Data
0xF800 [1] 0x7440 [2] 0xF900 Valid Data Valid Data 0x9000 Valid Data Zero Fill
0xF800 [1] 0x7480 [2] 0xF801 Valid Data Valid Data 0x8800 Zero Fill Valid Data
0xF800 [1] 0x74c0 [2] 0xF800 Valid Data Valid Data 0x8000 Zero Fill Zero Fill
0xF000 [1] 0x7400 [2] 0xF901 Valid Data No Data 0x9800 Valid Data Valid Data
0xF000 [1] 0x7440 [2] 0xF900 Valid Data No Data 0x9000 Valid Data Zero Fill
0xF000 [1] 0x7480 [2] 0xF801 Valid Data No Data 0x8800 Zero Fill Valid Data
0xF000 [1] 0x74c0 [2] 0xF800 Valid Data No Data 0x8000 Zero Fill Zero Fill
0xE800 [1] 0x7400 [2] 0xF901 No Data Valid Data 0x9800 Valid Data Valid Data
0xE800 [1] 0x7440 [2] 0xF900 No Data Valid Data 0x9000 Valid Data Zero Fill
0xE800 [1] 0x7480 [2] 0xF801 No Data Valid Data 0x8800 Zero Fill Valid Data
0xE800 [1] 0x74c0 [2] 0xF800 No Data Valid Data 0x8000 Zero Fill Zero Fill
0xE000 [1] 0x7400 [2] 0xF901 No Data No Data 0x9800 Valid Data Valid Data
0xE000 [1] 0x7440 [2] 0xF900 No Data No Data 0x9000 Valid Data Zero Fill
0xE000 [1] 0x7480 [2] 0xF801 No Data No Data 0x8800 Zero Fill Valid Data
0xE000 [1] 0x74c0 [2] 0xF800 No Data No Data 0x8000 Zero Fill Zero Fill
6.4 Processing Data At Fractional (Versus Integer) Variable Sample Rate Ratios Via The
'DAC Request Bits' Method
(I would like to offer thanks to Al Clark, of Danville Signal Processing, for his suggestions in using ring buffers to
process AD1819A data at fractional sample rate ratios)
The above methods work well at slower sample rates that are integer ratio values of 48 kHz. Methods 1 - 4 described section 6.2,
and in our source code examples in Appendix A, execute correctly for processing data set up for AD1819A sample rates of 16
kHz, 8 kHz, or 12 kHz. For example, when we program the AD1819A ADCs and DACs to run at a sample rate of 8 kHz, we expect
to receive a sample once every 6 frames and we are required (or requested by an AD1819a DAC request bit) to transmit data
once every 6 audio frames. For 16 kHz, we would expect to transmit or receive data once ever 3 frames, and at 12 kHz, once
every 4 audio frames. Normally for these even spacing of samples, we would not ever risk any sample overruns or underruns
because data will be evenly pipelined in and out of the DSP.
However, when running the AD1819A at fractional ratios of 48 kHz using the ADC valid bits to receive ADC data and the DAC
request bits to transmit DAC data, an occasional sample repeat or sample miss can occur. This is because received ADC valid
data and AD1819A DAC requests can be random relative to one another on the ADCs and DACs, for sample rates of, say, 23456
Hz, 8201 Hz, or 44100. When processing data in an interrupt service routine and polling the fetched ADC Valid Bits from the
receive TAG slot, we only execute our DSP routine every time we get valid ADC data. After processing the current valid
samples, we would normally place our results in the TX DMA buffer for the DACs to use when ready. The problem is, the
DACs may not have been requesting data via the AD1819A DAC request bits in the next audio frame, so we risk occasionally
drop a processed sample. Also, the ADC valid bits may not be set for a given frame, so no processing is done, but at the same
time, we could get two consecutive 'DAC request bit' audio frames. This then would result in repeating back a DSP output
sample twice, since the DSP algorithm was not processed in the current interrupt service routine. Keep in mind, this has nothing
to do with the 'REPEAT VS ZERO FILL SAMPLE' bit that is in the in the AD1819A's Miscellaneous Control Bits Register if the
DAC is starved. That functionality is for controlling the internal operation of the AD1819A DACs if the DSP did not send a
requested sample in a given frame. Of course, if the input ADC and output DAC sample rates are different, we would then
expect some ISR interpolation or decimation of samples to occur, in which we are repeating or skipping processed samples back
to the AD1819A output DACs from the processing routine because the DACs are running at a different sample rate than the
ADCs. Here, we are only concerned about the specific case where the ADCs sample rate is equivalent to the DACs, and we
want to ensure every new ADC sample is processed and all processed samples are sent back to the AD1819A.
For example, if we were to look at a scenario (Figure 20) where ADC Valid Bits being set at non-integer ratios of 48 kHz by the
AD1819A, while at the same time, DAC requests are made by the AD1819A DACs to keep DAC data filled at the same non-
integer sample rate ratio, we may see something like this:
Figure 20. Non-Periodic ADC Valid & DAC Request Bit Patterns
SYNC Pulse
|-|___________|-|____________|-|____________|-|_____________|-|____________|-|____________|-|___________
Frame N Frame (N+1) Frame (N+2) Frame (N+3) Frame (N+4) Frame (N+5) Frame (N+6)
ADC L/R Val. ADC L/R Val. No ADC val. ADC L/R Val. No ADC val. No ADC val. ADC L/R Val.
No DAC Req. No DAC Req. L/R DAC Req. L/R DAC Req. No DAC Req. L/R DAC Req. L/R DAC Req.
Left Ch. Data Left Ch. Data 0x0000 L Left Ch. Data 0x0000 L 0x0000 L Left Ch. Data
Right Ch. Data Right Ch. Data 0x0000 R Right Ch. Data 0x0000 R 0x0000 R Right Ch. Data
Note: 0x0000 L = No Data for left channel timeslot in current audio frame
0x0000 R = No Data for right channel timeslot in current audio frame
The AD1819A stuffs invalid slots with 'zeros'
Notice in Figure 20 above that in two consecutive audio frames, 2 L/R ADC valid bits may be set back-to-back, while 1 or 0 L/R
DAC request will be made in the same two audio frames. Another possible scenario that can occur is that for two consecutive
audio frames, 1 or 0 L/R ADC valid bits may be set while at the same time while 2 consecutive L/R DAC requests are made in the
same two audio frames. It is exactly these two cases that can occur when sample rates for the ADCs and DACs are set to
fractional ratios, such as 12345 Hz. This can cause 2 problems:
1) The DSP may process two consecutive ADC samples, and place the result in a holding register (in the case of our DSP
driver, these are variables in memory) waiting for the AD1819A DAC to request it, but if the DAC does not make a request,
then there is a possibility that that processed sample will be overwritten in the next audio processing interrupt routine.
2) The DSP may not receive ADC samples 1 or 2 ADC samples in a given frame, however the AD1819A DACs make two
consecutive DAC requests for the processed audio data waiting in the DSP's holding register (or variable in memory). In
this case there is a possibility that a processed sample will be transmitted to the DACs twice, before we are able to replace it
with an updated processed sample.
The solution for this 'equal ADC/DAC fractional sample rate ratio case' when using the 'DAC Request Bits' method is to use a
ring buffer. A ring buffer is a piece of allocated memory that is designed so that it's addressing of data periodically is allowed to
overflow (or underflow) to a certain predetermined number of locations. Ring buffers are often used to prevent sampling jitter in
sampling clocks, which can affect the quality of an audio signal. With the insertion of a ring buffer, the unpredictability of the
valid or requested data in a given audio frame between the ADCs and DACs are no longer affected. The memory buffer
increases the DSP's capturing of ADC data because sample frequency variations of the ADCs and DACs are absorbed by the
buffer. Valid AD1919A Left/Right DATA and AD1819A DAC request variations at fractional sample rates of 48 kHz can cause
the input and output data rate to vary independent in audio frames.
To ensure we have a smooth flow of data running at fractional ratios of 48 kHz, the programmer can implement a small ring buffer
(Figure 21) for the left and right channel to prevent an occasional sample repeat or miss when running at fractional rates. A
recommended scheme that has been found to work is to create one or two (depending on if we are performing mono or stereo
processing) small 4-word (or up to 8-word) ring buffers in the 'FETCH ADC DATA' and 'SEND DAC DATA' sections of the
AD1819A processing routine (see figure below). The small circular ring buffers are initialized such that the output pointer
offset the input pointer by 2 locations in memory. This would at least guarantee, for applications where the AD1819A ADCs are
set to the same fractional sample rate as the DACs, that the input pointer would never pass the output pointer, but may vary 1, 2
or 3 samples ahead from the output pointer. The effective delay will always be two samples, which means we would always be
between 1 to 3 '48-kHz' audio frames behind in getting an input sample into the DSP, and sending the result back out. This
delay, of course, in real-time processing is too negligible to affect the listener for real-time audio applications.
Figure 21. AD1819A DAC Left and Right Channel Ring Buffers
Below is an example ring buffer implementation for the left and right channels. Note that this code is not optimized. The
intermediate pointer states for the input and output are restored and saved using the same DAG index register I0, so that we are
not using 4 separate DAG index registers on the DSP to implement these ring buffers input and output taps. With some
additional overhead we only need to use one index register. The programmer can use a dedicated index register for each input
and output pointer if there are enough available for their application and then remove all memory pointer save and restore
instructions. Appendix A also includes ring buffer source code for use with the 'DAC Request Bits' Method.
.segment/dm dm_data;
.var Lchan_ring_buff[4] = 0, 0, 0, 0;
.var Rchan_ring_buff[4] = 0, 0, 0, 0;
.var L_input_ptr;
.var L_DAC_output_ptr; /* temporary storage of Index register */
.var R_input_ptr; /* this saves us from using 2 DAGs */
.var R_DAC_output_ptr;
.endseg;
-------------------------------------------------------------------------------------------------
.segment/pm pm_code;
/* initialize the ring buffer input and output pointers */
B0 = Lchan_ring_buff;
DM(L_input_ptr) = I0;
I0 = Lchan_ring_buff + 2; /* start output ptr in middle of the buffer */
DM(L_DAC_output_ptr) = I0;
B0 = Rchan_ring_buff;
DM(R_input_ptr) = I0;
I0 = Rchan_ring_buff + 2; /* start output ptr in middle of the buffer */
DM(R_DAC_output_ptr) = I0;
L0 = 4; /* both ring buffers are 4 words deep */
-------------------------------------------------------------------------------------------------
/* these instruction can be added in the AD1819A Interrupt Service Routines where codec data is received, processed and transmitted */
L0 = 4; /* input and output ring buffers are 4 words deep */
left_ring_buffer_input:
R1 = DM(rx_buf + LEFT_CHANNEL);
B0 = Lchan_ring_buff;
I0 = DM(L_input_ptr);
DM(I0,M1) = R1;
DM(L_input_ptr) = I0;
right_ring_buffer_input:
R1 = DM(rx_buf + RIGHT_CHANNEL);
B0 = Rchan_ring_buff;
I0 = DM(R_input_ptr);
DM(I0,M1) = R1;
DM(R_input_ptr) = I0;
left_ring_buffer_output:
B0 = Lchan_ring_buff;
I0 = DM(L_DAC_output_ptr);
R1 = DM(I0,M1);
DM(L_DAC_output_ptr) = I0;
DM(tx_buf + LEFT_CHANNEL) = R0
right_ring_buffer_output:
I0 = DM(R_DAC_output_ptr);
R0 = DM(I0,M1);
DM(R_DAC_output_ptr) = I0;
DM(tx_buf + RIGHT_CHANNEL) = R0;
.endseg;
NOTE:
Based on our ADI DSP Applications Group's 'loopback' listening tests for low distortion (i.e. clean audio) at fractional sample rate ratios using the 'ADC Valid Bits for
DAC transmission' Method, it was determined that the use of Ring Buffers is not really required. With this method of DAC transmission, a Left/Right DAC sample is
only transmitted in the next audio frame whenever we receive a new Left/Right ADC sample. This appears to properly pipeline input samples from the SPORT into the
21065L's DSP algorithm and back out of the SPORT without dropping (or rarely dropping) samples, because the AD1819A's Left and Right DAC 'conversion hold'
register will never be overwritten with a new value received through the AD1819A's serial interface while waiting to convert the previous DAC sample back to an
analog signal. With this alternate method, the 'valid' ADC L/R sample timeslots received in the previous frame with always ensure that the DSP will transmit 'valid'
L/R DAC timeslots to the AD1819A in the next audio frame.
Thus, the 'ADC Valid Bits' Method does not require the use of ring buffers when the ADC sample rate is equivalent to the DAC sample rate for both channels. When
the ADC and DAC sample rates are the same for a given channel, this results in the ADC valid bit patterns being identical to the DAC Tag L/R valid bits which are set
in the following frame. Since these Tag Bits are 'in phase', we never really run into a situation where a processed sample is skipped or repeated in the D/A
conversion.
6.5 Using RX ADC Valid Flag And TX DAC Valid Flag Variables For Processing Audio
Data At Variable Sample Rates
In certain applications, the user may want to process codec data elsewhere. For example, in C-based applications, the C-runtime
DSP routines may be placed in a main program 'while' loop waiting for SPORT interrupts. The codec interrupt service routine's
responsibility would be to receive and transmit codec data, while the processing of the data is done elsewhere. For slower
sample rates, the DSP processing routine would need to know which SPORT interrupt actually received valid data. The DSP
processing routine would also be responsible for notifying the codec transmit routine that it has valid processed data that can
be transmitted back to the DACs. In order to implement such a scheme, the user can define variables that can be used as
transmit and receive request flags that are set when data is ready, and cleared after the data has been transferred. For example,
the 21065L demo examples (Figure 22) use a dual buffer scheme, which allows the user to copy data into a temporary buffer
when the Rx Request variable has been set by the codec receive interrupt routine, while the DMA buffers are currently being
filled, the user processed data from alternate background buffers. After audio data is processed, the information is copied to the
transmit user buffer, and the Tx request variable is set. The codec processing routine detects that valid data is transferred into
the user output buffer, and copied the data into the SPORT transmit DMA buffer for transmission to the AD1819. It is the
responsibility of the DSP processing routine to clear any set rx flags after new ADC data has been processed and set any TX
flags when there is new processed data available for the codec ISR. It is the responsibility of the codec interrupt service routine
to set the RX flag for valid data received from the RX DMA buffer, or to clear the TX flag after transmit data has been copied to
the TX DMA buffer.
DMA
Tx Buffer
SPORT1
AD1819A
Codec
DMA
User Rx Buffer
Rx Buffer
Rx Request
The receive portion of the CODEC interface can be designed in a similar way. The DMA for SPORT1’s receive register is
configured to load the Rx DMA Buffer. When the RX Buffer is full, a SPORT interrupt is forced and the Rx Request variable is
set if there is valid ADC data. The DSP routine is conditionally called if the RX Request bit variable is set. If the variable > 0
then the contents of the RX Buffer is written into the User RX Buffer, and the RX Request is cleared. The DMA is reinitialized
to fill the RX Buffer again .
Assembly Language Rx Ready Flag Code Example For an 8 kHz ADC/DAC Sample Rate, with 48 kHz Frame Rate
The following example shows how the DSP routine and the Codec interrupt service routine would only process ADC data whenever there is new
ADC data available. The Codec ISR sets the rx flags whenever new ADC data is available. The DSP routine clears the rx flags after that data has
been processed. Since we are running at 8 kHz, the DSP routine would only be executed once out of every six interrupts, since:
48 kHz Audio Frame Rate / 8 kHz Sample Rate = 6 AC'97 Audio Frames Per Sample
.VAR RX_left_flag; /* DSP algorithm only processed when these bits are set */
.VAR RX_right_flag;
--------------
/* SPORT1 Rx Interrupt Service Routine . . . section where ADC data is received */
check_AD1819_ADC_left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_left_flag) = r4; /* if we have a new left sample, let the DSP routine know */
check_AD1819_ADC_right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz jump user_applic; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_right_flag) = r4; /* if we have a new right sample, let the DSP routine know */
--------------
/* DSP routine section where RX flag variables are cleared */
Echo: /* process both channel inputs */
/* get input samples from data holders */
r0 = dm(Left_Channel_In); /* left input sample */
r1 = dm(Right_Channel_In); /* right input sample */
r1 = ashift r1 by -1; /* scale signal by 1/2 for equal mix */
r2 = ashift r2 by -1; /* scale signal by 1/2 for equal mix */
r1 = r2 + r1; /* 1/2xL(n) + 1/2 xR(n) */
L6 = dm(delay_time);
/* put input sample into tap-0 of delay line,post-modify address after storage of input */
dm(i6, -1) = r1; /* put value from register r1 into delay line */
/* and decrement address by -1 */
r4 = 0;
dm(RX_left_flag) = r4; /* clear RX_left_flag since we have processed incoming data*/
dm(RX_right_flag) = r4; /* clear RX_rightflag since we have processed incoming data*/
rts; /* Return from Subroutine */
6.6 Processing 16-bit Data In 1.31 Fractional Format Or IEEE Floating Point Format
Data that is received or transmitted in the SPORT1 ISR is in a binary, 2's complement format. The DSP interprets the data in
fractional format, where all #s are between -1 and 0.9999999. Initially, the serial port places the data into internal memory in data
bits D0 to D15. In order to process the fractional data in 1.31 format, the processing routine first shifts the data up by 16 bits so
that it is left-justified in the upper data bits D16 to D31. This is necessary to take advantage of the fixed-point
multiply/accumulator's fractional 1.31 mode, as well as offer an easy reference for converting from 1.31 fractional to floating point
formats. This also guarantees that any quantization errors resulting from the computations will remain well below the 16 bit
result and thus below the AD1819A DAC Noise Floor. After processing the data, the DSP shifts the 1.31 result down by 16-bits
so that the data is truncated to a 1.15 number. This 1.15 fractional result is then sent to the AD1819A. Below are example
instructions to demonstrate shifting of data before and after the processing of data on the Master AD1819 left channel:
[Call Floating_Point_Algorithm]
REFERENCES
The following sources contributed information to this applications note:
1. ADSP-21065L SHARC User’s Manual, Analog Devices, Inc.,
(82-001833-01, Prentice-Hall, September 1998)
(We at Analog Devices express our sincere gratitude to Al Clark of Danville Signal Processing [email address:
[email protected]] for his contributions regarding the use of Ring Buffers to process AD1819A data at
fractional sample rates, along with his helpful hints in setting up the serial port DMA parameters for RX-
interrupt-based processing at variable sample rates)
7. ADSP-21065L / AD1819A DSP Driver Description
a a
SPORT1 ADSP-
AD1819A 21065L
Stereo
Line Out Left/Right
Speakers
Stereo
1. 21065L EZ-LAB System Initialization Routine (for SPORT1 Tx Interrupt Audio Processing)
2. AD1819A Initialization Routine (for SPORT1 Tx Interrupt Audio Processing)
3. How To Reset The AD1819A Via DSP Control With A Flag Out Pin
4. SPORT1 Clear Routine For Use With The Target65L RS232 / VDSP Debug Monitor
5. 21065L SPORT1 RX Interrupt Service Routine For Audio Processing Using The 'ADC Valid Bits' Method For DAC
Transmission
6. Installing A TX Interrupt Service Routine After Codec Register Initialization
7. Power Cycling The ADCs And DACs For Left/Right Sample Pair Synchronization With Variable Sample Rates Less
Than 48 kHz
8. Variable Sample Rate Tx Interrupt Service Routine For Audio Processing - 'ADC Valid Bits' Method For DAC
Transmission.
9. Variable Sample Rate Tx Interrupt Service Routine For Audio Processing - DAC Transmission Based On DAC Request
Bits with ADC/DAC Ring Buffers
10. Example Ring Buffer Implementation For The 'DAC Request Bits' Method
11. Variable Sample Rate Using Both The RX And TX Interrupts For Audio Processing, 'DAC Request Bits' Version
12. Example RX ISR For Three Daisy-Chained AD1819As
13. ADSP-21065L Interrupt Vector Table
14. Visual DSP (21065L EZ-LAB) Linker Description File.
The 21065L DSP example performs the following sequence of operations to establish AD1819A communications and process
audio data:
1. Initialize 65L DSP system stuff such as timers, flag pins, SDRAM, DAGs…
2. Initialize Serial Port 1 Registers
3. Program DMA Controller for Serial Port 1 Tx and Rx DMA chaining
4. Turn on Serial Port 1 and enable SPORT1 transmit interrupts
5. Reset the AD1819A (Optional, and required if RESET is tied to a DSP Flag Pin)
6. Wait for Codec to come 'on-line', and set up codec in Slot-16 Mode
7. Program desired AD1819A registers
8 Shut off SPORT1 transmit interrupts, enable SPORT1 receive interrupts
(only applies if processing audio data from the SPORT Rx Interrupt)
9. Start processing AD1819A audio data
C-Compiler-based Drivers
• Fixed 48 kHz, ADC Valid Bits Method, SPORT1 Receive Interrupt-based driver
• Variable Sample Rate, ADC Valid Bits Method, SPORT1 Transmit Interrupt-based, 7-word Tx DMA buffer & 7 TX Slots
Enabled, 5-word Rx DMA buffer & 5 Rx Slots Enabled
• Variable Sample Rate, ADC Valid Bits Method, SPORT1 Receive Interrupt-based, 16-word Tx DMA buffer & 16 TX Slots
Enabled, 5-word Rx DMA buffer & 5 Rx Slots Enabled
• Variable Sample Rate, ADC Valid Bits Method, both SPORT1 Transmit & Receive Interrupt-based, 5-word Tx DMA buffer &
5 TX Slots Enabled, 5-word Rx DMA buffer & 5 Rx Slots Enabled
• Variable Sample Rate, DAC Request Bits Method, both SPORT1 Transmit & Receive Interrupt-based, 5-word Tx DMA
buffer & 5 TX Slots Enabled, 5-word Rx DMA buffer & 5 Rx Slots Enabled
APPENDIX A:
Source Code Listing for 21065L EZ-LAB Audio
Driver (Visual DSP 4.x Project Files)
21065L EZ-LAB System Initialization Routine
(For SPORT1 TX ISR-based processing)
/*** INIT_065L_EZLAB.ASM **********************************************************
* *
* ADSP-21065L EZ-LAB Initialization and Main Program Shell *
* Developed using the ADSP-21065L EZ-LAB Evaluation Platform *
* *
* This routine contains function calls and routines to initialize the *
* state of the 21065L, program the DMA controller, initialize the AD1819a *
* and configure the SDRAM interface. DSP algorithm buffer initializations *
* are also called withing this routine. *
* *
* John Tomarakos *
* ADI DSP Applications Group *
* Revision 2.0 *
* 12/17/98 *
* *
***************************************************************************************/
.GLOBAL _main;
.GLOBAL Init_DSP;
.EXTERN Init_65L_SDRAM_Controller;
.EXTERN Blink_LEDs_Test;
.EXTERN Program_SPORT1_Registers;
.EXTERN Program_DMA_Controller;
.EXTERN AD1819_Codec_Initialization;
/*---------------------------------------------------------------------------*/
.SEGMENT/dm dm_data;
.var sine4000[4000] = "sinetbl.dat"; /* optional, used for generating sine tone to AD1819A DACs */
.global audio_frame_timer;
.var audio_frame_timer = 0; /* 48kHz timer variable */
.endseg;
/*---------------------------------------------------------------------------*/
.segment /pm pm_code;
wait_forever:
call wait_flag1;
bit tgl ustat1 0x3F; /* toggle flag 4-9 LEDs */
dm(IOSTAT)=ustat1;
jump wait_forever;
/*--------------------------------------------------------------------------------------------- *
* *
* Subroutines *
* *
*--------------------------------------------------------------------------------------------- */
wait_flag1:
/* wait for flag 1 button press and release */
if flag1_in jump wait_flag1; /* wait for button press */
release:
if not flag1_in jump release; /* wait for button release */
rts;
/*--------------------------------------------------------------------------------------*/
/* Note: This routine is first called at the Reset Vector in the Interrupt Vector Table */
/*--------------------------------------------------------------------------------------*/
Init_DSP:
/* code to blink flag 4 */
ustat1=0x3F; /* flags 4 thru 9 are outputs for LEDs */
dm(IOCTL)=ustat1;
bit set ustat1 0x3F; /* toggle flag 4-9 LEDs */
dm(IOSTAT)=ustat1; /* turn on all LEDs */
bit clr mode2 FLG2O | FLG1O | FLG0O; /* flag 3, 2 & 0 inputs */
Init_DAGs:
B1=sine4000;
L1=4000;
I1=sine4000;
M1=50;
B2=sine4000;
L2=4000;
I2=sine4000;
M2=40;
RTS;
.endseg;
AD1819A Initialization Routine (For SPORT Tx Interrupt Processing)
/*** AD1819a_initialization.ASM *********************************************
* *
* AD1819A/ADSP-21065L SPORT1 Initialization Driver *
* Developed using the ADSP-21065L EZ-LAB Evaluation Platform *
* *
* This version sets up codec communication for Variable Sample Rate *
* Support. After codec register programming, the ADCs and DACs are *
* powered down and back up again, so left/right valid bits and DAC *
* requests occur simultaneously in the same audio frame. *
* *
* For efficient handling of Tag bits/ADC valid/DAC requests, the codec *
* ISR is processes using the SPORT1 TX (vs RX) interrupt. The SPORT1 TX *
* interrupt is used to first program the AD1819A registers, with only *
* an RTI at that vector location. After codec initialization, the SPORT1 *
* TX ISR jump label is installed, replacing an 'RTI' instruction, so that *
* normal codec audio processing begins at that point. *
* *
* John Tomarakos *
* ADI DSP Applications Group *
* Revision 3.0 *
* 04/29/99 *
* *
*********************************************************************************/
.EXTERN spt1_svc;
.GLOBAL Program_SPORT1_Registers;
.GLOBAL Program_DMA_Controller;
.GLOBAL AD1819_Codec_Initialization;
.GLOBAL tx_buf;
.GLOBAL rx_buf;
.EXTERN Clear_All_SPT1_Regs;
#define AD1819_RESET_CYCLES 60
/* ad1819 RESETb spec = 1.0(uS) min */
/* 60(MIPs) = 16.67 (nS) cycle time, therefore >= 40 cycles */
.var Init_Codec_Registers[34] =
MASTER_VOLUME, 0x0000, /* Master Volume set for no attenuation */
MASTER_VOLUME_MONO, 0x8000, /* Master Mono volume is muted */
PC_BEEP_Volume, 0x8000, /* PC volume is muted */
PHONE_Volume, 0x8008, /* Phone Volume is muted */
MIC_Volume, 0x8008, /* MIC Input analog loopback is muted */
LINE_IN_Volume, 0x8808, /* Line Input analog loopback is muted */
CD_Volume, 0x8808, /* CD Volume is muted */
VIDEO_Volume, 0x8808, /* Video Volume is muted */
AUX_Volume, 0x8808, /* AUX Volume is muted */
PCM_OUT_Volume, 0x0808, /* PCM out from DACs is 0db gain for both channels */
RECORD_SELECT, Select_LINE_INPUTS, /* Record Select on Line Inputs for L/R channels */
RECORD_GAIN, Line_Level_Volume, /* Record Gain set for 0 dB on both L/R channels */
GENERAL_PURPOSE, 0x0000, /* 0x8000, goes through 3D circuitry */
THREE_D_CONTROL_REG, 0x0000, /* no phat stereo */
MISC_CONTROL_BITS, 0x0000, /* use SR0 for both L & R ADCs & DACs,repeat sample */
SAMPLE_RATE_GENERATE_0, Sample_Rate, /* user selectable sample rate */
SAMPLE_RATE_GENERATE_1, 48000; /* Sample Rate Generator 1 not used in this example */
.var Codec_Init_Results[34] =
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0;
.endseg;
/* -------------------------------------------------------------------------------------------- */
/* Sport1 Control Register Programming */
/* Multichannel Mode, dma w/ chain, early fs, act hi fs, fall edge, no pack, data=16/big/zero */
/* -------------------------------------------------------------------------------------------- */
Program_SPORT1_Registers:
/* This is required for disabling SPORT config for EZLAB RS232 debugger */
CALL Clear_All_SPT1_Regs; /* Clear and Reset SPORT1 and DMAs */
RTS;
/*------------------------------------------------------------------------------------ */
/* DMA Controller Programming For SPORT1 */
/*------------------------------------------------------------------------------------ */
Program_DMA_Controller:
r1 = 0x0001FFFF; /* cpx register mask */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* - Note: Tshift0 & TX0 will be automatically loaded with the first 2 values in the -*/
/* - Tx buffer. The Tx buffer pointer ( II3 ) will increment by 2x the modify value -*/
/* - ( IM3 ). -*/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
RTS;
/* -------------------------------------------------------------------------------------- */
/* AD1819A Codec Initialization */
/* -------------------------------------------------------------------------------------- */
AD1819_Codec_Initialization:
bit set imask SPT1I; /* enable sport0 x-mit interrupt */
Initialize_1819_Registers:
i4 = Init_Codec_Registers; /* pointer to codec initialization commands */
r15 = ENABLE_VFbit_SLOT1_SLOT2; /* enable v-frame bit, & slots 1&2 valid data bits */
LCNTR = 17, DO Codec_Init UNTIL LCE;
dm(tx_buf + TAG_PHASE) = r15 /* set valid slot bits in tag phase for slots 0,1,2 */
r1 = dm(i4, 1); /* fetch next codec register address */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r1; /* put codec register address into tx slot 1 */
r1 = dm(i4, 1); /* fetch register data contents */
dm(tx_buf + COMMAND_DATA_SLOT) = r1; /* put fetched codec register data into tx slot 2 */
Codec_Init: idle; /* wait until TDM frame is transmitted */
/*----------------------------------------------------------------------------------------------*/
/* Verify integrity of AD1819a indexed control registers to see if communication was successful */
/*--------------------------------------------------------------------------------------------- */
/* This section of codes is for debugging/verification of AD1819 registers. Theses */
/* instructions initiate codec read requests of registers shown in the Init_Codec_Registers */
/* buffer. The results of the read requests are placed in an output buffer called */
/* Codec_Init_Results, in which even DSP memory addresses contain the AD1819A register */
/* address, and the DSP's odd address in the buffer contains the register data for the */
/* AD1819A address.The AD1819A registers can then be verified with a JTAG emulator or the */
/* 65L RS232 VDSP debug monitor program. This section of code can be removed after debug. */
/*----------------------------------------------------------------------------------------------*/
verify_reg_writes:
i4 = Init_Codec_Registers;
m4 = 2;
i5 = Codec_Init_Results;
r15 = ENABLE_VFbit_SLOT1; /* enable valid frame bit, and slots 1 data bits */
LCNTR = 17, Do ad1819_register_status UNTIL LCE;
dm(tx_buf + TAG_PHASE) = r15; /* set valid slot bits in tag phase for slots 0,1,2 */
r1 = dm(i4,2); /* get indexed register address that is to be inspected */
r2 = 0x8000; /* set bit #15 for read request in command address word */
r1 = r1 OR r2; /* OR read request with the indirect register value */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r1; /* send out command address timeslot */
idle; /* wait 2 audio frames to go by, latency in getting data */
idle;
r3 = dm(rx_buf + STATUS_ADDRESS_SLOT);
dm(i5,1) = r3;
r3 = dm(rx_buf + STATUS_DATA_SLOT); /* fetch requested indexed register data */
dm(i5,1) = r3; /* store to results buffer */
ad1819_register_status:
nop;
/* For variable sample rate support, you must powerdown and powerback up the ADCs and DACs
so that the incoming ADC data and DAC requests occur in left/right pairs */
PowerDown_DACs_ADCs:
idle;
r15 = ENABLE_VFbit_SLOT1_SLOT2; /* enable valid frame bit, and slots 1&2 valid data bits */
dm(tx_buf + TAG_PHASE) = r15; /* set valid slot bits in tag phase for slots 0, 1 , 2 */
r0=POWERDOWN_CTRL_STAT;
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
r0=0x0300; /* power down all DACs/ADCs */
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
idle;
idle;
idle;
r15 = ENABLE_VFbit_SLOT1_SLOT2; /* enable valid frame bit, and slots 1&2 valid data bits */
dm(tx_buf + TAG_PHASE) = r15; /* set valid slot bits in tag phase for slots 0, 1 , 2 */
r0=POWERDOWN_CTRL_STAT; /* address to write to */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
r0=0; /* power up all DACs/ADCs */
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
idle;
idle;
/* ------------------------------------------------------------------------------------------- */
Install_ISR_SPORT1_Tx_ISR:
/* Use SPORT1 TX interrupt service function call for audio processing */
/* install the transmit interrupt function call to replace the initial RTI instruction */
/* "JUMP Process_AD1819_Audio_Samples" instruction into PX (0x063E 0000 xxxx). */
/* xxxx = address of Process_AD1819_Audio_Samples */
PX2 = 0x063e0000; /* Upper 32 bit Opcode for 'JUMP xxxx' instruction */
PX1 = Process_AD1819_Audio_Samples; /* Lower 16 bits of Opcode contain jump address */
PM(spt1_svc) = PX; /* copy to 0x34 - SPORT1 interrupt vect location */
/* ------------------------------------------------------------------------------------------- */
.endseg;
How To Reset The AD1819A Via DSP Control With A Flag Out Pin
The following code fragment demonstrates how to reset the codec through output flag control to fulfill the minimum AD1819A
reset and warm up requirements. This example was used with the AD1819 MAFE (on the SHARC 21062 EZ-LAB) to reset the
AD1819. Note that this code example assumes the use of a 33 MIPs SHARC DSP. For the 21065L, the #defines should be
modified to assume the use of 60 MHz.
#define AD1819_RESET_CYCLES 34
/* ad1819 RESETb spec = 1.0(uS) min */
/* 33.3(MIPs) = 30.0(nS) cycle time, therefore >= 33.3 cycles */
/* -------------------------------------------------------------- */
Reset_1819:
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* - ad1819a mafe pin assignments: - */
/* - FLAGOUT2 = RESETb = ad1819 reset - */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* CODEC Reset */
BIT CLR ASTAT FLG2; /* clear i/o flag #2 to assert RESETb pin */
LCNTR = AD1819_RESET_CYCLES-2 , DO rsetloop UNTIL LCE ;
rsetloop: NOP; /* wait for the min RESETb */
/* CODEC Warm-Up */
BIT SET ASTAT FLG2; /* set i/o flag #2 to deassert RESETb pin */
LCNTR = AD1819_WARMUP_CYCLES-2 , DO warmloop UNTIL LCE;
warmloop: NOP; /* wait for warm-up */
RTS;
SPORT1 Clear Routine For Use With The Target65L RS232 / VDSP
Debug Monitor
/* /////////////////////////////////////////////////////////////////////////////////////////
/ ROUTINE TO CLEAR AND RESET ALL SPORT1 REGISTERS /
/ This routine may be required for certaing AD1819A demos when using the 21065L EZ-LAB /
/ RS232 Debug Monitor program. The 21065L EZ-LAB boot EPROM Monitor kernel on power-up /
/ executes a routine that programs the SPORT1 Control and DMA registers to /
/ communicate with the AD1819A for the example supplied EZ-LAB demo programs. /
/ /
/ When invoking the 65L VDSP RS232 Debugger, SPORT1 DMA is already active in /
/ multichannel mode with DMA chaining. If we wish to leave the SPORT TDM and DMA /
/ channel configuration the same (i.e. 5 active channels and 5-word DMA buffers), /
/ we are usually still able to reprogram the DMA controller to point to our own /
/ own codec buffers with no side effects. However, if we need to change any SPORT /
/ control parameters such as the number of active TDM channels and DMA buffer sizes, /
/ then the active EPROM Monitor SPORT TDM configuration on powerup of the EZ-LAB board /
/ will affect the re-programming of the SPORT within a downloaded DSP executable. /
/ /
/ Since the monitor program has already activated the SPORT1 registers after a board /
/ reset, the side effect that occurs (when re-writing over the SPORT1 control /
/ registers) is that MCM DMA data transfers are mistakenly restarted /
/ without the full programming of all the SPORT parameters. Also, the TX and /
/ RX buffers may be partially full or full, and can affect the DMA controller's /
/ ability to correctly DMA in/out SPORT data to/from internal memory. What results /
/ is a failed link between the AD1819a and SPORT1 in user-modified code, because /
/ transmitted and received data is sent or received in different timeslots and misalign /
/ in the SPORT DMA buffers. /
/ /
/ This routine simply clears all SPORT1 ctrl and DMA registers back to their /
/ default states so that we can reconfigure it for our AD1819a application. /
/ /
/ John Tomarakos /
/ ADI DSP Applications /
/ Rev 1.0 /
/ 4/30/99 /
///////////////////////////////////////////////////////////////////////////////////////// */
Clear_All_SPT1_Regs:
IRPTL = 0x00000000; /* clear pending interrupts */
bit clr imask SPT1I;
R0 = 0x00000000;
dm(SRCTL1) = R0; /* sport1 receive control register */
dm(RDIV1) = R0; /* sport1 receive frame sync divide register */
dm(STCTL1) = R0; /* sport 0 transmit control register */
dm(MRCS1) = R0; /* sport1 receive multichannel word enable register */
dm(MTCS1) = R0; /* sport1 transmit multichannel word enable register */
dm(MRCCS1) = R0; /* sport1 receive multichannel companding enable register */
dm(MTCCS1) = R0; /* sport1 transmit multichannel companding enable register */
Receives MIC1 input from the AD1819A via SPORT0 and then transmits the audio data back out to the AD1819A Stereo DACs/Line Outputs.
This routine sends DAC data based on valid ADC data in a given audio frame.
This ISR version assumes the use of the default 48kHz pro audio sample rate, in which data is valid for every audio frame, if the tx and
rx DMA buffers are 5 words with 5 channels enabled on the TDM interface. Therefore, TAG slot info and ADC valid bit synchronization is
not as critical, since the tag bits and ADC valid bits are being set by the AD1819a and the DSP every time there is a new audio frame
(and thus a new interrupt) Therefore, the RX Interrupt can be used for audio processing after codec initialization. This makes it
somewhat easier to initialize the codec, while saving the user the extra overhead and code space for programming the codec to use it's
variable sample rate features. If the user wishes to use the RX interrupt for variable sample rates < 48 kHz, then the tx DMA buffer
should be 16 words, the DMA tx Count register equal to 16, and channels 0-15 enabled on the tx TDM interface, so that we have plenty of
time to write to the tx TAG slot.
JT
ADI DSP Applications
Rev 3.0
12/17/98
**************************************************************************************************************************************
Serial Port 1 Receive Interrupt Service Routine performs arithmetic computations on SPORT1 receive
data buffer (rx_buf) and sends results to SPORT1 transmit data buffer (tx_buf)
*****************************************************************************************************/
/* Left and Right ADC valid Bits used for testing of valid audio data in current TDM frame */
#define M_Left_ADC 12
#define M_Right_ADC 11
.GLOBAL Process_AD1819_Audio_Samples;
.GLOBAL Left_Channel;
.GLOBAL Right_Channel;
.EXTERN tx_buf;
.EXTERN rx_buf;
.endseg;
Process_AD1819_Audio_Samples:
r0 = 0x8000; /* Clear all AC97 link Audio Output Frame slots */
dm(tx_buf + TAG_PHASE) = r0; /* and set Valid Frame bit in slot 0 tag phase */
r0 = 0;
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
dm(tx_buf + LEFT) = r0;
dm(tx_buf + RIGHT) = r0;
Check_ADCs_For_Valid_Data:
r0 = dm(rx_buf + TAG_PHASE); /* Get ADC valid bits from tag phase slot */
r1 = 0x1800; /* Mask other bits in tag */
r2 = r0 and r1;
Set_TX_Slot_Valid_Bits:
r1 = dm(tx_buf + TAG_PHASE); /* frame/addr/data valid bits */
r3 = r2 or r1; /* set tx valid bits based on recieve tag info */
dm(tx_buf + TAG_PHASE) = r3;
Check_AD1819_ADC_Left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP Check_AD1819_ADC_Right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Left_Channel) = r6; /* save to data holder for processing */
Check_AD1819_ADC_Right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz RTI; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Right_Channel) = r6; /* save to data holder for processing */
/* ----------------------------------------------------------------------------------------------------- */
/* *** Insert DSP Algorithms Here *** */
/* */
/* Input L/R Data Streams - DM(Left_Channel) DM(Right_Channel) */
/* Output L/R Results - DM(Left_Channel) DM(Right_Channel) */
/* */
/* These left/right data holders are used to pipeline data through multiple modules, and */
/* can be removed if the dsp programmer needs to save instruction cycles */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Coding TIP: */
/* The samples from the AD1819A are 16-bit and are in the lower 16 bits of the the 32-bit */
/* word. They are shifted to the most significant bit positions in order to preserve the */
/* sign of the samples when they are converted to floating point numbers. The values are */
/* also scaled to the range +/-1.0 with the integer to float conversion */
/* (f0 = float r0 by r1). */
/* */
/* To convert between our assumed 1.31 fractional number and IEEE floating point math, */
/* here are some example assembly instructions ... */
/* */
/* r1 = -31 <-- scale the sample to the range of +/-1.0 */
/* r0 = DM(Left_Channel); */
/* f0 = float r0 by r1; */
/* [Call Floating_Point_Algorithm] */
/* r1 = 31; <-- scale the result back up to MSBs */
/* r8 = fix f8 by r1; */
/* DM(Left_Channel) = r8; */
/* ----------------------------------------------------------------------------------------------------- */
user_dsp_applic:
Power Cycling The ADCs And DACs For Left/Right Sample Pair
Synchronization With Variable Sample Rates < 48 KHz
/* For variable sample rate support, you must powerdown and powerback up the ADCs and DACs
so that the incoming ADC data and DAC requests occur in left/right pairs */
PowerDown_DACs_ADCs:
idle;
r15 = ENABLE_VFbit_SLOT1_SLOT2; /* enable valid frame bit, and slots 1&2 valid data bits */
dm(tx_buf + TAG_PHASE) = r15; /* set valid slot bits in tag phase for slots 0, 1 , 2 */
r0=POWERDOWN_CTRL_STAT;
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
r0=0x0300; /* power down all DACs/ADCs */
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
idle;
idle;
idle;
r15 = ENABLE_VFbit_SLOT1_SLOT2; /* enable valid frame bit, and slots 1&2 valid data bits */
dm(tx_buf + TAG_PHASE) = r15; /* set valid slot bits in tag phase for slots 0, 1 , 2 */
r0=POWERDOWN_CTRL_STAT; /* address to write to */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
r0=0; /* power up all DACs/ADCs */
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
idle;
idle;
/* Left and Right ADC valid Bits used for testing of valid audio data in current TDM frame */
#define M_Left_ADC 12
#define M_Right_ADC 11
#define DAC_Req_Left 0x80
#define DAC_Req_Right 0x40
.GLOBAL Process_AD1819_Audio_Samples;
.GLOBAL Left_Channel_In;
.GLOBAL Right_Channel_In;
.GLOBAL Left_Channel_Out;
.GLOBAL Right_Channel_Out;
.GLOBAL RX_left_flag;
.GLOBAL RX_right_flag;
.EXTERN tx_buf;
.EXTERN rx_buf;
.EXTERN fir;
.segment /dm dm_codec;
/* AD1819a stereo-channel data holders - used for DSP processing of audio data received from codec */
.VAR Left_Channel_In; /* Input values from AD1819A ADCs */
.VAR Right_Channel_In;
.VAR Left_Channel_Out; /* Output values for AD1819A DACs */
.VAR Right_Channel_Out;
.VAR Left_Channel; /* can use for intermediate results to next filter stage */
.VAR Right_Channel; /* can use for intermediate results to next filter stage */
.VAR RX_left_flag; /* DSP algorithm only processed when these bits are set */
.VAR RX_right_flag;
.VAR ADC_valid_bits;
.endseg;
Process_AD1819_Audio_Samples:
/* Build Transmit Tag Phase Slot Information */
r0 = 0x8000; /* Set Valid Frame bit 15 in slot 0 tag phase */
dm(tx_buf + TAG_PHASE) = r0; /* Write tag to tx-buf ASAP before it's shifted out SPORT! */
r0 = 0; /* Clear AC97 link Audio Output Frame slots for now */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
dm(tx_buf + LEFT) = r0;
dm(tx_buf + RIGHT) = r0;
check_ADCs_for_valid_data:
r0 = dm(rx_buf + TAG_PHASE); /* Get ADC valid bits from tag phase slot */
r1 = 0x1800; /* Inspect for valid L/R ADC data */
r2 = r0 and r1; /* Mask other bits in tag */
dm(ADC_valid_bits) = r2;
set_tx_slot_valid_bits:
r1 = dm(tx_buf + TAG_PHASE); /* set tx valid bits based on ADC valid bits info */
r3 = r2 or r1; /* set left/right channel bits in tag, if required */
dm(tx_buf + TAG_PHASE) = r3; /* Write tag to tx-buf ASAP before it's shifted out SPORT! */
check_AD1819_ADC_left:
BTST r2 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample, otherwise continue */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_left_flag) = r4; /* if we have a new left sample, let the DSP routine know */
check_AD1819_ADC_right:
BTST r2 by M_Right_ADC; /* Check Master right ADC valid bit */
If sz jump user_applic; /* If valid data then save ADC sample, otherwise continue */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_right_flag) = r4; /* if we have a new right sample, let the DSP routine know */
/* ------------------------------------------------------------------------------------------------------ */
/* user_applic( ) - User Applications Routines */
/* *** Insert DSP Algorithms Here *** */
/* */
/* Input L/R Data Streams - DM(Left_Channel_In) DM(Right_Channel_In) */
/* Output L/R Results - DM(Left_Channel_Out) DM(Right_Channel_Out) */
/* */
/* These left/right data holders are used to pipeline data through multiple modules, and */
/* can be removed if the dsp programmer needs to save instruction cycles */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Coding TIP: */
/* The samples from the AD1819A are 16-bit and are in the lower 16 bits of the the 32-bit */
/* word. They are shifted to the most significant bit positions in order to preserve the */
/* sign of the samples when they are converted to floating point numbers. The values are */
/* also scaled to the range +/-1.0 with the integer to float conversion */
/* (f0 = float r0 by r1). */
/* */
/* To convert between our assumed 1.31 fractional number and IEEE floating point math, */
/* here are some example assembly instructions ... */
/* */
/* r1 = -31 <-- scale the sample to the range of +/-1.0 */
/* r0 = DM(Left_Channel); */
/* f0 = float r0 by r1; */
/* [Call Floating_Point_Algorithm] */
/* r1 = 31; <-- scale the result back up to MSBs */
/* r8 = fix f8 by r1; */
/* DM(Left_Channel) = r8; */
/* ----------------------------------------------------------------------------------------------------- */
user_applic:
/* do audio processing on input samples */
r4 = 0x0; /* since we are not using the right flag, always clear */
dm(RX_right_flag) = r4; /* since left & right come in pairs at same fs rate, we
only need one flag (because we powered down ADCs for L/R sync).
Thus, the user can optionally remove the right flag set/clear
instructions to save cycles */
r4 = dm(RX_left_flag);
r4 = pass r4;
if eq jump playback_audio_data; /* if RX_left_flag = 1, then do audio processing */
/* filter routine will clear RX_left_flag */
do_audio_processing:
call (pc, fir);
playback_audio_data:
/* Transmit Left and Right Valid Data every time there the ADCs have valid data */
r2 = dm(ADC_valid_bits);
tx_AD1819_DAC_left:
BTST r2 by M_Left_ADC; /* Check to see if we need to send DAC right sample */
IF sz JUMP tx_AD1819_DAC_right; /* If valid data then transmit DAC sample */
r15 = dm(Left_Channel_Out); /* get channel 1 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + LEFT) = r15; /* output right result to AD1819a Slot 3 */
tx_AD1819_DAC_right:
BTST r2 by M_Right_ADC; /* Check to see if we need to send DAC right sample */
If sz jump tx_done; /* If valid data then transmit DAC sample */
r15 = dm(Right_Channel_Out); /* get channel 2 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + RIGHT) = r15; /* output right result to AD1819a Slot 4 */
tx_done:
r0=dm(audio_frame_timer); /* get last count */
rti(db); /* return from interrupt, delayed branch */
r0=r0+1; /* increment count */
dm(audio_frame_timer)=r0; /* save updated count */
/* ----------------------------------------------------------------------------------------- */
.endseg;
Variable Sample Rate ISR Using The TX Interrupt For Processing -
DAC Transmission Based On DAC Request Bits With Ring Buffers
/* **************************************************************************************************
/ /
/ AD1819A - SPORT1 TX INTERRUPT SERVICE ROUTINE /
/ /
/ Receives MIC1/Line input data from the AD1819A via SPORT1 and transmits processed audio data /
/ back out to the AD1819A Stereo DACs/Line Outputs /
/ /
/ This SPORT1 tx ISR version uses the DAC Request Bits to send and receive audio samples at /
/ different rates other than the default 48 kHz. Assuming the L/R ADCs and DACs are running /
/ at the same sample rate, we transmit a processed sample based on the DAC requests from the /
/ AD1819A while performing the processing based on the ADC valid bits. /
/ /
*****************************************************************************************************
/
This Serial Port 1 Transmit Interrupt Service Routine performs arithmetic computations on /
the SPORT1 receive DMA buffer (rx_buf) and places results to SPORT1 transmit DMA buffer (tx_buf) /
/
rx_buf[5] - DSP SPORT receive buffer /
Slot # Description DSP Data Memory Address /
------ -------------------------------------- ------------------------------------------------- /
0 AD1819A Tag Phase DM(rx_buf + 0) = DM(rx_buf + TAG_PHASE) /
1 Status Address Port DM(rx_buf + 1) = DM(rx_buf + STATUS_ADDRESS_SLOT) /
2 Status Data Port DM(rx_buf + 2) = DM(rx_buf + STATUS_DATA_SLOT) /
3 Master PCM Capture (Record) Left Chan. DM(rx_buf + 3) = DM(rx_buf + LEFT) /
4 Master PCM Capture Right Channel DM(rx_buf + 4) = DM(rx_buf + RIGHT) /
/
tx_buf[7] - DSP SPORT transmit buffer /
Slot # Description DSP Data Memory Address /
------ -------------------------------------- -------------------------------------------------- /
0 ADSP-21065L Tag Phase DM(tx_buf + 0) = DM(tx_buf + TAG_PHASE) /
1 Command Address Port DM(tx_buf + 1) = DM(rx_buf + COMMAND_ADDRESS_SLOT) /
2 Command Data Port DM(tx_buf + 2) = DM(rx_buf + COMMAND_DATA_SLOT) /
3 Master PCM Playback Left Channel DM(tx_buf + 3) = DM(rx_buf + LEFT) /
4 Master PCM Playback Right Channel DM(tx_buf + 4) = DM(rx_buf + RIGHT) /
5 Dummy Slot (Not Used) /
6 Dummy Slot (Not used) /
/
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* ADSP-21060 System Register bit definitions */
#include "def21065l.h"
#include "new65Ldefs.h"
/* Left and Right ADC valid Bits used for testing of valid audio data in current TDM frame */
#define M_Left_ADC 12
#define M_Right_ADC 11
#define DAC_Req_Left 0x80
#define DAC_Req_Right 0x40
.GLOBAL Process_AD1819_Audio_Samples;
.GLOBAL Left_Channel_In;
.GLOBAL Right_Channel_In;
.GLOBAL Left_Channel_Out;
.GLOBAL Right_Channel_Out;
.EXTERN tx_buf;
.EXTERN rx_buf;
/* AD1819a stereo-channel data holders - used for DSP processing of audio data received from codec */
.VAR Left_Channel_In;
.VAR Right_Channel_In;
.VAR Left_Channel_Out;
.VAR Right_Channel_Out;
/* AD1819 ADC/DAC ring buffer variables, may be required for Fractional Sample Rate Rations of 48 kHz*/
.VAR Lchan_ring_buff[6] = 0, 0, 0, 0, 0, 0;
.VAR Rchan_ring_buff[6] = 0, 0, 0, 0, 0, 0;
.VAR L_input_ptr; /* temporary storage of Index register, this saves us from using 4 DAG pointers */
.VAR L_DAC_output_ptr;
.VAR R_input_ptr;
.VAR R_DAC_output_ptr;
.VAR ADC_sample_test = 0x00000000;
.GLOBAL Lchan_ring_buff, Rchan_ring_buff, L_input_ptr, L_DAC_output_ptr, R_input_ptr, R_DAC_output_ptr;
.endseg;
Process_AD1819_Audio_Samples:
/* Build Transmit Tag Phase Slot Information */
r0 = 0x00c0; /* slots3 and slots 4 DAC REQ bit mask */
check_DAC_request_bits:
/* do not overwrite contents of r1, since it is required at the end of this interrupt! */
r1 = dm(rx_buf + STATUS_ADDRESS_SLOT); /* Get ADC request bits from address slot */
r2 = r1 and r0; /* Mask out the AD1819 Master DRRQ0 and DLRQ0 bits */
r2 = r2 xor r0; /* Set active low DAC request bits to active hi */
r2 = lshift r2 by 5; /* shift up so output tag info is bits 12 and 11 */
set_TX_slot_valid_bits:
r0 = 0x8000; /* Write tag to tx-buf ASAP before it's shifted out! */
r2 = r2 or r0; /* set tx valid bits based on received DAC request info */
dm(tx_buf + TAG_PHASE) = r2; /* Set Valid Frame & Valid Slot bits in slot 0 tag phase */
r0 = 0; /* Clear all AC97 link Audio Output Frame slots */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
dm(tx_buf + LEFT) = r0;
dm(tx_buf + RIGHT) = r0;
r0 = dm(rx_buf + TAG_PHASE); /* get tag information to inspect for valid L/R ADC data */
DM(ADC_sample_test) = r0; /* save for conditional ring buffer input storage */
check_AD1819_ADC_left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
check_AD1819_ADC_right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz jump user_applic; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
/* ------------------------------------------------------------------------------------------------------ */
/* user_applic( ) - User Applications Routines */
/* *** Insert DSP Algorithms Here *** */
/* */
/* Input L/R Data Streams - DM(Left_Channel_In) DM(Right_Channel_In) */
/* Output L/R Results - DM(Left_Channel_Out) DM(Right_Channel_Out) */
/* */
/* These left/right data holders are used to pipeline data through multiple modules, and */
/* can be removed if the dsp programmer needs to save instruction cycles */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Coding TIP: */
/* The samples from the AD1819A are 16-bit and are in the lower 16 bits of the the 32-bit */
/* word. They are shifted to the most significant bit positions in order to preserve the */
/* sign of the samples when they are converted to floating point numbers. The values are */
/* also scaled to the range +/-1.0 with the integer to float conversion */
/* (f0 = float r0 by r1). */
/* */
/* To convert between our assumed 1.31 fractional number and IEEE floating point math, */
/* here are some example assembly instructions ... */
/* */
/* r1 = -31 <-- scale the sample to the range of +/-1.0 */
/* r0 = DM(Left_Channel); */
/* f0 = float r0 by r1; */
/* [Call Floating_Point_Algorithm] */
/* r1 = 31; <-- scale the result back up to MSBs */
/* r8 = fix f8 by r1; */
/* DM(Left_Channel) = r8; */
/* ------------------------------------------------------------------------------------------------------ */
user_applic:
{call (pc, Audio_Algorithm);}
playback_audio_data:
/* Transmit Left and Right Valid Data if Requested */
r2=DAC_Req_Left; /* Check to see if Left DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_left; /* if it is 1, it means we have no request, so move on */
call (pc, left_ring_buff_out); /* if DAC req set, then get processed o/p from ring buffer */
r15 = dm(Left_Channel_Out); /* get channel 1 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + LEFT) = r15; /* output right result to AD1819a Slot 3 */
bypass_left:
r2=DAC_Req_Right; /* Check to see if Right DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_right; /* if it is 1, it means we have no request, so move on */
call (pc, right_ring_buff_out); /* if DAC req set, then get processed o/p from ring buffer */
r15 = dm(Right_Channel_Out); /* get channel 2 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + RIGHT) = r15; /* output right result to AD1819a Slot 4 */
bypass_right:
r0=dm(audio_frame_timer); /* get last count */
rti(db); /* return from interrupt, delayed branch */
r0=r0+1; /* increment count */
dm(audio_frame_timer)=r0; /* save updated count */
Example Ring Buffer Implementation For The 'DAC Request Bits'
Method
/* ---------------------------------------------------------------------------- */
/* Left/Right Channel Ring Buffers Routines, for sample rate jitter attenuation */
/* -------------------------------------------------------------------------- */
/* These ring buffers may be required when using the tx interrupt for audio */
/* processing and running at fractional sample rate rations of 48 kHz using */
/* the 'DAC Request Bits Method' to eliminate risk or repeating or dropping */
/* processed samples, resulting in a loss in signal quality. */
/* */
/* This method is not the most efficient, but only requires 1 index register */
/* for implementation instead of four. The user could also use any four */
/* available primary or secondary index registers to implement the ring */
/* buffers, and then remove the memory pointer save/restore instructions. */
/* ---------------------------------------------------------------------------- */
.EXTERN Lchan_ring_buff;
.EXTERN Rchan_ring_buff;
.EXTERN L_input_ptr;
.EXTERN L_DAC_output_ptr;
.EXTERN R_input_ptr;
.EXTERN R_DAC_output_ptr;
.EXTERN ADC_sample_test;
Init_Ring_Buffers:
/* initialize the ring buffer input and output pointers */
B0 = Lchan_ring_buff;
DM(L_input_ptr) = I0;
B0 = Rchan_ring_buff;
DM(R_input_ptr) = I0;
/* ///////////////////////////////////////////////////////////////////////////////////////////////// */
Sample_Jitter_Attenuator:
L0 = 6; /* input and output ring buffers are 6 words deep */
M0 = 1;
r9 = DM(ADC_sample_test);
BTST r9 by M_Left_ADC; /* Did we process a valid left sample in this ISR? */
IF sz JUMP right_ring_buff_in; /* If we did, store result to left ring buffer input */
left_ring_buff_in:
R0 = DM(Left_Channel_In);
B0 = Lchan_ring_buff;
I0 = DM(L_input_ptr);
DM(I0,M0) = R0;
DM(L_input_ptr) = I0;
right_ring_buff_in:
BTST r9 by M_Right_ADC; /* Did we process a valid right sample in this ISR? */
IF sz JUMP ring_done; /* If we did, store result to right ring buffer input */
R0 = DM(Right_Channel_In);
B0 = Rchan_ring_buff;
I0 = DM(R_input_ptr);
DM(I0,M0) = R0;
DM(R_input_ptr) = I0;
ring_done:
rts;
/* -------------------------------------------------------------------------------------------------- */
left_ring_buff_out:
L0 = 6;
M0 = 1;
B0 = Lchan_ring_buff;
I0 = DM(L_DAC_output_ptr);
R0 = DM(I0,M0);
DM(L_DAC_output_ptr) = I0;
DM(Left_Channel_Out) = R0;
rts;
/* -------------------------------------------------------------------------------------------------- */
right_ring_buff_out:
B0 = Rchan_ring_buff;
I0 = DM(R_DAC_output_ptr);
R0 = DM(I0,M0);
DM(R_DAC_output_ptr) = I0;
DM(Right_Channel_Out) = R0;
rts;
/* -------------------------------------------------------------------------------------------------- */
.endseg;
Variable Sample Rate ISR Using Both The RX and TX Interrupt For
Processing - TX DAC Transmission Based On DAC Request Bits
/* **************************************************************************************************
Receives MIC1 input from the AD1819A via SPORT0 and then transmits the audio data back out to the
AD1819A Stereo DACs/Line Outputs. This version supports the variable sample rate features of the
AD1819A, testing both the ADC valid bits and DAC request bits for transmitting and receiving data
at sample rates (selectable in 1 Hz increments) other than 48 kHz.
*****************************************************************************************************
Serial Port 1 Transmit Interrupt Service Routine performs arithmetic computations on SPORT1 receive
data buffer (rx_buf) and sends results to SPORT1 transmit data buffer (tx_buf)
*****************************************************************************************************/
/* Left and Right ADC valid Bits used for testing of valid audio data in current TDM frame */
#define M_Left_ADC 12
#define M_Right_ADC 11
#define DAC_Req_Left 0x80
#define DAC_Req_Right 0x40
.GLOBAL Process_AD1819_Audio_Input;
.GLOBAL Playback_Audio_Data;
.GLOBAL Left_Channel;
.GLOBAL Right_Channel;
.GLOBAL Left_Channel_In;
.GLOBAL Right_Channel_In;
.GLOBAL Left_Channel_Out;
.GLOBAL Right_Channel_Out;
.GLOBAL RX_left_flag;
.GLOBAL RX_right_flag;
.EXTERN tx_buf;
.EXTERN rx_buf;
.EXTERN Slapback_Echo;
.EXTERN Stereo_Double_Tracking;
.EXTERN effects_counter;
.segment /dm dm_codec;
/* AD1819A stereo-channel data holders and flags-used for DSP processing of received codec audio data*/
.VAR Left_Channel_In; /* Input values from AD1819A ADCs */
.VAR Right_Channel_In;
.VAR Left_Channel_Out; /* Output values for AD1819A DACs */
.VAR Right_Channel_Out;
.VAR Left_Channel; /* can use for intermediate results to next filter stage */
.VAR Right_Channel; /* can use for intermediate results to next filter stage */
.VAR RX_left_flag; /* DSP algorithm only processed when these bits are set */
.VAR RX_right_flag;
.VAR DAC_RQ; /* used to pass DAC request bits info from rx ISR to tx ISR */
.endseg;
/* **************************************************************************************** */
/* */
/* SPORT1 RX INTERRUPT SERVICE ROUTINE */
/* */
/* **************************************************************************************** */
Process_AD1819_Audio_Input:
bit set mode1 SRRFL; /* enable background register file */
NOP; /* 1 CYCLE LATENCY FOR WRITING TO MODE1 REGISER!! */
get_DAC_request_bits:
r1 = dm(rx_buf + STATUS_ADDRESS_SLOT); /* Get ADC request bits from address slot */
dm(DAC_RQ) = r1; /* save for SPORT1 TX ISR */
r0 = dm(rx_buf + TAG_PHASE); /* get tag information to inspect for valid L/R ADC data */
check_AD1819_ADC_left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP check_AD1819_ADC_right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + LEFT); /* get Master 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Left_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_left_flag) = r4; /* if we have a new left sample, let the DSP filter routine know */
check_AD1819_ADC_right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz jump user_applic; /* If valid data then save ADC sample */
r6 = dm(rx_buf + RIGHT); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign in 1.31 format */
dm(Right_Channel_In) = r6; /* save to data holder for processing */
r4 = 1;
dm(RX_right_flag) = r4; /* if we have a new right sample, let the DSP filter routine know */
/* ------------------------------------------------------------------------------------------------------ */
/* user_applic( ) - User Applications Routines */
/* *** Insert DSP Algorithms Here *** */
/* */
/* Input L/R Data Streams - DM(Left_Channel_In) DM(Right_Channel_In) */
/* Output L/R Results - DM(Left_Channel_Out) DM(Right_Channel_Out) */
/* */
/* These left/right data holders are used to pipeline data through multiple modules, and */
/* can be removed if the dsp programmer needs to save instruction cycles */
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/* Coding TIP: */
/* The samples from the AD1819A are 16-bit and are in the lower 16 bits of the the 32-bit */
/* word. They are shifted to the most significant bit positions in order to preserve the */
/* sign of the samples when they are converted to floating point numbers. The values are */
/* also scaled to the range +/-1.0 with the integer to float conversion */
/* (f0 = float r0 by r1). */
/* */
/* To convert between our assumed 1.31 fractional number and IEEE floating point math, */
/* here are some example assembly instructions ... */
/* */
/* r1 = -31 <-- scale the sample to the range of +/-1.0 */
/* r0 = DM(Left_Channel); */
/* f0 = float r0 by r1; */
/* [Call Floating_Point_Algorithm] */
/* r1 = 31; <-- scale the result back up to MSBs */
/* r8 = fix f8 by r1; */
/* DM(Left_Channel) = r8; */
/* ------------------------------------------------------------------------------------------------------ */
user_applic:
/* since we powered down the ADCs after codec initialization, the samples should occur in
left right pairs. Therefore, since both the left and right channels are running at the
same fs, when we detect a left sample, we will call our DSP routine because we will have
both a new left sample and a new right sample */
r4 = dm(RX_left_flag);
r4 = pass r4;
if eq jump rx_end; /* if RX_left_flag = 1, then do audio processing */
/* delay routine will clear RX_left_flag */
do_audio_processing:
r0 = DM(effects_counter);
r0 = pass r0; /* get preset mode */
if eq call (pc, Slapback_Echo); /* check for count == 0 */
r0 = DM(effects_counter); /* check again */
r0 = pass r0; /* still the same ? */
if eq jump rx_end; /* bypass if not stereo */
r0 = r0 - 1; /* decrement, must be stereo effect */
if eq call (pc, Stereo_Double_Tracking); /* check for count == 1 */
/* ---- DSP processing is finished, now playback results to AD1819 via TX ISR ---- */
rx_end:
r4 = 0x0; /* since we are not using the right flag, always clear */
dm(RX_right_flag) = r4; /* since left & right come in pairs at same fs rate, we
only need one flag */
r0=dm(rx_audio_frame_timer); /* get last count */
r0=r0+1; /* increment count */
dm(rx_audio_frame_timer)=r0; /* save updated count */
/* **************************************************************************************** */
/* */
/* SPORT1 TX INTERRUPT SERVICE ROUTINE */
/* */
/* **************************************************************************************** */
Playback_Audio_Data:
/* Build Transmit Tag Phase Slot Information */
r0 = 0x00c0; /* slots3 and slots 4 DAC REQ bit mask */
check_DAC_request_bits:
/* DAC request bits were fetched from spt1 rx ISR! */
r1 = dm(DAC_RQ); /* Get ADC request bits from address slot */
r2 = r1 and r0; /* Mask out the AD1819 Master DRRQ0 and DLRQ0 bits */
r2 = r2 xor r0; /* Set active low DAC request bits to active hi */
r2 = lshift r2 by 5; /* shift up so output tag info is bits 12 and 11 */
set_TX_slot_valid_bits:
r0 = 0x8000; /* Write tag to tx-buf ASAP before it's shifted out! */
r2 = r2 or r0; /* set tx valid bits based on received DAC request info */
dm(tx_buf + TAG_PHASE) = r2; /* Set Valid Frame & Valid Slot bits in slot0 tag phase */
r0 = 0; /* Clear all AC97 link Audio Output Frame slots */
dm(tx_buf + COMMAND_ADDRESS_SLOT) = r0;
dm(tx_buf + COMMAND_DATA_SLOT) = r0;
dm(tx_buf + LEFT) = r0;
dm(tx_buf + RIGHT) = r0;
/* Transmit Left and Right Valid Data if Requested */
r2=DAC_Req_Left; /* Check to see if Left DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_left; /* if it is 1, it means we have no request, so move on */
bypass_left:
r2=DAC_Req_Right; /* Check to see if Right DAC REQ? */
r3=r1 and r2; /* DAC request is active low */
if ne jump bypass_right; /* if it is 1, it means we have no request, so move on */
bypass_right:
r0=dm(tx_audio_frame_timer); /* get last count */
rti(db); /* return from interrupt, delayed branch */
r0=r0+1; /* increment count */
dm(tx_audio_frame_timer)=r0; /* save updated count */
/* ----------------------------------------------------------------------------------------- */
.endseg;
Example RX ISR For Three Daisy-Chained AD1819As
/* ----------------------------------------------------------------------------------------- */
/* Serial Port 1 Receive Interrupt Service Routine */
/* performs arithmetic computations on SPORT1 receive data buffer (rx_buf) and */
/* sends results to SPORT1 transmit data buffer (tx_buf) */
/*
rx_buf[9] - DSP SPORT recieve buffer
Slot # Description DSP Data Memory Address
0 AD1819A Tag Phase DM(rx_buf + 0)
1 Status Address Port DM(rx_buf + 1)
2 Status Data Port DM(rx_buf + 2)
3 Master PCM Capture (Record) Left Channel DM(rx_buf + 3)
4 Master PCM Capture Right Channel DM(rx_buf + 4)
5 Slave 1 PCM Capture Left Channel DM(rx_buf + 5)
6 Slave 1 PCM Capture Right Channel DM(rx_buf + 6)
7 Slave 2 PCM Capture Left Channel DM(rx_buf + 7)
8 Slave 2 PCM Capture Right Channel DM(rx_buf + 8)
Process_AD1819_Audio_Samples:
r0 = 0x8000; /* Clear all AC97 link Audio Output Frame slots */
dm(tx_buf + 0) = r0; /* and set Valid Frame bit in slot 0 tag phase */
r0 = 0;
dm(tx_buf + 1) = r0;
dm(tx_buf + 2) = r0;
dm(tx_buf + 3) = r0;
dm(tx_buf + 4) = r0;
dm(tx_buf + 5) = r0;
dm(tx_buf + 6) = r0;
dm(tx_buf + 7) = r0;
dm(tx_buf + 8) = r0;
Check_ADCs_For_Valid_Data:
r0 = dm(rx_buf); /* Get ADC valid bits from tag phase slot */
r1 = 0x1f80; /* Mask other bits in tag */
r2 = r0 and r1;
Set_TX_Slot_Valid_Bits:
r1 = dm(tx_buf + 0); /* frame/addr/data valid bits */
r3 = r2 or r1; /* set tx valid bits based on recieve tag info */
dm(tx_buf +0) = r3;
Check_Master_ADC_Left:
BTST r0 by M_Left_ADC; /* Check Master left ADC valid bit */
IF sz JUMP Check_Master_ADC_Right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + 3); /* get Master 1819 left channel input sample */
r6= lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Master_Left_Channel)=r6; /* save to data holder for processing */
Check_Master_ADC_Right:
BTST r0 by M_Right_ADC; /* Check Master right ADC valid bit */
IF sz JUMP Check_Slave1_ADC_Left; /* If valid data then save ADC sample */
r6 = dm(rx_buf + 4); /* get Master 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Master_Right_Channel) = r6; /* save to data holder for processing */
Check_Slave1_ADC_Left:
BTST r0 by S1_Left_ADC; /* Check Slave 1 left ADC valid bit */
if sz jump Check_Slave1_ADC_Right; /* If valid data then save ADC sample */
r6 = dm(rx_buf + 5); /* get Slave 1 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Slave1_Left_Channel) = r6; /* save to data holder for processing */
Check_Slave1_ADC_Right:
BTST r0 by S1_Right_ADC; /* Check Slave 1 right ADC valid bit */
if sz jump Check_Slave2_ADC_Left; /* If valid data then save ADC sample */
r6 = dm(rx_buf + 6); /* get Slave 1 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Slave1_Right_Channel) = r6; /* save to data holder for processing */
Check_Slave2_ADC_Left:
BTST r0 by S2_Left_ADC; /* Check Slave 2 left ADC valid bit */
if sz jump Check_Slave2_ADC_Right; /* If request is made save ADC sample */
r6 = dm(rx_buf + 7); /* get Slave 2 1819 left channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Slave2_Left_Channel) = r6; /* save to data holder for processing */
Check_Slave2_ADC_Right:
BTST r0 by S2_Right_ADC; /* Check Slave 2 right ADC valid bit */
if sz rti; /* If valid data then save ADC sample */
r6 = dm(rx_buf + 8); /* get Slave 2 1819 right channel input sample */
r6 = lshift r6 by 16; /* shift up to MSBs to preserve sign */
dm(Slave2_Right_Channel) = r6; /* save to data holder for processing */
/* --------------------------------------------- */
/* Insert Sample/Block Processing Algorithm Here */
/* --------------------------------------------- */
Loopback_Audio_Data:
r15 = dm(Master_Left_Channel); /* get channel 1 output result */
r15 = lshift r15 by -16; /* put back in bits 0..15 for SPORT tx */
dm(tx_buf + 3) = r15; /* output left result to Master AD1819 Slot 3 */
.EXTERN _main;
.EXTERN Init_DSP;
.EXTERN Process_AD1819_Audio_Samples;
.SEGMENT/PM isr_tbl;
/* *** 0x20 - IRQ0 Interrupt Service Routine (ISR) , 4 locations max *** */
irq0_svc: RTI; RTI; RTI; RTI;
/* 0x28 - Vectors for Serial Port 0 Receive A & B DMA channels 0/1 */
spr0_svc: RTI; RTI; RTI; RTI;
/* 0x2C - Vectors for Serial Port 1 Receive A & B DMA channels 2/3 */
spr1_svc: JUMP Process_AD1819_Audio_Samples; RTI; RTI; RTI;
/* 0x30 - Vectors for Serial Port 0 Transmit A & B DMA channels 4/5 */
spt0_svc: RTI; RTI; RTI; RTI;
/* 0x34 - Vectors for Serial Port 1 Transmit A & B DMA channels 6/7 */
spt1_svc: RTI; RTI; RTI; RTI;
.ENDSEG;
Visual DSP Tools (21065L EZ-LAB) Linker Description File
// ************************************************************************************/
// * */
// * 21065L EZ-LAB LINKER DESCRIPTION FILE */
// * */
// * For use with the 21065L EZ-LAB Evaluation Platform. The Interrupt Table is */
// * split into 2 sections- low and high. IRQ0 is removed, so that the UART */
// * remains functional and is not overwritten after downloading of user code */
// * */
// * (JT - 10/23/98) */
// ************************************************************************************/
ARCHITECTURE(ADSP-21065L)
SEARCH_DIR( $ADI_DSP\21k\lib )
// The lib060.dlb must come before libc.dlb because libc.dlb has some 21020
// specific code and data
$LIBRARIES = lib060.dlb;
MAP (loopback.map)
//
// ADSP-21065L Memory Map:
// ------------------------------------------------
// Internal memory 0x0000 0000 to 0x0007 ffff
// ------------------------------------------------
// 0x0000 0000 to 0x0000 00ff IOP Regs
// 0x0000 0100 to 0x0000 01ff IOP Regs of processor ID 001
// 0x0000 0200 to 0x0000 02ff IOP Regs of processor ID 002
// 0x0000 0300 to 0x0000 7fff Reserved (unusable)
//
// Block 0 0x0000 8000 to 0x0000 9fff Normal Word (32/48) Addresses
// 0x0000 A000 to 0x0000 Bfff Reserved
// Block 1 0x0000 C000 to 0x0000 Dfff Normal Word (32/48) Addresses
// 0x0000 E000 to 0x0000 ffff (Reserved)
// Block 0 0x0001 0000 to 0x0001 3fff Short Word address space (16-bit)
// 0x0001 4000 to 0x0001 7fff Reserved
// Block 1 0x0001 8000 to 0x0001 bfff Short Word (16) Addresses
//
// 0x0001 C000 to 0x0001 ffff Reserved
//
// ------------------------------------------------
// Multiproc memory 0x0000 0100 to 0x0000 02ff
// ------------------------------------------------
//
// ------------------------------------------------
// External memory 0x0002 0000 to 0x03ff ffff
// ------------------------------------------------
//
MEMORY
{
// IRQ0 Interrupt 0x20 - 0x23 reserved by EZ-LAB UART Monitor Program */
isr_tabl { TYPE(PM RAM) START(0x00008005) END(0x0000807f) WIDTH(48) }
pm_code { TYPE(PM RAM) START(0x00008100) END(0x00008bff) WIDTH(48) }
pm_data { TYPE(PM RAM) START(0x00009400) END(0x000097ff) WIDTH(32) }
krnl_code { TYPE(PM RAM) START(0x00009000) END(0x000097ff) WIDTH(48) }
dm_data { TYPE(DM RAM) START(0x0000c000) END(0x0000dfff) WIDTH(32) }
EMAFE_addr { TYPE(DM RAM) START(0x01000000) END(0x01000000) WIDTH(32) }
EMAFE_data { TYPE(DM RAM) START(0x01000001) END(0x01000001) WIDTH(32) }
UART_regs { TYPE(DM RAM) START(0x01000008) END(0x0100000F) WIDTH(32) }
codec_reset { TYPE(DM RAM) START(0x01000010) END(0x01000010) WIDTH(32) }
seg_dm_sdram { TYPE(DM RAM) START(0x03000000) END(0x030ffeff) WIDTH(32) }
krnl_ext_res { TYPE(DM RAM) START(0x030fff00) END(0x030fffff) WIDTH(32) }
}
PROCESSOR p0
{
LINK_AGAINST( $COMMAND_LINE_LINK_AGAINST)
OUTPUT( $COMMAND_LINE_OUTPUT_FILE )
SECTIONS
{
// .text output section
isr_tabl
{
INPUT_SECTIONS( $OBJECTS(isr_tbl) $LIBRARIES(isr_tbl))
} >isr_tabl
pm_code
{
INPUT_SECTIONS( $OBJECTS(pm_code) $LIBRARIES(pm_code))
} >pm_code
pm_data
{
INPUT_SECTIONS( $OBJECTS(pm_data) $LIBRARIES(pm_data))
} >pm_data
dm_data
{
INPUT_SECTIONS( $OBJECTS(dm_data dm_codec) $LIBRARIES(dm_data))
} > dm_data
//---------------------------------
// EXTERNAL MEMORY SEGMENTS
// if you do not want to initialize SRAM area in executable, use SHT_NOBITS
// example sdram SHT_NOBITS
// {
// INPUT_SECTIONS( $OBJECTS(segsdram))
// } > seg_dm_sdram
//--------------------------------
dm_sdram // SHT_NOBITS
{
INPUT_SECTIONS( $OBJECTS(testtone dm_delay segsdram))
} > seg_dm_sdram
}
}
4 3 2 1
SPORT0
OPEN: SINGLE AD1819 SDATA_IN TFS0
CLOSED: MASTER AD1819 SYNC 10 27a 51
BIT_CLK 6 SYNC 27c RFS0 52 TFS0
26c RXCLK0 54 RFS0
D JP2
OPEN: MULTIPLE CODECS AD1819 JP1 BIT_CLK 26a TXCLK0 RCLK0
TCLK0
ADSP-2106x D
XTAL_OUT
TS3/4 CLOCK_OUT 2C -3VA
JP2
XTAL_IN
4A -12V
3C +12V
MULTIPLE/SINGLE 1A AGND
4C AGND
13A Vcc
2 3 13C Vcc
Y? 25A Vcc
24.576MHz C? 25C Vcc
C? 22pF NP0 9A DGND
22pF NP0 9C DGND
17A DGND
17C DGND
21A DGND
21C DGND
C 29A DGND C
29C DGND
/RESET11
SDATA_OUT5
8
SDATA_IN10
SYNC6
JP3 BIT_CLK
OPEN: ONE SLAVE
CLOSED: TWO SLAVES AD1819 JP3
CS0 45
46 1
CS[0,1]=00
HARDCODED FOR SLAVE #1 FUNCTION SLAVE 1 CS1 47
CHAIN_IN
CLOCK_OUT
48
Note: A 10-K to 20-K Ohm pulldown
XTAL_OUT
TS5/6
XTAL_IN
TS7/8 TITLE:
MULTIPLE AD1819 CODECS
XTAL_IN
D D
A6 MD0
C6 MD1
A7 MD2
C7 MD3
A8 MD4
C8 MD5
A10 MD6
C10 MD7
MODULE DATA, MD0..15 (16xI/O)
A11 MD8
41-SIGNAL LEADS,
C11 MD9
A12 MD10
C12 MD11
A14 MD12
C14 MD13
A15 MD14
C15 MD15
A19 MA1
C19 MA2
A20 MA3
C20 MA4
MODULE REGISTER ADDR, MA0..7(8xI/P)
A23 MA5
C22 MA6
A23 MA7
RESET
SDATA_OUT BIT_CLK C26 RXCLK0
SDATA_IN SYNC C27 RFS0
SYNC SDATA_IN C28 RXD0
BIT_CLK A26 TXCLK0
SERIAL COMMS PORT 0, 6 LINES
SYNC A27 TFS0
SDATA_OUT A28 TXD0
C30 RXCLK1
C31 RFS1
C32 RXD1
A30 TXCLK1
B A31 TFS1 B
A32 TXD1
A FILE: A
C:\CLIEWORK\LARRY\MAFEINTF.SCH
TITLE:
FB1 R1
J1 EMI 1k C33
4
LINE 3 C11 C12 C13 C14
5 C17 R10 1u 10u TANT 10u TANT 10u TANT 10u TANT
INPUT 2 1n +5VA +5VA +5VD +5VD
47k
+
1
+
-
-
FB5 R5 C5 C6 C7 C8
D 100n 100n 100n 100n D
EMI 1k C32
38 42 25 26 4 1 7 9
C21 R14 1u
1n 47k AVdd2 AVss2 AVdd1 AVss1 DVss1 DVdd1 DVss2 DVdd2
12
FB2 R2 C31 24
1u LINE_IN_R
EMI 1k
J2 4 23
3 LINE_IN_L
CDROM 11
5
2 C18 21 /RESET
INPUT R11
1 1n 47k MIC1 5
C34 22 SDATA_OUT
FB6 R6
1u MIC2 8
EMI 1k
SDATA_IN
20 10
C CD_R SYNC C
C22
R15 18 6
1n CD_L BIT_CLK
47k
R7 C35 19
FB7 CD_GND
EMI 1k 1u
16 AD1819
VIDEO_L
MULTIPLE DEVICE
17
VIDEO_R
DAISY CHAIN
FB3 R3 45
14 CS0
EMI 1k
J3 4 AUX_L 46
PORT
3 15 CS1
C30 AUX_R 47
PHONE 5 R12 1u
2 C19 CHAIN_IN
1n 47k 13 48
1
PHONE CLOCK_OUT
37
MONO_OUT
B B
R8 36
FB8 C29
1k 1u LINE_OUT_R
EMI
R16 C23 35
47k LINE_OUT_L
1n
AFILT1 AFILT2 FILT_L FILT_R CX3D RX3D VREFOUT VREF XTAL_IN XTAL_OUT
29 30 31 32 34 33 28 27 2 3
Y1
FB4 R4 C27
24.576MHz
EMI 1k 1u
J4 2.25Vdc +
4 C3
LINE 3 100n -
5
OUTPUT 2 C20 C1 C2 C26 C25 C9 C4 C10 C15 C16
1 R13 1n 270p NP0270p NP0 1u 1u 47n NP0 100n 10u TANT 22p NP0 22p NP0
47k
FB9 R9 C28
EMI 1k 1u
A FB10 FILE: A
C:\CLIEWORK\LARRY\AD19MAFE.SCH
600Z
TITLE:
C24 AD1819 SINGLE MAFE AUDIO I/O
R17 1n
47k SIZE: DRG: ANALOG DEVICES, INC., RSTC
CHASSI GROUND ANALOG GROUND DIGITAL GROUND
LETTER Larry Hurst 804 WOBURN ST
WILMINGTON, MA 01887-3494
DATE: DRW No. SHT OF REV:
11-Dec-1996 96327-01-04 1 1 A
4 3 2 1
APPENDIX B - AD1819A Indexed Control Register Reference
Reg Name D15 D14 D13 D12 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 Default
Num
00h Reset X SE4 SE3 SE2 SE1 SE0 ID9 ID8 ID7 ID6 ID5 ID4 ID3 ID2 ID1 ID0 0400h
02h Master Volume MM X LMV LMV LMV LMV LMV LMV X X RMV RMV4 RMV3 RMV2 RMV1 RMV 8000h
5 4 3 2 1 0 5 0
04h Reserved X X X X X X X X X X X X X X X X X
06h Master Volume Mono MM X X X X X X X X X MMV MMV MMV MMV MMV MMV 8000h
M 5 4 2 2 1 0
08h Reserved X X X X X X X X X X X X X X X X X
0Ch Phone Volume PHM X X X X X X X X X X PHV4 PHV PHV PHV PHV 8008h
3 2 1 0
0Eh Mic Volume MCM X X X X X X X X M20 X MCV MCV3 MCV2 MCV1 MCV 8008h
4 0
10h Line In Volume LM X X LLV4 LLV3 LLV2 LLV1 LLV0 X X X RLV4 RLV3 RLV2 RLV1 RLV0 8808h
12h CD Volume CVM X X LCV4 LCV3 LCV2 LCV1 LCV0 X X X RCV4 RCV3 RCV2 RCV1 RCV0 8808h
14h Video Volume VM X X LVV4 LVV3 LVV2 LVV1 LVV0 X X X RVV4 RVV3 RVV2 RVV1 RVV0 8808h
16h Aux Volume AM X X LAV4 LAV3 LAV2 LAV1 LAV0 X X X RAV4 RAV3 RAV2 RAV1 RAV0 8808h
18h PCM Out Vol OM X X LOV4 LOV3 LOV2 LOV1 LOV0 X X X ROV4 ROV3 ROV2 ROV1 ROV0 8808h
1Ah Record Select X X X X X LS2 LS1 LS0 X X X X X RS2 RS1 RS0 0000h
1Ch Record Gain IM X X X LIM3 LIM2 LIM1 LIM0 X X X X RIM3 RIM2 RIM1 RIM0 8000h
1Eh Reserved X X X X X X X X X X X X X X X X X
24h Reserved X X X X X X X X X X X X X X X X X
26h Powerdown Cntrl/Stat X X PR5 PR4 PR3 PR2 PR1 PR0 X X X X REF ANL DAC ADC 000Xh
28h Reserved X X X X X X X X X X X X X X X X X
.. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
74h Serial Configuration SLOT REGM REG REGM DRQ DLR DLR DLR X X X X X DRR DRR DRR 7000h
16 2 M1 0 EN Q2 Q1 Q0 Q2 Q1 Q0
7X0Xh
76h Misc Control Bits DAC X X X X DLSR X ALSR MOD SRX1 SRX8 X X DRSR X ARSR 0000h
Z EN 0D7 D7
78h Sample Rate 0 SR01 SR014 SR01 SR012 SR01 SR01 SR09 SR08 SR07 SR06 SR05 SR04 SR03 SR02 SR01 SR00 BB80h
5 3 1 0
7Ah Sample Rate 1 SR11 SR114 SR11 SR112 SR11 SR11 SR19 SR18 SR17 SR16 SR15 SR14 SR13 SR12 SR11 SR10 BB80h
5 3 1 0
7Eh Vendor ID2 T7 T6 T5 T4 T3 T2 T1 T0 REV7 REV6 REV5 REV4 REV3 REV2 REV1 REV0 5300h
AD1819A Block Diagram Register Map
MIC1 0
MS 0dB/20dB LS/RS (0)
MIC2 1
M20 0x0E
S 0x20
LINE LS (4)
RS (4)
G A M 0x1C
S 16-bit
AUX LS (3) LIV A/D
RS (3) E IM
L
CD LS (1) E
RS (1)
C
VID LS (2) T G A M 0x1C
RS (2) O 16-bit
R RIV A/D
PHONE_IN LS/RS (7) IM
LS (5)
LS/RS (6)
RS (5) RESET#
SYNC
S 0x1A
G A M 0x18
16-bit
LOV D/A
M 0x02 A 0x02 3D 0x22 OM
L_OUT MM LMV POP3D
0
M 0x06 A 0x06 3D 0x20
MONO_OUT 1
MMM MMV SWITCH
MIX S 0x20
M 0x02 A 0x02 3D 0x22
R_OUT MM RMV POP3D G A M 0x18
16-bit
ROV D/A
OM
M 0x0A
PCM
A 0x0A
PC_BEEP PCV
Oscillators
XCTLO XCTLI
MIC1
0 dB/
MIC2 20 dB
LINE PGA
SYNTH
Selector
CD PCM in
VID
PGA
PHONE_IN
G G G G G G
∑ A A A A A A
MV
HP_OUT_L M M M M M M
G
Tone Fat
L_OUT MV
Control
∑ ∑
Stereo
∑ ∑ ∑ ∑ ∑ A
M
HP_OUT_R MV
A G=Gain
M A=Attenuate
M=Mute
PC_BEEP
MV=Master Volume
Information furnished in this document by Analog Devices, Inc., is believed to be accurate and reliable. However, no responsibility is assumed
by Analog Devices Inc., for its use; nor for any infringements of patents or other rights of third parties which may result from its use. No
license is granted by implication or otherwise under the patent rights of Analog Devices. Analog Devices Inc. reserves the right to make
changes without further notice to any products and information contained in this document.
Analog Devices makes no guarantee regarding the suitability of its DSP and codec products for any particular purpose, nor does Analog
Devices assume any liability arising out of the application or use of Analog Devices DSP and codec products, and specifically disclaims any
and all liability, including without limitation consequential or incidental damages. Operating parameters, such as voltage and temperature, as
specified in Analog Devices data sheets must be validated for each application by the customer’s technical experts. Analog Device's DSP
and codec products are not designed, intended, or authorized for use for products in which the failure of the ADI part could create a situation
where personal injury or death may occur. If the Buyer/User/Designer uses Analog Devices products for any unintended or unauthorized
application, then Analog Devices cannot be held responsible.