📄 ac97_example.c
字号:
/***********************************************************************
* $Workfile: ac97_example.c $
* $Revision: 1.3 $
* $Author: WellsK $
* $Date: Oct 01 2003 12:03:58 $
*
* Project: AC97 interrupt driven driver example
*
* Description:
* A AC97 driver (interrupt mode) example.
*
* Revision History:
* $Log: //smaicnt2/pvcs/VM/sharpmcu/archives/sharpmcu/software/csps/lh7a404/bsps/sdk7a404/examples/ac97_int_record/ac97_example.c-arc $
*
* Rev 1.3 Oct 01 2003 12:03:58 WellsK
* Added logic to get TTB address from register CP15 TTB.
*
* Rev 1.2 Sep 18 2003 09:26:14 WellsK
* Updated example for MMU and VIC driver changes.
*
* Rev 1.1 Jul 18 2003 09:35:54 WellsK
* Added reset of CODEC after ac97_open() command.
*
* Rev 1.0 Jul 07 2003 09:43:56 WellsK
* Initial revision.
*
*
***********************************************************************
* SHARP MICROELECTRONICS OF THE AMERICAS MAKES NO REPRESENTATION
* OR WARRANTIES WITH RESPECT TO THE PERFORMANCE OF THIS SOFTWARE,
* AND SPECIFICALLY DISCLAIMS ANY RESPONSIBILITY FOR ANY DAMAGES,
* SPECIAL OR CONSEQUENTIAL, CONNECTED WITH THE USE OF THIS SOFTWARE.
*
* SHARP MICROELECTRONICS OF THE AMERICAS PROVIDES THIS SOFTWARE SOLELY
* FOR THE PURPOSE OF SOFTWARE DEVELOPMENT INCORPORATING THE USE OF A
* SHARP MICROCONTROLLER OR SYSTEM-ON-CHIP PRODUCT. USE OF THIS SOURCE
* FILE IMPLIES ACCEPTANCE OF THESE CONDITIONS.
*
* COPYRIGHT (C) 2001 SHARP MICROELECTRONICS OF THE AMERICAS, INC.
* CAMAS, WA
**********************************************************************/
#include "abl_types.h"
#include "abl_irq_fiq.h"
#include "abl_arm922t_cp15_driver.h"
#include "lh7a404_ac97_driver.h"
#include "lh7a404_timer_driver.h"
#include "lh7a404_vic_driver.h"
#include "sdk7a404_cpld_driver.h"
/* Number of samples to store */
#define SAMPLE_COUNT 70000
/* Sample storage buffer */
UNS_32 data_samples[SAMPLE_COUNT];
/***********************************************************************
*
* Function: c_entry
*
* Purpose: Interrupt driven AC97 driver example
*
* Processing:
* See function. This example sets up the CODEC to play a record a
* stereo on the line input and play it back on the PCM output.
*
* Parameters: None
*
* Outputs: None
*
* Returns: Always returns 1
*
* Notes: None
*
**********************************************************************/
int c_entry(void)
{
INT_32 xa, ac97dev1;
AC97_VOLUME_T vol;
AC97_MIX_GAIN_T mix;
AC97_TONE_T tone;
AC97_CHANNEL_CONFIG_T chcfg;
AC97_REC_GAIN_T recgain;
AC97_BKG_T ac97int;
/* Disable interrupts */
disable_irq_fiq();
/* Initialize CPLD */
cpld_init();
/* Set virtual address of MMU table (needed for VIC driver
functions) */
cp15_set_vmmu_addr((UNS_32 *) cp15_get_ttb());
/* Initialize interrupt system */
vic_initialize(0xC0000000);
/* Install standard IRQ dispatcher at ARM IRQ vector */
vic_install_arm_handler(IRQ_VEC, (PFV) vic_arm_irq_dispatcher);
/* Install VIC1 and VIC2 handlers */
vic_install_arm_handler(VIC1_IRQ_VEC, (PFV) vic1_irq_dispatcher);
vic_install_arm_handler(VIC2_IRQ_VEC, (PFV) vic2_irq_dispatcher);
/* Install AC97 handler in the IRQ dispatcher */
vic_install_handler(VIC_AACINTR, VIC_IRQ, (PFV) ac97_isr);
/* Open the AC97 controller channel #1 */
if ((ac97dev1 = ac97_open(AAC, 0)) == (INT_32) NULL)
{
return 0;
}
/* Reset AC97 CODEC power and allow a small delay (300mS) for
device to re-initialize correctly */
ac97_ioctl(ac97dev1, AC97_DO_RESET, 1);
timer_wait_us(TIMER1, (300 * 1000));
/* Enable IRQ interrupts in the ARM core */
enable_irq();
/* Enable AC97 interrupt in the interrupt controller */
vic_int_enable(VIC_AACINTR, TRUE);
/* Set CODEC volumes to MAX (all CODEC outputs) */
vol.mute = FALSE;
vol.left = AC97_MAX_VOL;
vol.right = AC97_MAX_VOL;
vol.select = MASTER_OUT;
ac97_ioctl(ac97dev1, AC97_SET_VOL, (INT_32) &vol);
vol.select = AUX_OUT;
ac97_ioctl(ac97dev1, AC97_SET_VOL, (INT_32) &vol);
vol.select = MONO_OUT;
ac97_ioctl(ac97dev1, AC97_SET_VOL, (INT_32) &vol);
/* Mute all CODEC mixer channels */
mix.mute = FALSE;
mix.left = AC97_MIX_GN_MAX; // TBD MAX GAIN SB MIN
mix.right = AC97_MIX_GN_MAX; // TBD MAX GAIN SB MIN
for (xa = BEEP_OUT; xa < PCM_OUT; xa++)
{
mix.select = (AC97_MIX_GAIN_SEL_T) xa;
ac97_ioctl(ac97dev1, AC97_SET_MIXGAIN, (INT_32) &mix);
}
/* Set PCM output channel to max gain in mixer (volume) */
mix.mute = FALSE;
mix.left = AC97_REC_GN_MAX;
mix.right = AC97_REC_GN_MAX;
mix.select = PCM_OUT;
ac97_ioctl(ac97dev1, AC97_SET_MIXGAIN, (INT_32) &mix);
/* Use maximum gain for line input */
mix.select = LINE_IN;
ac97_ioctl(ac97dev1, AC97_SET_MIXGAIN, (INT_32) &mix);
/* Select line in as the recording device */
ac97_ioctl(ac97dev1, AC97_SET_RCHAN, (INT_32) LINE_IN_SEL);
/* Set maximum recording gain */
recgain.left_gain = 0x0008; /* Nominal gain */
recgain.right_gain = 0x0008; /* Nominal gain */
ac97_ioctl(ac97dev1, AC97_SET_RECGAIN, (INT_32) &recgain);
/* Set bass and treble tone control to bypass - this is not
supported on the Wolfson 9708 CODEC, but there should be no
problems attempting to issue the command */
tone.bass_gain = AC97_TONE_BYPASS;
tone.treble_gain = AC97_TONE_BYPASS;
ac97_ioctl(ac97dev1, AC97_SET_TONE, (INT_32) &tone);
/* Record sample using interrupts */
chcfg.srate = BPSEC_8000;
chcfg.ssize = BPSAM_16;
chcfg.channels = 2;
chcfg.compact = FALSE;
chcfg.dir = RECORD;
chcfg.tmode = AC97_INTERRUPT;
ac97_ioctl(ac97dev1, AC97_SET_CHANNEL, (INT_32) &chcfg);
/* Setup record configuration */
ac97int.buffer = data_samples;
ac97int.transfer_size = SAMPLE_COUNT;
ac97int.transfer_trip_size = 0xFFFFFFFF;
ac97int.funcptr = (AC97_CB_FUNC_T) NULL;
/* Start audio record of data */
ac97_ioctl(ac97dev1, AC97_INT_START, (INT_32) &ac97int);
/* Wait for channel to go idle */
while (ac97_ioctl(ac97dev1, AC97_GET_STATUS, AC97_CHANNEL_ST) !=
CH_IDLE);
/* Mute the line in channel */
mix.mute = TRUE;
ac97_ioctl(ac97dev1, AC97_SET_MIXGAIN, (INT_32) &mix);
/* Now configure the channel for playback using interrupts */
chcfg.dir = PLAYBACK;
ac97_ioctl(ac97dev1, AC97_SET_CHANNEL, (INT_32) &chcfg);
/* Setup playback configuration */
ac97int.buffer = data_samples;
ac97int.transfer_size = SAMPLE_COUNT;
ac97int.transfer_trip_size = 0xFFFFFFFF;
ac97int.funcptr = (AC97_CB_FUNC_T) NULL;
/* Play the data back */
ac97_ioctl(ac97dev1, AC97_INT_START, (INT_32) &ac97int);
/* Wait for channel to go idle */
while (ac97_ioctl(ac97dev1, AC97_GET_STATUS, AC97_CHANNEL_ST) !=
CH_IDLE);
/* Disable AC97 interrupt in the interrupt controller */
vic_int_enable(VIC_AACINTR, FALSE);
/* Disable ARM core IRQ interrupts */
disable_irq();
return 1;
}
#ifndef __GNUC__
/* With ARM and GHS toolsets, the entry point is main() - this will
allow the linker to generate wrapper code to setup stacks, allocate
heap area, and initialize and copy code and data segments. For GNU
toolsets, the entry point is through __start() in the crt0_gnu.asm
file, and that startup code will setup stacks and data */
int main(void)
{
return c_entry();
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -