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

📄 an_gen_6x8_1_c_listing.c

📁 CMX618/CMX638声码器操作源码
💻 C
📖 第 1 页 / 共 2 页
字号:
//********************************
// PROJECT:			CMX618 Encode/Decode Data Exchange with Serial Flash
//
// FILE:			MAIN.C
//
// PROCESSOR:			AT89C2051
//
// LAST MODIFIED:		July 10, 2008
//
// COMMENTS:
// The purpose of this project is to:
// - receive encoded data (with FEC) from the CMX618 (on EV6180)
// - write 243 bytes of encoded data to a serial flash device (Winbond W25X80)
// - read out the data from the serial flash.
// - pass the data to the CMX618 decoder for playback
//
// C-BUS and SPI communications are "bit banged" from processor.
//********************************

#include <REG2051.H>		    // header file for AT89C2051

//CMX618 Register Mapping
#define RESET 		0x01
#define SYNC		0x02
#define SYNCCTRL	0x04
#define AIG		0x05
#define AOG		0x06
#define VCFG		0x07
#define MVCFG		0x2C
#define SDTMF		0x08
#define POWERSAVE	0x09
#define DTMFATTEN	0x0A
#define EXCODECCONT	0x0B
#define IDD		0x0C
#define SVCREQ		0x0E
#define FRAMETYPEW	0x0F
#define DECFRAME	0x10
#define ECFIFO		0x24
#define SVCACK		0x2E
#define FRAMETYPER	0x2F
#define ENCFRAME	0x30
#define VCTRL		0x11
#define MVCTRL		0x3C
#define EXCODECCMD	0x12
#define CLOCK		0x1D
#define VDWHLWM		0x1E
#define IRQENAB		0x1F
#define DFRAMEDATA	0x37
#define EFRAMEDATA	0x38
#define STATUS		0x40

//CMX618 VCFG Register Definitions
#define HDD 		0x20				//selects "hard bits" for decoding
#define FEC		0x10				//enables FEC
#define _80MSEC		0x00
#define _60MSEC		0x03
#define _40MSEC		0x02
#define _20MSEC		0x01
#define _2750BPS	0x08
#define _2400BPS 	0x04
#define _2050BPS	0x00

//CMX618 VCTRL Register Definitions
#define DVDW		0x0010				//enables "Vocoder Data Wanted" function
#define ENC		0x0002				//enables CMX618 encoder				  		
#define DEC		0x0001				//enables CMX618 decoder
#define SLEEP		0x0000				//stop encoder & decoder

//CMX618 POWERSAVE Register Definitions
#define CODEC		0x02
#define BIAS		0x01

//CMX618 IRQENAB Register Definitions
#define RDY		0x8000				//Ready (for new commands)
#define VDW		0x0100				//Vocoder Data Wanted (decode mode)
#define VDA		0x0001				//Vocoder Data Available (encode mode)

//Flash Definitions
#define WRITE_ENABLE	0x06
#define CHIP_ERASE	0xC7
#define PAGE_PROGRAM	0x02
#define READ_DATA	0x03
#define READ_STATUS	0x05
#define BUSY		0x01

#define APPEND_ONE	0x01
#define APPEND_ZERO	0xFE
#define BYTELENGTH	27			//length of CMX618 encode packet, in bytes
						//adjustment of BYTELENGTH will result in...
						//...adjustment of writes to flash and addressing scheme
#define ON 	0
#define OFF 	1

//Function Declarations
void initialize_618(void);
void initialize_uC(void);
void spi_write(unsigned char xbyte);
unsigned char spi_read(void);
void erase_flash(void);
void program_flash(unsigned char add1, unsigned char add2, unsigned char add3);
void read_flash(unsigned char m, unsigned char n, unsigned char p);
void encode_process(void);
void decode_process(void);

//C-BUS Function Declarations
void wr_byte(unsigned char byte);
void wr1(unsigned char address, unsigned char databyte);
void wr2(unsigned char address, unsigned int dataword);
unsigned char rd_byte(void);
unsigned char rd1(unsigned char address);
unsigned int rd2(unsigned char address);

//User Interface Pin Mapping
sbit ENCSWITCH	= P3^7;				
sbit DECSWITCH	= P1^0;
sbit LED1   	= P1^4;
sbit LED2	= P1^3;
sbit LED3	= P1^2;
sbit RED_LED	= P1^1;

//C-BUS to uC Pin Mapping
sbit CSN	= P3^5;
sbit CDATA	= P3^4;
sbit RDATA 	= P3^3;
sbit IRQ	= P3^2;		  	//externally triggered IRQ pin
sbit SCLK	= P3^1;		   	//supplies CLK to CMX618 (C-BUS) and flash

//Flash to uC Pin Mapping
sbit SS 	= P1^7;
sbit DO 	= P1^6;
sbit DI		= P1^5;
//The CLK line for flash is fed by the SCLK used by C-BUS

//Global Variables
unsigned int timer1_counter=0;			//counter allows for a wide variety of delays
unsigned char CMX618_data[BYTELENGTH]; 		//array for CMX618 encoded & decoded data 
unsigned char ENCODE_ADDRESS_HIGH=0x00;		//counters for flash "page program" address increment
unsigned char ENCODE_ADDRESS_MID=0x00;
unsigned char ENCODE_ADDRESS_LOW=0x00;	
unsigned char DECODE_ADDRESS_HIGH=0x00;		//counters for flash "read data" address increment
unsigned char DECODE_ADDRESS_MID=0x00;
unsigned char DECODE_ADDRESS_LOW=0x00;
unsigned char spi_data=0;  			//data received from the SPI port ("slave in")
unsigned char state=0;				//state variable: 0=config, 1=encode, 2=decode, 3=powersave

//Global Flags
bit timer1_expired=0;				//flag for 20s & 100ms delay
bit busy=1;					//flag for flash task completion
bit rdy=0;					//CMX618 RDY bit in Status Register
bit decode_complete=0;				//flag for decode completion
bit CMX618IRQ=0;

//********************************
//FUNCTION:
void initialize_618(void)
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: CMX618 configured as follows:
// - 2400bps encode + 1200bps FEC = 3600bps = 216bits (27 bytes) in a 60ms frame
// - CMX618 on EV6180 uses 12MHz xtal.
// - IRQENAB is not written here but is instead written within "main" during encode and decode sections. 
// - IDD delay register is not adjusted, so 8ms default delay is used.
// - SYNCCTRL register is not written because VDA(encode) and VDW(decode) IRQs control data pacing.
//********************************
{
//Only IRQ that is enabled on powerup is RDY
//IRQ will exist here due to hard reset
  rd2(STATUS);		//clear IRQ from hard reset
  rdy=0;		//reset RDY flag

//Perform software reset
  CSN=0;
   wr_byte(RESET);
  CSN=1;

//Wait for RDY bit before subsequent commands 
  while(!rdy);		//wait for RDY bit
  rdy=0;		//clear flags

//Basic CMX618 adjustments
  wr2(CLOCK, 0x0005);		
  wr1(POWERSAVE, (CODEC | BIAS));		
  wr1(VCFG, (HDD | FEC | _2400BPS | _60MSEC));	

  while(!rdy);		//Wait for configuration to complete...
  rdy=0;		
//NOTE: A check of SVCACK ($2E) b0 can be made at this point for debug purposes.
//SVCACK b0 only has meaning after a service has been performed and RDY has been asserted.
//If SVCACK b0 is not equal to 1 after RDY is asserted, an error has been made.
//In this case, a General Reset should be issued and device configuration restarted.

//Wait 100ms for Vbias to stabilize...
  timer1_counter=5;		   		//20ms x 5 = 100ms delay
  timer1_expired=0;				//clear flag
  TR1=1;					//turn on Timer 1
  while(!timer1_expired);
  timer1_expired=0;

//Input and output gains...
  wr1(AIG, 0x8F);				//Mic amp=20dB, I/P gain=22.5dB 
  wr1(AOG, 0x07);				//Earpiece gain=0dB, O/P gain=0dB

//High and low watermarks for VDW bit
  wr2(VDWHLWM, 0x809E);				//High watermark=0x9E=158 samples as per datasheet example
    while(!rdy);	
    rdy=0;			
  wr2(VDWHLWM, 0x0048);				//Low watermark=0x48=72 samples as per datasheet example
    while(!rdy);	
    rdy=0;		
}

//********************************
//FUNCTION:  
void initialize_uC(void)
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: 
// INT0 used for CMX618 IRQ detection (falling edge triggered).
// Timer 1 used for:
// - switch debouncing
// - 20sec Chip Erase lockup prevention
// - 100ms CMX618 delay for Vbias to stabilize during configuration.
//********************************
{
 IE=0x89;					// Enabled IRQs; Global, Timer 1, EX0.
 IT0=1;						// INT0 (for CMX618 C-BUS IRQ) falling-edge triggered

//Timer configuration
 TMOD=0x10;					// Timer 1 in 16-bit timer (Mode 1)
 TH1=0xB8;					// Timer 1 = 18432 counts = 20ms
 TL1=0x00;

//Configure pins as inputs
 P1=P1 | 0x0F;					//write 1s to lower nibble for LEDs
 P3_7=1;					//switch configured as input 
 IRQ=1;
 DO=1;
}



//********************************
//FUNCTION:
void CMX618_IRQ() interrupt 0
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: Ext INT0 Interrupt Servide Routine.
// The Status register is read, and the "state" variable determines which bits will be checked.
//********************************
{
 unsigned int temp=0x0000;
 temp=rd2(STATUS);
 switch(state)
 {
  case 0:	//configuration mode, check for RDY bit
    if((temp & 0x8000) == 0x8000)	 
      rdy=1;
    break;

  case 1:	//encode mode, check for VDA bit
   if((temp & 0x0001) == 0x0001)
    CMX618IRQ=1;
   break;
  
  case 2:	//decode mode, check for VDW bit
   if((temp & 0x0100) == 0x0100)
    CMX618IRQ=1;
   break;

  case 3:	//powersave mode, not actually used in this routine
    break;
  } 
}

//********************************
//FUNCTION:
void timer1() interrupt 3
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: Timer 1 Interrupt Servide Routine.
// This timer is used for:
// - switch debouncing within "main"
// - the 20s delay for Chip Erase lockup prevention
// - the 100ms delay needed in the CMX618 initialization.
// A counter is decremented each time Timer 1 overflows.  
// When the count reaches 0, a flag is set.
//********************************
{
  timer1_counter--;
  if(timer1_counter==0)
   {
     timer1_expired=1;
	 TR1=0;
	}
  else
   TR1=1;
   
  TH1=0xB8;	  //reload for 20ms overflow
  TL1=0x00;
}


//******************************************
// FUNCTION:
void spi_write(unsigned char xbyte)
//
// PURPOSE: Write a single byte to flash input port.
//
// DESCRIPTION: This function takes in a single-byte corresponding to the
// value to be written to the flash input port.
//
// A 'for' loop is started and the SCLK line is pulled low.  The msb of the byte is obtained and
// written to flash.  The byte is left-shifted one place and SCLK is pulled high to latch the bit 
// into the flash.  The 'for' loop iterates 7 more times to complete the byte write operation.
//
// Data into the flash DI pin is sampled on the rising edge of SCLK.
// 
// This function does not return a variable.
//*******************************************
{
 unsigned char i;

 for(i=8; i!=0; i--)
  {
   SCLK=0;
   if(xbyte & 0x80)	 
     DI=1;
   else
     DI=0;
   xbyte <<= 1;	
   SCLK=1;
  }	  
}

//******************************************
// FUNCTION:
unsigned char spi_read(void)
//
// PURPOSE: Read a single byte from the flash SPI output port.
//
// DESCRIPTION: This function does not take in a variable.
//
// The SCLK line is pulled low and a 'for' loop is started.  The SCLK line is pulled high to
// latch out the latest data bit, and this bit is appended to any previously received bits.
// The received bits are left-shifted one place and SCLK is pulled low.
// The 'for' loop iterates 7 more times to complete the read operation.
// 
// This function returns the received byte to the calling routine.
//*******************************************
{
 unsigned char ybyte=0x00, i;

 SCLK=0;
 for(i=0; i<8; ++i)
  {
   ybyte <<= 1;		//left-shift here due to decrementing operator
   SCLK=1;
   if(DO)			//append 1 to ybyte if DO=1
     ybyte |= APPEND_ONE;	
   else				//else, append 0 to ybyte
     ybyte &= APPEND_ZERO;	
   SCLK=0;
   //fast processors may need a delay here
  }
 return(ybyte);
}

//********************************
//FUNCTION:
void encode_process(void)
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: 
// This routine is called by the CMX618 Interrupt Service Routine if the Status register VDA bit=1.
// This routine reads out an encoded voice data packet from the CMX618 and
// writes it to flash.
//********************************
{
  unsigned char i;

//Read out an encoded data packet from the CMX618
  CSN=0;				//start streaming C-BUS transaction
   wr_byte(ENCFRAME);	 		//write address for ENCFRAME register
   for(i=0; i<BYTELENGTH; ++i)
    CMX618_data[i]=rd_byte();		//read out encoded data
  CSN=1;				//end streaming C-BUS transaction
       
//Write encoded data to flash
  program_flash(ENCODE_ADDRESS_HIGH, ENCODE_ADDRESS_MID, ENCODE_ADDRESS_LOW);
   
//Increment page address for next flash write 
  if(ENCODE_ADDRESS_HIGH==0xFF)		//if max address = 0xFF, error condition...turn on Red LED
  	RED_LED=ON;	
  
  if(ENCODE_ADDRESS_LOW!=0xD8)
    ENCODE_ADDRESS_LOW = ENCODE_ADDRESS_LOW + BYTELENGTH;
  else					//c is excessive and must be reset, but what about a and b?
   {
    if(ENCODE_ADDRESS_MID<0xFF)		//if b is not excessive (<255), increment b and reset c
      {
	ENCODE_ADDRESS_LOW=0;
	ENCODE_ADDRESS_MID++;
      }
    else				//if b is excessive, increment a and reset b & c.
      {
	ENCODE_ADDRESS_LOW=0;
	ENCODE_ADDRESS_MID=0;
	ENCODE_ADDRESS_HIGH++;
      }
    }
}


//********************************
//FUNCTION:
void decode_process(void)
//
//INPUTS:  none
//
//OUTPUTS:	none
//
//DESCRIPTION: This routine transfers an encoded voice data packet to the CMX618 decoder.
// This routine is called by the CMX618 Interrupt Service Routine if the Status register VDW bit=1.
// Data is written to the CMX618 decoder first and another data packet is then read out of flash.
// This was done to ensure that data would be supplied to the decoder almost immediately after the VDW interrupt.
// (The "main" routine performs an extra "read flash" operation so that an encoded packet is
// already in memory when "decode process" is called for the first time.  This should ensure that

⌨️ 快捷键说明

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