Warning: main(/www/www/htdocs/style/globals.php) [function.main]: failed to open stream: No such file or directory in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 1
Warning: main() [function.include]: Failed opening '/www/www/htdocs/style/globals.php' for inclusion (include_path='.:/www/www/common:/www/www/php/lib/php') in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 1
Warning: main(/www/www/htdocs/style/header.php) [function.main]: failed to open stream: No such file or directory in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 8
Warning: main() [function.include]: Failed opening '/www/www/htdocs/style/header.php' for inclusion (include_path='.:/www/www/common:/www/www/php/lib/php') in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 8
In this architecture, a PCM device is a device capable
of supporting either a PCM capture channel,
or a PCM playback channel, or both.
A PCM capture channel converts an analog signal
to a digital PCM stream, whereas a PCM playback channel
takes a digital PCM stream and converts it to analog.
A PCM device may also support converting multiple PCM streams
simultaneously; each of these streams is called a PCM subchannel.
As described earlier, your Audio HW DLL must provide an entry point called
ctrl_init().
The
Organization of a Driver
chapter describes the initialization that this function must do no matter
what features your DLL supports.
In much the same way that we created a mixer device
in the previous chapter, we now create a PCM device
using the
ado_pcm_create()
function. This informs the upper levels of software
that this card now supports a PCM device.
If you call this function again, it creates additional devices.
The prototype of the ado_pcm_create() function is:
int32_t ado_pcm_create( ado_card_t *card,
char *name,
uint32_t flags,
char *id,
uint32_t play_subchns,
ado_pcm_cap_t *play_cap,
ado_pcm_hw_t *play_hw,
uint32_t cap_subchns,
ado_pcm_cap_t *cap_cap,
ado_pcm_hw_t *cap_hw,
ado_pcm_t **rpcm );
The arguments are:
- card
- The card argument that io-audio passed to your
Audio HW DLL's ctrl_init() function.
The library uses this argument as the card to link the new device onto.
- name, id
- Text names for the PCM device, usually a variation of the card name.
They're used only for information display by client applications.
- flags
- Information about the device for the use of client applications,
for example, indicating whether or not both the playback and capture
can be used at the same time.
These flags are informational only;
enforcing any of these conditions is done by code
and isn't based on these flags.
- play_subchns, cap_subchns
- The number of playback and capture subchannels supported.
If zero, the channel isn't supported.
- play_cap, cap_cap
- Structures listing the full capabilities of the device's playback
and capture channels.
These include format, rate, and voices
supported.
The upper driver layers use this information to verify a client request
before allowing the request to pass to the hardware.
This information is also passed back to the client
as the static capabilities of the device.
- play_hw, cap_hw
- Structures containing the playback and capture callback functions to be
called by the upper layers of the driver.
It's in these functions that you actually program the hardware.
For more information, see
“How does the PCM stream operate?”
later in this chapter.
- rpcm
- The location
in which to store a pointer to the internal PCM device structure.
You'll need this pointer for additional PCM function calls.
In order to make the PCM device work, you need to define the
callback functions in the
ado_pcm_hw_t
structures for the capture and playback portions of the PCM device.
Before we look at them in detail, let's first review
how a PCM stream operates in hardware.
The model used in this architecture
is a DMA buffer in memory that's divided
into two or more buffer fragments.
When instructed to do so, the hardware acts
on a fragment using DMA, and then generates an
interrupt on completing the fragment.
So, if we consider the simplified case of
playback with a 50K buffer, composed of two fragments,
here's what happens when the client application sends data:
- First the data is written into the DMA buffer
until both fragments are filled,
then the hardware is told to start playing the
first fragment, and to continue playing the fragments
in order until told to stop.
- When the hardware signals an interrupt,
meaning the first fragment has been completed,
io-audio puts more client data into the first fragment,
and the cycle continues.
- The driver stops the playback when the next fragment
to be played isn't filled with new data.
This is called an underrun condition.
From a programming perspective,
if the hardware can be set up to do a
looping DMA buffer playback with an interrupt every x bytes,
implementing this model is very straightforward.
A variation on this theme is to reprogram the
DMA engine after every fragment in the interrupt routine.
In the general case, the client suggests the fragment size
and number of fragments, but the driver has the
ultimate authority on these parameters.
Warning: main(/www/www/htdocs/style/footer.php) [function.main]: failed to open stream: No such file or directory in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 222
Warning: main() [function.include]: Failed opening '/www/www/htdocs/style/footer.php' for inclusion (include_path='.:/www/www/common:/www/www/php/lib/php') in /www/www/docs/6.4.1/ddk_en/audio/pcm.html on line 222