📄 epstub.c
字号:
/*
* FILENAME: EpStub.c
*
*/
#include "license.h"
#include "ipport.h"
#include "lpc23xx/type.h"
#include "lpc23xx/lpc230x.h"
#include "lpc23xx/irq.h"
#ifdef AUDIO_WEB_STUB
#define NO_DAC 1
/** #define WP_SOCKTYPE long **/
/* __P() - prototype masking
*
* ANSI compilers should have no problem with prototypes in function
* declarations, so by default we don't mask them.
*/
#define __P(x) x
#include "q.h"
#include "netbuf.h"
#include "net.h"
#include "ip.h"
#include "msock.h"
#include "mbuf.h"
#include "msring.h"
#include "menu.h"
int Ep_upcall(int code, M_SOCK so, void * datapkt);
void audiotimer_isr(void) __irq;
static void Audiotimerinit(void);
static void get_potval (void);
static void AudioADCinit(void);
#ifndef APP_NEWQLEN
#define APP_NEWQLEN 10 /* max # buffered new sessions */
#endif
#define MAXAUDIOQUEUE 2000
#define QFULL 0
#define QEMPTY 1
#define QUSE 2
#define ENDIENESS 0
/* Clock Definitions */
#define CPU_CLOCK 15000000 /* CPU Clock */
#define VPB_CLOCK (CPU_CLOCK/1) /* VPB Clock */
#define MILLISECONDTIMER (CPU_CLOCK /1175)
/* Audio Definitions */
#define DATA_FREQ (1 ) //44056//32000//11025// 44100 /* Audio Data Frequency */
/* LED Definitions */
#define LEDMSK 0x000000FF /* P2.0..7 */
static struct msring ht_msring;
static M_SOCK ht_msring_buf[APP_NEWQLEN + 1];
static short int AudioQueue[MAXAUDIOQUEUE];
static short int Tail=ENDIENESS;
static short int Head=ENDIENESS;
volatile static unsigned char QueueStatus =QEMPTY ;
static int DataRecv =FALSE;
static long DataOut =0;
DWORD Volume; /* Volume Level */
WORD PotVal; /* Potenciometer Value */
WORD VolCur = 0x0100; /* Volume Current Value */
/* HTTP_PORT - TCP port on which web server will listen.
* This definition provides a default, which may be overridden
* from webport.h or ipport.h.
*/
#ifndef AUDIO_PORT
#define AUDIO_PORT (0xeeee)
#endif /* HTTP_PORT */
struct sockaddr_in AdServersin;
WP_SOCKTYPE AudioSock = INVALID_SOCKET; /* our TCP listen socket */
unsigned long VUM=0;
typedef struct WavHeader
{
BYTE Riff[4];
DWORD FileLength;
BYTE wave[4];
BYTE format[4];
DWORD FormatChunk;
WORD formatcode;
WORD NoOfChannels;
DWORD SampleRate;
DWORD BytesPerSec;
WORD NoOfBytesPerSample;
WORD NoOfBitsPerSample;
BYTE data[4];
DWORD BytesOfWaveData;
}WavHeader;
WavHeader WavHeaderFormat;
#define ADSERVER_IDLE 0
#define ADSERVER_STOPPED 1
#define ADSERVER_RUNNING 2
volatile static int AdServer_state = ADSERVER_IDLE;
static M_SOCK sox;
/* FUNCTION: audioserver_init()
*
* audioserver_init() - this is called by the main init routines,
* at startup time. It opens a tcp socket to
* listen for web connections.
*
* PARAM1:
*
* RETURNS: Returns 0 if OK, non-zero if error.
*/
int
audioserver_init()
{
int e; /* error holder */
dprintf("\naudioserver_init\n");
/* set up queue and listen */
msring_init(&ht_msring, ht_msring_buf ,
sizeof(ht_msring_buf) / sizeof(ht_msring_buf[0]));
AdServersin.sin_addr.s_addr = 0; /* wildcard IP address */
AdServersin.sin_port = AUDIO_PORT; /* http port */
AudioSock = m_listen(&AdServersin, Ep_upcall, &e);
/* dprintf("AudioSock = %.8x\n", AudioSock); */
if (AudioSock == INVALID_SOCKET)
{
dprintf("*** Ep_init error %d (0x%x) starting listen on Ep server\n", e, e);
return -1;
}
/* put socket in non-blocking mode */
e = m_ioctl(AudioSock, SO_NBIO, NULL);
if (e != 0)
{
m_close(AudioSock);
dprintf("*** Ep_init error %d: m_ioctl\n", e);
return -1;
}
#if NO_DAC
Audiotimerinit();
AudioADCinit();
#endif
return 0;
}
int EpStrCmp(char* Source1,char* Source2,int Len)
{
int i=0;
for (i=0;i<Len;i++)
{
if(*Source1++ != *Source2++)
{
return 1;
}
}
return 0;
}
void SetSamplingRate(DWORD SamplingRate)
{
T1TCR = 2; /*reset*/
T1MR0 = ((MILLISECONDTIMER*1000)/SamplingRate)-1 ; /* TC0 Match Value 0 */
T1MCR = 3; /* TCO Interrupt and Reset on MR0 */
T1TCR = 1;
}
/*
* FUNCTION: Ep_upcall()
* Audio callback for tcp data and state changes
* Save pointer to pkt.
*
* RETURN: 0
*/
static int
Ep_upcall(int code, M_SOCK so, void * datapkt)
{
int retcode = 0;
PACKET pkt;
char *wrkP;
int i;
char* bufferaudio;
int FileStart =0;
/* are we active? */
if (AdServer_state != ADSERVER_RUNNING)
return 0; /* no */
switch(code)
{
case M_OPENOK: /* new socket is connected */
msring_add(&ht_msring, so);
break;
case M_CLOSED: /* TCP lost socket connection */
break; /* let stale conn timer catch these */
case M_RXDATA: /* received data packet */
pkt = (PACKET)datapkt;
wrkP = pkt->m_data;
/**********************************************/
bufferaudio = (char*)AudioQueue;
#if NO_DAC
while( QueueStatus == QFULL);
#endif
/*To check start of file*/
if(!EpStrCmp(wrkP,"RIFF",4))
{
memcpy((char*)&WavHeaderFormat,(const char*)wrkP,44);
SetSamplingRate(WavHeaderFormat.SampleRate);
FileStart =44;
}
else
{
FileStart =0;
}
for (i=0; i < (pkt->m_len-FileStart); )
{
QueueStatus = QEMPTY;//to avoid premtion problem
*(bufferaudio+(Tail++))= wrkP[i++];
*(bufferaudio+(Tail++))= wrkP[i++];
QueueStatus = QUSE;
if(Tail >= (MAXAUDIOQUEUE+MAXAUDIOQUEUE)) //short unsigned int
{
Tail =ENDIENESS;
}
if(Tail == Head && QueueStatus != QEMPTY)
{
QueueStatus = QFULL;
#if NO_DAC
while( QueueStatus == QFULL);
#endif
}
}
sox = so;
DataRecv = TRUE;
break;
case M_TXDATA: /* ready to send more */
retcode = -1; /* return nonzero code to indicate we don't want it */
break;
default:
dprintf("*** ht_upcall: default\n");
dtrap(); /* not a legal case */
return 0;
}
USE_VOID(datapkt);
return retcode;
}
/*
* FUNCTION: SendAck()
* check routine called from loop.
* This routine merely replies
* with a simple webpage to any
* HTTP GET or POST.
*
* RETURN: void
*/
void SendAck(void)
{
PACKET pktSend ;
int retcode;
char AckData[5]="ACK";
if(DataRecv == TRUE)
{
//To send ACk
pktSend = tcp_pktalloc(strlen(AckData) + 60);
if(pktSend == NULL)
{
dprintf("NULL POINTER\n");
}
strcpy(pktSend->m_data, AckData);
pktSend->m_len = strlen(AckData) + 1;
/* send it */
retcode = tcp_send(sox, pktSend);
if ((retcode == ENOTCONN) || (retcode == EWOULDBLOCK))
{
tcp_pktfree(pktSend);
dprintf("*** ht_upcall: tcp_send ENOTCONN or EWOULDBLOCK\n");
retcode = 0;
}
DataRecv = FALSE;
}
}
#ifndef SUPERLOOP
#include OSPORT_H
TK_OBJECT(to_webAudioport);
TK_ENTRY(tk_webAudioport);
//long webport_wakes = 0;
struct inet_taskinfo Audiotask = {
&to_webAudioport,
"web Audio server",
tk_webAudioport,
NET_PRIORITY,
WEB_STACK_SIZE,
};
/* The application thread works on a "controlled polling" basis:
* it wakes up periodically and polls for work.
*
* The Web Server task could aternativly be set up to use blocking sockets,
* in which case the loops below would only call the "xxx_check()"
* routines - suspending would be handled by the TCP code.
*/
/* FUNCTION: tk_webport()
*
* PARAM1: n/a
*
* RETURNS: n/a
*/
TK_ENTRY(tk_webAudioport)
{
while (!iniche_net_ready)
TK_SLEEP(1);
for (;;)
{
switch (AdServer_state)
{
case ADSERVER_IDLE:
if (audioserver_init() == 0)
AdServer_state = ADSERVER_RUNNING;
else
{
AdServer_state = ADSERVER_STOPPED;
}
break;
case ADSERVER_STOPPED:
break;
case ADSERVER_RUNNING:
SendAck(); /* give web server some cycles, probably block */
break;
}
tk_yield(); /* give up CPU in case it didn't block */
// webport_wakes++; /* count wakeups */
if (net_system_exit)
{
if (AdServer_state == ADSERVER_RUNNING)
{
m_close(AudioSock);
ht_msring.buflen = 0;
ht_msring.buf = 0;
dprintf("linstener stopped.\n");
AdServer_state = ADSERVER_STOPPED;
}
break;
}
}
TK_RETURN_OK();
}
/*
* Get Potenciometer Value
*/
static void get_potval (void) {
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);
}
void audiotimer_isr(void) __irq
{
long int val;
static unsigned long Tick=0 ;
if (QueueStatus != QEMPTY)
{ /* Data Stream is running */
val = AudioQueue[DataOut];
DataOut++; /* Update Data Out Index */
Head+=2;
if( Head >=( MAXAUDIOQUEUE+MAXAUDIOQUEUE))
{
Head =ENDIENESS;
}
if( (Head == Tail) )
{
QueueStatus = QEMPTY;
}
if( QueueStatus == QFULL)
{
QueueStatus = QUSE;
}
if( DataOut >= MAXAUDIOQUEUE) /* Get Audio Sample */
{
DataOut=0;
}
if (val < 0) VUM -= val; /* Accumulate Neg Value */
else VUM += val; /* Accumulate Pos Value */
val *= (Volume ); //maximum volume
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 */
// }
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 */
FIO2CLR = LEDMSK; /* Turn Off all LEDs */
FIO2SET = LEDMSK >> (7 - val); /* LEDs show VU Meter */
}
T1IR = 1; /* Clear Interrupt Flag */
VICVectAddr = 0; /* Acknowledge Interrupt */
}
static void Audiotimerinit(void)
{
/* Setup Timer Counter 0: Periodic Timer with Interrupt at DATA_FREQ Rate */
T1MR0 = (*1000)-1 ; /* TC0 Match Value 0 */
T1MCR = 3; /* TCO Interrupt and Reset on MR0 */
T1TCR = 1;
/* clear all the other control registers */
/* set up the interrupt handler */
if (install_irq(TIMER1_INT, (void *)&audiotimer_isr, 0x03) < 0)
dtrap();
}
static void AudioADCinit(void)
{
PCONP |= (1 << 12); /* Enable power to AD block */
AD0CR = 0x00200E01; /* ADC: 10-bit AIN0 @ 4MHz */
}
#endif /* SUPERLOOP */
#endif /* AUDIO_WEB_STUB */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -