⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 epstub.c

📁 Audio driver. This audio driver is developed on lpc2368.This used to develop audio system on LPC23xx
💻 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 + -