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

📄 timing.c

📁 Source Code for the Flash Audio Head Unit Player
💻 C
字号:
/* 
**  PHILIPS ARM 2005 DESIGN CONTEST
**  ENTRY AR1757
**  FLASH CARD AUDIO PLAYER FOR HEAD END UNIT
**                                                                          
**  TIMING.C:  Timer and Internal / Stereo DAC output generation                                
** 
** 
*/                                                                           


#include <LPC213X.H>                          // LPC21XX Peripheral Registers
#include "timing.h"
#include "types.h"
#include <string.h>

// define this to use inbuilt 10-bit DAC, otherwise use the TLV320DAC23
#define INTERNAL_DAC

// P0.20 is the LRCLK
#define LRCLK_PIN (1L<<20)

static volatile u32 timeval;
static u16 ticks_per_sec;
   
// double sample buffers	
static s16 buffer0[BUFSIZE],buffer1[BUFSIZE],*p;
// current read counter
static u16 cnt=BUFSIZE;
// current sample rate
static int CurrentHz=0;
static volatile u16 buffer_done=0,buffer_active=0;

/* Timer Counter 0 Interrupt executes nominally at 44100 Hz or 88200 Hz for external DAC */

static void tc0 (void) __attribute__ ((interrupt));

static void tc0 (void)
{
#ifdef INTERNAL_DAC
	static s16 x;

	// combine left and right channel for mono output
	x=(*p++ ) >> 1 ;
	x+=(*p++) >> 1;
   DACR		  = 32768+x;
			
  if(!--cnt)
  {
    // swap buffers
  	cnt=BUFSIZE>>1;
	buffer_active ^= 1;
	if(!buffer_active)
		p=buffer0;
	else
		p=buffer1;
	buffer_done=1;
	timeval++;
  }
   		
#else

  // Toggle LRCLK according to sample
  if(cnt & 1)
  	IOSET0 = LRCLK_PIN;
  else
    IOCLR0 = LRCLK_PIN;

  // Load 16-bit sample into output FIFO.. this starts transmission
  SSPDR	 = *p++;

  // Count down and swap over buffers at end				
  if(!--cnt)
  {
    // swap buffers
  	cnt=BUFSIZE;
	buffer_active ^= 1;
	if(!buffer_active)
		p=buffer0;
	else
		p=buffer1;
	buffer_done=1;

	// Timing function
	timeval++;
  }
   		
#endif
      

  T0IR        = 1;                            // Clear interrupt flag
  VICVectAddr = 0xff;                            // Acknowledge Interrupt
} 

// clear buffers to zero values
void clear_buffers(void)
{
	memset(buffer0, 0, sizeof(buffer0));
	memset(buffer1, 0, sizeof(buffer1));
}

// change the dac sampling rate based on a 60MHz clock
void set_dac_rate(int Hz)
{
  if(Hz != CurrentHz)
  {
   
  CurrentHz=Hz;

  T0TCR = 2;                                  // Timer0 Disable & reset

#ifdef INTERNAL_DAC
	T0MR0 = 15000000L / Hz;	
	ticks_per_sec = (256*Hz) / (BUFSIZE>>1);
#else
	T0MR0 = 15000000L / (Hz<<1);	
	ticks_per_sec = (256*(Hz<<1)) / (BUFSIZE>>1);
#endif
  
  T0IR        = 1;                            // Clear interrupt flag
  VICVectAddr = 0;                            // Acknowledge Interrupt
  T0TCR = 1;                                  // Timer0 Enable
  }

}

// mark time point
u32 mark(void)
{
	return timeval;
}

u32 elapsed_sec(u32 timemark)
{
	return (256 * (mark() - timemark)) / ticks_per_sec;
}

// delay ticks function
void delay (int ticks)  
{                             
  u32 i;

  i = mark();
  while ((mark() - i) < ticks);                  
}

// get free sample buffer	
s16 *get_buffer(int (*poll_fn)())
{
	do 
	{
		if(poll_fn())
		{
			// abort
		    clear_buffers();

			return NULL;
		}
	}
	while(!buffer_done) ;
	
	buffer_done=0;

	if(!buffer_active)
		return buffer1;
	else
		return buffer0;
}

#define I2C_EN 64
#define I2C_START 32
#define I2C_STOP 16
#define I2C_SI 8
#define I2C_AA 4

#define DAC_ADDR 26

// Write to a nominated external DAC register via I2C bus
static bool write_dac(u8 reg,u16 value)
{
	bool lsb_sent=FALSE;

	I20CONCLR = I2C_START|I2C_STOP|I2C_SI|I2C_AA;	// Clear STA, STOP, SI, AA
	I20CONSET = I2C_EN;			// I2EN

	I20CONSET = I2C_START;		// Start bit

	// Form 16-bit write value for DAC
	value = (value & 511) | (reg << 9);

	for(;;)
	{
	 while(!(I20CONSET & I2C_SI)) ;

	 switch(I20STAT) {
	 	case 0x08:
		case 0x10:
			I20DAT = DAC_ADDR << 1;			// send address with write request
			I20CONCLR = I2C_STOP | I2C_SI;	// clear SI and STOP bit
			lsb_sent=FALSE;
			break;
 		case 0x18:
			I20DAT = (u8)(value >> 8);
			I20CONCLR =  I2C_STOP | I2C_SI | I2C_START;	// clear SI and STOP and START bit
			break;
		case 0x38:
			I20CONCLR = I2C_STOP | I2C_SI;
			I20CONSET = I2C_START;
			break;
		case 0x28:
			if(!lsb_sent)
			{
				I20DAT = (u8)value;
				lsb_sent=TRUE;
				I20CONCLR =  I2C_STOP | I2C_SI | I2C_START;	// clear SI and STOP and START bit
			}
			else
			{
				I20CONSET = I2C_STOP;
				I20CONCLR = I2C_SI | I2C_START;
				return TRUE;
			}
		case 0x20:
		case 0x30:
	 	default:
			I20CONCLR = I2C_STOP | I2C_SI | I2C_START;
			return FALSE; 
		}
	}
	 
	return FALSE;
}



/* Setup the DAC/Timing Interrupt */
void init_timing (void) 
{
	clear_buffers();

  // configure SPI1 for SPI CPOL=1 CPHA=0 16-bit format, maximum frequency
  SSPCR0 = 64|15;
  // maximum frequency 15 MHz (PCLK=60MHz/4)
  SSPCPSR = 1;	
  // configure master mode and enable
  SSPCR1 = 2;

  // DAC I2C initialisation

  // Set SCLK to 375kHz
  I20SCLH = 20;
  I20SCLL = 20;

#ifndef INTERNAL_DAC

  write_dac(0, 0x80);	// left not muted, simultaneous update
  write_dac(1, 0x80);	// right not muted, simultaneous update
  write_dac(2, 0x80 | 0x20 | 0x10); // left headphone output muted
  write_dac(3, 0x80 | 0x20 | 0x10); // right headphone output muted
  write_dac(4, 0x10);   // dac on
  write_dac(5, 8|4) ;   // soft mute, de-emphasis 44.1kHz
  write_dac(6, 4|2|1);      // power on, clk, osc, output, dac
  write_dac(7, 1);      // left justified, slave mode, 16-bit data
  write_dac(8, 0x20 | 2 | 1);      // usb mode, filter type=1, sample rate=44.118 khz

#endif
 
  // Enable internal DAC output  	
  PINSEL1 = (PINSEL1 | (1L<<19)) & ~(1L<<18);		
 
  // Enable SSP pins SCLK (P0.17), MISO (P0.18), MOSI (P0.19)
  PINSEL1 = (PINSEL1 | (1L<<3) | (1L<<5) | (1L<<7)) & ~((1L<<2) | (1L<<4) | (1L<<6));

  // Make SSEL (P0.20) a GPIO output for LRCLK
  IODIR0 |= LRCLK_PIN;
  IOCLR0 =LRCLK_PIN;

	// set interrupt vector in 0
	VICVectAddr0 = (unsigned long)tc0;          

  buffer_active=0;
  p=buffer0;
#ifdef INTERNAL_DAC
  cnt=BUFSIZE>>1;
#else
  cnt=BUFSIZE;
#endif

  buffer_done=1;

  T0MCR = 3;                                  // Interrupt and Reset on MR0

  // default settings
  set_dac_rate(44100);
	
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt

  VICIntEnable |= 0x00000010;                  // Enable Timer0 Interrupts
 
}
  
// 
// software timing loop for non-irq based timing during initialisation
//
void delay_100ms(void)
{
	u32 i;
	
	for(i=0;i<2000000L;i++) ;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -