The ABDAC peripheral on AVR32 MCUs is ideal for generating audio playback. This article describes how to do this and includes a link to a sample driver that generates a sine wave output.
Many embedded applications increasingly feature audio playback, whether simple audio feedback in response to user input or streaming audio at full high speed. The ABDAC on the Atmel AVR32 MCU can support a wide range of playback frequencies by using a common clock interface.
ABDAC is a very simple peripheral that is easy to use. It requires a clock signal provided by a general-purpose clock system, as well as a data input for the channel. The block diagram in Figure 1 gives an overview of this module. Refer to the device data sheet for a detailed description of the ABDAC peripheral.
Figure 1: Clock and datapath block diagram.
The ABDAC uses a common clock to provide the sampling frequency. This common clock is hardwired inside the device and must be 256 times the sampling frequency.
The general clock should be configured and enabled before enabling ABDAC. See the Clocking section in the device datasheet for a description of which general-purpose clock to use. This section also describes further configuration of the general-purpose clock.
The general-purpose clock output range may be limited by its source clock frequency. Therefore, it is critical to design an oscillator that provides a base frequency that can be divided by a general-purpose clock divider to achieve the desired output sample rate. Table 1 shows examples.
When ABDAC is enabled; it expects the Sampled Data Register (SDR) to be updated at the same interval as the output sample rate. Both channels can be updated with a single written instruction as they are in the same I/O register (SDR)
Table 1: Base frequency required for output sample rate.
If the sample data register is not updated within 256 clock cycles from the general clock input to the ABDAC, the underrun bit in the Interrupt Status Register (ISR) will be set. Underrun is a sign of too much CPU load, so the application should do it by using interrupts, or better, if there is direct memory access (DMA) in the device.
There are two interrupts available to offload the CPU. The TX_READY interrupt can be used as a trigger to indicate that the next sample of each channel can be written.
The application should also enable the underrun interrupt to handle the underrun when the Sample Data Register (SDR) is filled. Underload can cause glitches and noise on the output signal.
If an underrun interrupt is triggered, the CPU is overloaded because the application cannot provide data in a timely manner.
ABDAC can be connected to the DMA controller on the device. This takes the load off the CPU when transferring data from the buffer in RAM to the ABDAC. The application only needs to fill the buffer and pass the buffer address to the DMA controller.
The trigger on buffer completion will let the application know when to pass a new buffer to the DMA controller.
The underrun interrupt is critical for DMA transfers because it indicates that the data bus in the device is overloaded or that the DMA transfer to the ABDAC does not have sufficient priority.
The output of this device is not suitable for driving headphones or speakers. The pads limit the maximum current flow. In most practical cases this is not enough to drive a low impedance source.
Due to this limitation, an external amplifier should be connected to the output lines to amplify these signals. This amplifier device can also be used to control the volume.
For testing purposes, the line input or microphone input on the sound system can be used to evaluate the output signal.
To connect the ABDAC to a high impedance device, such as the line input on an amplifier, a passive filter should be added. Figure 2 shows an example schematic.
Figure 2: Line output with passive filter schematic.
An external amplifier is required if the ABDAC is directly driving low impedance headphones or speakers. Figure 3 shows an example schematic using Texas Instruments’ TPA152 stereo audio amplifier.
The complete source code for the drivers discussed in this article can be found at www.atmel.com/dyn/resources/prod_documents/AVR32120.zip.
The driver consists of two files, “dac.c” and “dac.h”, where “dac.h” declares all functions and “dac.c” contains the source code. The only thing that needs to be changed in the driver is to specify the target device. The target device is specified at the top of “dac.h”.
The driver’s sample code outputs a sine wave on both DAC channels. This output is enabled by user input on the GPIO line. Wiring information is included in the documentation accompanying the source code.
The example code is for the ATSTK1000, but with some tweaks it should work with any AVR32 device with an ABDAC.
Figure 3: High power output with external amplifier schematic.
Figure 4 shows the flow of the sample application. The application does this by polling function calls to reduce dependencies on other modules.
Figure 4: ABDAC example application flow diagram.
The ABDAC interface has an interrupt line connected to the Interrupt Controller (IC). Handling the ABDAC interrupt requires programming the IC before configuring the ABDAC. For more information and details on the interrupt controller, see the application note AVR32101: “AVR32 Interrupt Controller”.