Technical Notes on using Analog Devices' DSP components and development tools
Contact our technical support by phone: (800) ANALOG-D or e-mail: dsp.support@analog.com
Or vi sit ou r on-l ine re sourc es ht tp:// www.analog.com/dsp and http://www.analog.com/dsp/EZAnswer
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec
Contributed by Jeff Sondermeyer, Senior DSP FAE, and Paul Ellis, Engineering Technologist, Daniels Electronics
May 13, 2003
Introduction
The AD73322L is a dual front-end processor for
general-purpose applications including speech
and telephony. It features two 16-bit A/D
conversion channels and two 16-bit D/A
conversion channels. Each channel provides
78dB signal-to-noise ratio. Over a voiceband
signal bandwidth. It also features an input-tooutput gain network in both the analog and
digital domains. This is featured on both codecs
and can be used for impedance matching or
scaling when interfacing to Subscriber Line
Interface Circuits (SLICs).
The AD73322L is particularly suited for a
variety of applications in the speech and
telephony area, including low bit rate, high
quality compression, speech enhancement,
recognition and synthesis. The low group delay
characteristic of the part (25uS typical) makes it
suitable for single or multichannel active control
applications. The AD73322L also has a flexible
serial port which allows up to four dual Codecs
to be connected in cascade providing eight
input/output channels. Furthermore, the typical
power consumption for the AD73322L device is
50mW at 3.0V. When used in conjunction with
our new low power Blackfin® processors, this
provides an overall, power efficient, end-to-end,
glueless solution suitable for handheld speech
and telephony battery operated devices.
Hardware Interface
In this application, an AD73322L is connected to
SPORT1 on the ADSP-BF535 (see Figure 1).
The AD73322L is a 16-bit Codec operating from
a single supply down to 2.7V. It has a
programmable sample rate up to 64KHz. To
avoid any voltage translation when connecting it
to the ADSP-BF535, the codec should be
operated at 3.3V (same as the Blackfin® I/O
voltage). We tested the AD73322L-ADSPBF535 interface in two configurations: single
codec, dual channel and cascaded eight channel
modes. Figure 2 shows the single, dual channel
glueless connection to the ADSP-BF535. Figure
3 shows the cascaded eight channel connection
to the ADSP-BF535 (assembly code for the
eight-channel operation is not shown in this note
but is part of the VisualDSP++™ 3.1 project ZIP
file).
In order to synchronize the codec to the ADSPBF535 processor, we connected the AD73322L
SE (serial enable) control line to the FP11 on
ADSP-BF535. This ensures that we are always
reading the proper channel from the codec after
initialization. When SE is de-asserted, the first
channel of the last device in the cascade chain is
transmitted back to the processor. In this way,
we can always identify which channel is coming
from the codec(s).
s
Copyright 2003, Analog Devices, Inc. All rights reserved. Analog Devices assumes no responsibility for customer product design or the use or application of
customers’ products or for any infringements of patents or rights of others which may result from Analog Devices assistance. All trademarks and logos are property
of their respective holders. Information furnished by Analog Devices Applications and Development Tools Engineers is believed to be accurate and reliable, however
no responsibility is assumed by Analog Devices regarding technical accuracy and topicality of the content provided in Analog Devices’ Engineer-to-Engineer Notes.
a
Figure 1: ADDS-21535-EZLITE to Eval-AD73322LEB Interface
The /RESET pin of the AD73322L may be
connected to the system or hardware reset for the
ADSP-BF535 or it may be controlled using a
general purpose flag from the ADSP-BF535 (as
shown in Figure 2 and Figure 3). In the event of
tying it to the system reset, it is advisable to
operate the device in mixed mode, which allows
a software reset, otherwise there is not
convenient way of resetting the device.
Digital Interface
The AD73322L is designed to easily interface to
most common processors. The SCLK, SDO,
SDOFS, SDI, and SDIFS must be connected to
the ADSP-BF535’s Serial Clock, Receiver Data,
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 2 of 36
Receive Data Frame Sync, Transmit Data and
Transmit Data Frame Sync pins respectively (See
Figure 2). Where it is required to configure a
cascade of up to eight codecs (four AD73322L
dual codecs), it is necessary to ensure that the
timing of the SE and /RESET signals be
synchronized at each device in the cascade. A
simple D type flip flop is sufficient to sync each
signal to the MCLK (master clock), as in Figure
2. Connection of a cascade of devices to a
ADSP-BF535 is no more complicated than
connecting a single device. Instead of
connecting the SDO and SDOFS to the DSP’s Rx
port, these are now daisy-chained to the SDI and
SDIFS of the next device in the cascade. The
SDO and SDOFS of the final device in the
cascade are connected to the DSP’s Rx port to
complete the chain. SE and /RESET on all
devices are fed from the signals that were
synchronized with the MCLK using the circuit as
described above. The SCLK from only one
device need be connected to the DSP’s SCLK
input(s) as all devices will be running at the same
SCLK frequency and phase. Note that SCLK in
this context does not refer to the system clock on
the ADSP-BF535 but to the serial clock on the
AD73322L.
a
ADSP-BF535
RCLK1
TCLK1
RFS1
TFS1
DR1
DT1
PF10
PF11
AD73322L
SCLK
SDIFS
SDOFS
SDO
SDI
RESET
SE
Figure 2: Dual Channel CODEC-DSP connection
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 3 of 36
a
ADSP-BF53xAD73322L # 1
RCLK1
TCLK1
RFS1
TFS1
DR1
DT1
PF10
PF11
SCLK
SDIFS
SDOFS
SDO
SDI
RESET
SE
N/C
RFS1
TFS1
PF10
PF11
AD73322L # 3
SCLK
SDIFS
SDOFS
SDO
SDI
RESET
SE
PF11 from DSP
MCLK from Conv.
PF10 from DSP
MCLK from Conv.
D
CLK
D
CLK
74HC74
74HC74
PF11 to 73322
Q
PF10 to 73322
Q
RFS1
TFS1
PF10
AD73322L #2
SCLK
SDIFS
SDOFS
SDO
SDI
RESET
SE
N/CN/C
RFS1
TFS1
PF10
PF11PF11
AD73322L #4
SCLK
SDIFS
SDOFS
SDO
SDI
RESET
SE
Figure 3: Eight Channel CODEC-DSP Connection
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 4 of 36
a
ADSP-BF535 Programming
Considerations
This section discusses some aspects of how the
serial port of the ADSP-BF535 should be
configured and the implications of whether Rx
and Tx interrupts should be enabled.
Following are the key settings of the ADSPBF535 SPORT required for the successful
operation with the AD73322L:
• Frame Syncs occur one SPORT serial clock
cycle before the MSB of the serial word.
• Frame Syncs are active high.
If SPORT interrupts are enabled, it is important
to note that the active signals on the frame sync
pins do not necessarily correspond with the
positions in time of where SPORT interrupts are
generated. On ADSP-BF535 processor, it is
necessary to enable SPORT interrupts and use
Interrupt Service Routines (ISRs) to handle
Tx/Rx activity.
ADSP-BF535 Software
Considerations
Sync Loop Back (FSLB) or NonFSLB when
deciding on DSP to AFE connectivity. There is
also a choice to be made between using
autobuffering of input and output samples or
simply choosing to accept them as individual
interrupts. As most modern DSP engines support
these modes, this appendix will attempt to
discuss these topics in a generic DSP sense.
Operating Mode
The AD73322L supports two basic operating
modes: FSLB and NonFSLB. As described
previously, FSLB has some limitations when
used in Mixed Mode but is very suitable for use
with the autobuffering DMA feature that is
offered on many modern DSPs (including the
ADSP-BF535). Autobuffering allows the user to
specify the number of input or output words
(samples) that are transferred before a specific
Tx or Rx SPORT interrupt is generated. Given
that the AD73322L outputs two sample words
per sample period, it is possible using
autobuffering to have the ADSP-BF535 SPORT
generate a single interrupt on receipt of the
second of the two sample words (Appendix 1 is a
very simple autobuffer DMA example).
Additionally, both samples could be stored in a
data buffer within the data memory store. This
technique has the advantage of reducing the
number of both Tx and Rx SPORT interrupts to a
single one at each sample interval. The user also
knows where each sample is stored. The
alternative is to handle a larger number of
SPORT interrupts (twice as many in the case of a
single AD73322L) while also having some status
flags to indicate where each new sample comes
from (or is destined for).
It is important when choosing the operating
mode and hardware configuration of the
AD73322L to be aware of their implications for
ADSP-BF535 software operation. The user has
the flexibility of choosing from either Frame
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 5 of 36
Mixed-Mode Operation
To take full advantage of mixed-mode operation,
it is necessary to configure the ADSPBF535/Codec interface in NonFSLB and to
disable autobuffering (see Appendix 2). This
a
allows a variable numbers of words to be sent to
the AD73322L in each sample period—the extra
words being control words that are typically used
to update gain settings in adaptive control
applications. The recommended sequence for
updating control registers in mixed mode is to
send the control word(s) first before the DAC
update word. This EE note used this method and
provides two listings. Appendix 1 is the
assembly code for a single AD73322 codec. See
Figure 4 for a Logic Analyzer plot of the relevant
timing signals. Also, See Figure 5 for a scope
plot of necessary timing (blue=clock,
yellow=frame and purple=data). You can see
from these two figures that each 16-bit word has
a 1-bit frame signal that proceeds the data by one
SCLK. Due to this functionality, Multi-channel
Mode (MCM or TDM) SPORT modes do not
work with this codec. As a result, we are forced
to use either autobuffer DMA or interrupts to
process each and every 16-bit word.
Figure 4: Logic Analyzer of AD73322L Timing
It is possible to use mixed-mode operation when
configured in FSLB, but it is necessary to replace
the DAC update with a control word write in
each sample period which may cause some
discontinuity in the output signal due to a sample
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 6 of 36
point being missed and the previous sample
being repeated. This however may be acceptable
in some cases as the effect may be masked by
gain changes, etc.
a
Figure 5: Scope plot of two channels
Interrupts
The AD73322L transfers and receives
information over the serial connection from the
ADSP-BF535 SPORT. This occurs following
reset during the initialization phase—and in both
data-mode and mixed-mode. Each transfer of
data to or from the ADSP-BF535 can cause a
SPORT interrupt to occur. However even in
FSLB configuration where serial transfers in and
out of the DSP are synchronous, it is important to
note that Tx and Rx interrupts do not occur at the
same time due to the way that Tx and Rx
interrupts are generated internally within the
ADSP-BF535’s SPORT. This is especially
important in time critical control loop
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 7 of 36
applications where it may be necessary to use Rx
interrupts only, as the relative positioning of the
Tx interrupts relative to the Rx interrupts in a
single sample interval are not suitable for quick
update of new DAC positions.
AD73322L Initialization
Following reset, the AD73322L is in its default
condition which ensures that the device is in
Control Mode and must be programmed or
initialized from the ADSP-BF535 to start
conversions. As communications between
AD73322L and the ADSP-BF535 are interrupt
driven, it is usually not practical to embed the
a
initialization codes into the body of the
Conclusions
initialization routine. It is more practical to put
the sequence of initialization codes in a memory
buffer and to access this buffer with a pointer
that is updated on each interrupt. If a circular
buffer is used, it allows the interrupt routine to
check when the circular buffer pointer has
wrapped around—at which point the
initialization sequence is complete. In FSLB
configurations, a single control word per codec
per sample period is sent to the AD73322L
whereas in NonFSLB, it is possible to initialize
the device in a single sample period provided the
SCLK rate is programmed to a high rate. It is
also possible to use autobuffering in which case
an interrupt is generated when the entire
initialization sequence has been sent to the
This note provides the hardware interface and
assembly code for ADSP-BF535 interface to
AD73322L operating in mixed mode. While this
code example is not the most efficient in terms of
the number interrupts, it does provide the most
flexibility allowing multiple AD73322L’s to be
cascaded with full control and realtime parameter
updates. Each codec will add two additional
interrupts that must be processed. The assembly
code in this example is not fully optimized and is
not C callable. Additional work should be done
to expand the simple FSLB mode (in Appendix
1) to provide a full talkthrough utilizing Tx and
Rx autobuffer DMAs.
AD73322L.
References
[1] ADSP-BF535 Blackfin® DSP Hardware Reference. Revision 1.0, Nov. 2002, Analog Devices, Inc.
[2] AD73322L, Low Cost, Low Power CMOS General Purpose Dual Analog Front End Datasheet,
b#1000110100000000, // CRF - A Gain Tap=0, Single Ended,
// A Gain Tap=Disables,
b#1000010000000000, // CRF - Dac=0, DGain tap=Disabled
// InterpolatorBypass=Disabled
b#1000111000000000, // CRG - Digital Gain Tap Coef0-7=0
b#1000011000000000, // CRG - Digital Gain Tap Coef0-7=0
b#1000111100000000, // CRH - Digital Gain Tap Coef8-15=0
b#1000011100000000, // CRH - Digital Gain Tap Coef8-15=0
b#1001110100000000, // CRF - A Gain Tap=0, Single Ended,
// A Gain Tap=Disables,
b#1001010100000000, // CRF - Input not inverted, LoopBack=Disabled,
// A Gain Tap Muted
b#1000110100000000, // CRF - A Gain Tap=0, Single Ended,
// A Gain Tap=Disables,
b#1000010100000000, // CRF - Input not inverted, LoopBack=Disabled,
// A Gain Tap Muted
b#1001111000000000, // CRG - Digital Gain Tap Coef0-7=0
b#1001011000000000, // CRG - ditto
b#1000111000000000, // CRG - Digital Gain Tap Coef0-7=0
b#1000011000000000, // CRG - ditto
b#1001111100000000, // CRH - Digital Gain Tap Coef8-15=0
b#1001011100000000, // CRH - ditto
b#1000111100000000, // CRH - Digital Gain Tap Coef8-15=0
b#1000011100000000, // CRH - ditto
b#1001100000110001, // CRA - Data Mode, Mixed Mode=Off, LoopBack=0,
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 10 of 36
/* SPORT Register Bits */
#define RXS 1 /* Status register: Receive Status bit */
#define TXS 2 /* Status register: Transmit Status bit */
#define TSPEN 0 /* TX Config reg: Tx Sport Enable */
// 5432109876543210 b#1000110100000000, // CRF - A Gain Tap=0, Single Ended,
// A Gain Tap=Disables,
b#1000010000000000, // CRF - Dac=0, DGain tap=Disabled
// InterpolatorBypass=Disabled
// 5432109876543210 b#1000111000000000, // CRG - Digital Gain Tap Coef0-7=0
b#1000011000000000, // CRG - Digital Gain Tap Coef0-7=0
// 5432109876543210 b#1000111100000000, // CRH - Digital Gain Tap Coef8-15=0
b#1000011100000000, // CRH - Digital Gain Tap Coef8-15=0
// 5432109876543210
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 23 of 36
// ---------------------------------------------------------------------------// Data to output to the CODECs ... Sine, Cos and 1, 2, 3 and 4 pulse trains
// ---------------------------------------------------------------------------// update the Channel number
[--SP] = (r7:0);
[--SP] = (P5:4);
LoadP4(Channel) // get current Channel
R0.l = w[P4];
R7 = R0; // save for later use
R0 += 1; // point to next
w[P4] = R0.l; // save new value
R1 = NoChannels; // (JWS) Old=8, new=2
cc = R0 == R1; // test for roll over
if !cc jump NoRollOver;
R0 = 0x00; // Channel has rolled over, reset to 0
w[P4] = R0.l;
// ---------------------------------------------------------------------------// get and save the CODEC data to the correct buffer
NoRollOver:
Sport1_Rx:
LoadR6 (RxChannelEnables) // determine if channel is enabled
R6 = R6 + R7; // base + offset
P4 = R6;
R0 = b[P4]; // current channel enable
cc = R0 == 0; // off if 0, on if not 0
if cc jump NoSave;
// channel is enabled
LoadP4 (RxBufPointer)
R6 = w[P4]; // R6=point to top of RxBuf1
R5 = RxBufLength * 2; // *2 because it's in bytes
R4 = R5.l * R7.l (fu); // select buffer: R4=(256*2 Bytes * Channel)
R3 = R4 + R6; // R3=top of RxBuf1 + (256*2 Bytes * Channel)
LoadR5 (RxBuf1) // base address of Rx buffers
R3 = R3 + R5; // add offset to base address
P4 = R3;
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 25 of 36
a
LoaddP5 (SPORT1_RX) // read current data
R0 = w[P5];
w[P4] = R0; // save it.
NoSave:
R6 = NoChannels - 1; // (JWS) old=7, new=1
cc = R7 == R6;
if !cc jump Sport1_Tx;
LoadR6 (TxChannelEnables)
R6 = R6 + R7;
P4 = R6;
R0 = b[P4];
cc = R0 == 0x00;
if cc jump OutputNull; // jump if channel is OFF
LoadP4 (TxBufPointer) // channel is enabled
R6 = w[P4];
R5 = TxBufLength * 2;
R4 = R5.l * R7.l(fu);
R3 = R4 + R6;
LoadR5 (RxBuf1) // base address of Tx buffers
// (JWS) right now you just write out the
RxBuffer..
// just a talkthrough
R3 = R3 + R5;
P4 = R3;
LoaddP5 (SPORT1_TX) // get data
R1 = w[P4];
w[P5] = R1; ssync; // write to Sport1
TxPointerTest: // test
R6 = NoChannels - 2; // (JWS) old=6, new=0
cc = R7 == R6; // (JWS) is channel number = 0???
if !cc jump Sport1_ISR_Exit;
// ---------------------------------------------------------------------------// This ISR is used only during CODEC initizlization and temporarily replaces
// _Sport1ISR
_CODEC_INIT_ISR:
[--SP] = (R7:6); // save regs
[--SP] = (P5:3);
LoadP3 (TxBufPointer)
R6 = w[P3]; // read the current pointer
P5 = R6;
LoadP4 (CODEC_Init_Data)
P4 = P4 + P5;
R7 = w[P4]; // read the current data word
LoaddP4 (SPORT1_TX)
w[P4] = R7;
R7 = CODEC_INIT_Length * 2;
cc = R6 == R7; // see if init is complete
if cc jump CODEC_Init_Done;
R6 += 2; // init not complete, point to the next
w[P3] = R6; // word of data
jump Tx_ISR_Done;
CODEC_Init_Done:
LoadP4 (Done) // show that CODEC init is complete
R6 = 0x01;
w[P4] = R6;
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 27 of 36
// ---------------------------------------------------------------------------// the following code allows the Blackfin to stay in supervisor mode exclusively
LoaddP0 (EVT15) // set IVG15 to the start of real code
LoadP1 (SStart)
[P0] = P1; ssync;
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 33 of 36
a
nop; // this MUST be here !!
// CODEC init fails without it.
nop;
nop;
LoaddP0 (FIO_FLAG_S) // release the CODEC Reset line
R0.l = 0x400;
w[P0] = R0.l; ssync;
// ---------------------------------------------------------------------------// Basic DSP is initilized and configured. Now do the CODEC
Call Init_CODEC;
Call CODEC_Sync;
// ---------------------------------------------------------------------------// CODEC is now up and running... load data into the output buffers
LoadP0 (TxBufPointer) // reset pointers
R0.l = 0x00;
w[P0] = R0.l;
LoadP0 (RxBufPointer) // reset pointers
w[P0] = R0.l;
WaitForDone:
R0 = w[P1]; // wait for flag to show that the
cc = R0 == 0; // CODEC has been initialized.
if cc jump WaitForDone;
// Loadd (P0, FIO_FLAG_C) // put the CODEC to sleep via the SE line
// R0 = 0x800;
// w[P0] = R0; ssync;
LoadR0 (_Sport1ISR) // restore the ISR to the main
LoaddP0 (EVT8) // Sport ISR
[P0] = R0;
rts;
// ---------------------------------------------------------------------------// Copys from one memory location to another
// P0 = Source
// P1 = Destination
// P2 = number of WORDs
CopyMem:
lsetup (CopyStart, CopyEnd) lc0 = P2; // setup loop to copy memory to memory
CopyStart:
R0 = w[P0++];
w[P1++] = R0;
CopyEnd:
nop; // this nop is required. A loop_end
rts; // can never end with rts (etc)
Interfacing the ADSP-BF535 Blackfin® Processor to the AD73322L Codec (EE-193) Page 35 of 36
a
// ---------------------------------------------------------------------------// Allow the DSP to determine when the start of a block of data
// starts from the CODEC. ( I then know when to set Channel to 0)