📄 usbaudio.c
字号:
/*----------------------------------------------------------------------------
* Name: DEMO.C
* Purpose: USB Audio Demo
* Version: V1.10
*----------------------------------------------------------------------------
* This software is supplied "AS IS" without any warranties, express,
* implied or statutory, including but not limited to the implied
* warranties of fitness for purpose, satisfactory quality and
* noninfringement. Keil extends you a royalty-free right to reproduce
* and distribute executable files created using this software for use
* on Philips LPC2xxx microcontroller devices only. Nothing else gives
* you the right to use this software.
*
* Copyright (c) 2005-2006 Keil Software.
*---------------------------------------------------------------------------*/
#include <LPC230X.H> /* LPC230x definitions */
#include "type.h"
#include "usb.h"
#include "usbcfg.h"
#include "usbhw.h"
#include "usbcore.h"
#include "target.h"
#include "irq.h"
#include "usbaudio.h"
#define ADC_POLLING 0
BYTE Mute; /* Mute State */
DWORD Volume; /* Volume Level */
BYTE AudioON = 1; /* Controlled by WEB server */
#if USB_DMA
#if KEIL_IDE
DWORD InfoBuf[P_C] __at DMA_BUF_ADR; /* Packet Info Buffer */
short DataBuf[B_S] __at (DMA_BUF_ADR+4*P_C);/* Data Buffer */
#else
DWORD *InfoBuf = (DWORD *)(DMA_BUF_ADR);
short *DataBuf = (short *)(DMA_BUF_ADR + 4*P_C);
#endif
#else
short DataBuf[B_S]; /* Data Buffer */
#endif
WORD DataOut; /* Data Out Index */
WORD DataIn; /* Data In Index */
BYTE DataRun; /* Data Stream Run State */
WORD PotVal; /* Potenciometer Value */
DWORD VUM; /* VU Meter */
DWORD Tick; /* Time Tick */
/*
* Timer Counter 0 Interrupt Service Routine
* executed each 31.25us (32kHz frequency)
*/
volatile DWORD ADC0Value;
volatile DWORD ADC0IntDone = 0;
/******************************************************************************
** Function name: ADC0Handler
**
** Descriptions: ADC0 interrupt handler
**
** parameters: None
** Returned value: None
**
******************************************************************************/
void ADC0Handler (void) __irq
{
DWORD regVal;
IENABLE; /* handles nested interrupt */
regVal = AD0STAT; /* Read ADC will clear the interrupt */
if ( regVal & (1 << 16) )
{
switch ( regVal & 0xFF ) /* check DONE bit */
{
case 0x01:
ADC0Value = AD0DR0;
ADC0IntDone = 1;
break;
default:
break;
}
AD0CR &= 0xF8FFFFFF; /* stop ADC now */
}
IDISABLE;
VICVectAddr = 0; /* Acknowledge Interrupt */
}
/*
* Get Potenciometer Value
*/
void get_potval (void) {
#if ADC_POLLING
DWORD val;
AD0CR |= 0x01000000; /* Start A/D Conversion */
do {
val = AD0GDR; /* Read A/D Data Register */
} while ((val & 0x80000000) == 0); /* Wait for end of A/D Conversion */
AD0CR &= ~0x01000000; /* Stop A/D Conversion */
PotVal = ((val >> 8) & 0xF8) + /* Extract Potenciometer Value */
((val >> 7) & 0x08);
// PotVal = (val >> 6);
#else
if ( ADC0IntDone )
{
ADC0IntDone = 0;
PotVal = ((ADC0Value >> 8) & 0xF8) + /* Extract Potenciometer Value */
((ADC0Value >> 7) & 0x08);
// PotVal = (ADC0Value >> 6);
}
#endif
return;
}
/*
* Timer Counter 0 Interrupt Service Routine
* executed each 31.25us (32kHz frequency)
*/
void TIMER0_ISR (void) __irq {
long val;
DWORD cnt;
#if !ADC_POLLING
AD0CR |= (1 << 24 );
#endif
if (DataRun) { /* Data Stream is running */
val = DataBuf[DataOut]; /* Get Audio Sample */
cnt = (DataIn - DataOut) & (B_S - 1); /* Buffer Data Count */
if (cnt == (B_S - P_C*P_S)) { /* Too much Data in Buffer */
DataOut++; /* Skip one Sample */
}
if (cnt > (P_C*P_S)) { /* Still enough Data in Buffer */
DataOut++; /* Update Data Out Index */
}
DataOut &= B_S - 1; /* Adjust Buffer Out Index */
if (val < 0) VUM -= val; /* Accumulate Neg Value */
else VUM += val; /* Accumulate Pos Value */
val *= Volume; /* Apply Volume Level */
val >>= 16; /* Adjust Value */
val += 0x8000; /* Add Bias */
val &= 0xFFFF; /* Mask Value */
} else {
val = 0x8000; /* DAC Middle Point */
}
if (Mute) {
val = 0x8000; /* DAC Middle Point */
}
if ( !AudioON )
{
val = 0x8000;
}
DACR = val & 0xFFC0; /* Set Speaker Output */
if ((Tick++ & 0x03FF) == 0) { /* On every 1024th Tick */
get_potval(); /* Get Potenciometer Value */
if (VolCur == 0x8000) { /* Check for Minimum Level */
Volume = 0; /* No Sound */
} else {
Volume = VolCur * PotVal; /* Chained Volume Level */
}
val = VUM >> 20; /* Scale Accumulated Value */
VUM = 0; /* Clear VUM */
if (val > 7) val = 7; /* Limit Value */
// IOCLR2 = LEDMSK; /* Turn Off all LEDs */
// IOSET2 = LEDMSK >> (7 - val); /* LEDs show VU Meter */
}
T0IR = 1; /* Clear Interrupt Flag */
VICVectAddr = 0; /* Acknowledge Interrupt */
}
/* Main Program */
DWORD usbaudioInit(void) {
PINSEL1 &= ~0x0030C000; /* P0.23, A0.0, function 01, P0.26 AOUT, function 10 */
PINSEL1 |= 0x00204000;
// IODIR2 = LEDMSK; /* LED's defined as Outputs */
/* Enable CLOCK into ADC controller */
PCONP |= (1 << 12);
AD0CR = 0x00200E01; /* ADC: 10-bit AIN0 @ 4MHz */
#if !ADC_POLLING
AD0INTEN = 0x001; /* Enable ADC0 */
if ( install_irq( ADC0_INT, (void *)ADC0Handler, HIGHEST_PRIORITY ) == FALSE )
{
return (FALSE);
}
#endif
DACR = 0x00008000; /* DAC Output set to Middle Point */
/* Setup Timer Counter 0: Periodic Timer with Interrupt at DATA_FREQ Rate */
T0MR0 = Fpclk/DATA_FREQ - 1; /* TC0 Match Value 0 */
T0MCR = 3; /* TCO Interrupt and Reset on MR0 */
T0TCR = 1; /* TC0 Enable */
/* Setup Timer Counter 0 Interrupt */
install_irq( TIMER0_INT, (void *)TIMER0_ISR, HIGHEST_PRIORITY );
USB_Init(); /* USB Initialization */
USB_Connect(TRUE); /* USB Connect */
return ( TRUE );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -