| |
//sta013.c
#include <mega128.h>
#include "mp3data.h"
#ifndef begin
#define begin {
#define end }
#endif
//prototypes
void STA013_Write(unsigned char address, unsigned char data);//writes via I2C
void STA013_Audio_Stop(void);//sends stop playing comand
void STA013_Show_Info(void);//displays contents of the registers
void STA013_Test_Serial_Interface(void)
begin
//test the SCKR, SDI and DATA_REQ lines
unsigned char c,sdi,sckr,data_req;
unsigned char tmpstr[BUF_SIZE],tmpinstr[BUF_SIZE];
c=0;
sdi=0;
sckr=0;
while(c!='q')
begin
sdi=sdi^0x01;
sckr=sckr^0x01;
SDI=sdi;
SCKR=sckr;
data_req = DATA_REQ;
if (sdi==0x01)
begin
while(OUT_RDY==0);S_Printf("Setting sdi to 1\n\r");
end
if (sckr==0x01)
begin
while(OUT_RDY==0);S_Printf("Setting sckr to 1\n\r");
end
if (data_req==0x01)
begin
while(OUT_RDY==0);S_Printf("data_req = 1\n\r");
end
else
begin
if (data_req==0x00)
begin
while(OUT_RDY==0);S_Printf("data_req = 0\n\r");
end
else
begin
sprintf(tmpstr,"data_req %x\n\r",data_req);
while(OUT_RDY==0);S_Print(tmpstr);
end
end
while(OUT_RDY==0);
S_Printf("Press q <enter> to quit");
while(OUT_RDY==0);
S_Printf(",<enter> to continue\n\r");
while(!IN_RDY);
S_In(tmpinstr);
c = tmpinstr[0];
end
end
void STA013_Audio_Send(unsigned char data)
begin
unsigned char i;
//using a for loop now, might be faster to use 7 copies
for (i=0;i<8;i++)
begin
if ((data & 0x80)==0x80)
begin//send 1
SDI = 1;
SCKR = 1;
end
else
begin//send 0
SDI = 0;
SCKR = 1;
end
data = data << 1;
//now send a negative edge and STA013 will sample SDI
SCKR = 0;//negative edge
/*
#asm//slow things down a bit
nop
nop
#endasm
*/
end//for i
end
void STA013_Audio_Stop(void)
begin
STA013_Write(PLAY,0x00);
delay_us(5);
STA013_Write(RUN,0x00);//not sure whether this is needed yet
S_Printf("Stopped play\n\r");
end
void STA013_Play_MP3(void)
begin
unsigned int i = 0;
//need to tell STA013 to start playing via I2C
//send RUN(0x72) = 0x01, STA013 goes into decode state
//send PLAY(0x13) = 0x01 and MUTE(0x14) = 0x00;
//S_Printf("Writing run\n\r");
STA013_Write(0x72,0x01);
//S_Printf("Writing play\n\r");
STA013_Write(0x13,0x01);
//S_Printf("Writing mute\n\r");
STA013_Write(0x14,0x00);
//DATA_REQ should go high
while(1)
begin
if (DATA_REQ)
begin//send the next byte of mp3 data
//S_Printf("DATA_REQ\n\r");
STA013_Audio_Send(mp3data[i++]);
end
/*
else //debug, see if DATA_REQ ever goes low
begin
while(!OUT_RDY);
S_Printf("data req low\n\r");
end */
if (i==MP3_Data_Size) //out of data
begin
STA013_Audio_Stop();
while(OUT_RDY==0);
S_Printf("Beacuse out of data\n\r");
//STA013_Show_Info();//for debug
break;
end;
end
end
//play from the serial input buffer
void STA013_Play_Buffer(void)
begin
//S_Printf("Writing run\n\r");
STA013_Write(0x72,0x01);
//S_Printf("Writing play\n\r");
STA013_Write(0x13,0x01);
//S_Printf("Writing mute\n\r");
STA013_Write(0x14,0x00);
//DATA_REQ should go high
while(dataheadptr!=BUF_END_ADD -1);//let buffer fill up
lcd_gotoxy(0,0);
lcd_putsf("MP3 Playback st ");
while(SERIAL_MODE=Xmode)
begin
if (DATA_REQ)//STA requests data
begin
STA013_Audio_Send(*mp3ptr);
if (mp3ptr+1<BUF_END_ADD)
begin
while(mp3ptr+1 == dataheadptr)PORTE = ~(0x05);//PORTE = PORTE&0xfe;//buffer under-run, wait for more data
mp3ptr++;
end
else
begin//need to wrap around to the start
while(dataheadptr==BUF_START_ADD)PORTE=~(0x06); //PORTE = PORTE&0xfe;//under-run,led0 on
mp3ptr=BUF_START_ADD;
end
//debug
//PORTE=PORTE|0x01;//turn off led 0
end
end
STA013_Audio_Stop();
lcd_gotoxy(0,0);lcd_putsf("MP3 End ");
end
void STA013_HW_Reset(void)
begin
//Setup PORTD for the data transmission
DDRD = DDRD | (1<<7) | (1<<6);//7,6 used for output, SDI, SCKR
PORTD = 0x00;//set all to zero, as well as turn off pull up for PORTD.5 DATA_REQ
//don't think I need to use the pull up, need to check this though
//set !reset output
DDRF = DDRF | 0x80;
#ifdef showerror
if ((DDRF&0x80)!=0x80)
begin
S_Printf("Err setting DDRF\n\r");
end
#endif
PORTF = PORTF & 0x7f;//reset
delay_ms(500U);
PORTF = PORTF | 0x80;//reset off
#ifdef showerror
if ((PORTF&0x80)!=0x80)
begin
S_Printf("Err setting PORTF\n\r");
end
#endif
delay_ms(1000U);
end
void STA013_Current_Add_Read(void)
begin
unsigned char data = 0, status, tmpstr[BUF_SIZE];
#ifdef verbose
S_Printf("Cur_Add_R Send start cond\n\r");
#endif
I2C_START;//send start condition
I2C_WAIT;//wait until start conditition transmitted
status = TWSR&0xf8;
if (status!=TWI_START)
begin
#ifdef verbose
S_Printf("Start failed\n\r");
sprintf(tmpstr,"Status=%x\n\r",status);
S_Print(tmpstr);
#endif
end
S_Printf("Start condition transmitted\n\r");
TWDR = STA_WRITE;//I2C slave address
I2C_TRANSMIT;//TWCR = (1<<TWINT)|(1<<TWEN);//start transmission of address
I2C_WAIT;//wait until STA_READ has been transmitted and ACK recieved
status = TWSR&0xf8;
if (status != MR_ADD_ACK)
begin
S_Printf("I2C no ack write\n\r");
sprintf(tmpstr,"Status=%x\n\r",status);
S_Print(tmpstr);
end
//respond with TWINT TWEA return an acknowledge, table 88
status = TWSR&0xf8;
sprintf(tmpstr,"Status=%x\n\r",status);
S_Print(tmpstr);
S_Printf("rdy to ack data\n\r");
//TWCR = (1<<TWINT)|(1<<TWEA)|(1<<TWEN);//must remember to always set TWEN when I want to do I2C
//recieve and not ack
TWCR = (1<<TWINT)|(1<<TWEN);
I2C_WAIT;//is this neccesary? think so
status = TWSR&0xf8;
sprintf(tmpstr,"Status=%x\n\r",status);
S_Print(tmpstr);
while(OUT_RDY==0);
S_Outf("transmit complete\n\r");
//I2C_READ;//clear TWINT flag
/*
status = TWSR&0xf8;
while(status!=MR_DATA_ACK){status = TWSR&0xf8;};//see whether status can become MR_DATA_ACK
while(OUT_RDY==0);
S_Outf("DATA ACK!\n\r");
*/
I2C_WAIT;
if (status != MR_DATA_ACK)
begin
S_Printf("I2C no data recieved\n\r");
sprintf(tmpstr,"Status=%x\n\r",status);
S_Print(tmpstr);
end
data = TWDR;
sprintf(tmpstr,"Data = %x\n\r",data);
S_Print(tmpstr);
S_Printf("Send stop\n\r");
I2C_STOP;
S_Printf("Send stop successful\n\r");
end
/*
Start Condition
Send A Byte The value is 0x86 (134). The seven most significant bits instruct the STA013 to listen (because there may be other chips connected to SDA and SCL). The LSB is clear, telling the STA013 that will will be writing an address.
Send A Byte The value is the address where we need to read data. The main program will pass the address to our sta013_read function.
Stop Condition
Start Condition
Send A Byte The value is 0x87 (135). Again, the upper bits select the STA013, and the LSB sets up the next access to read.
Receive A Byte Read the byte from the STA013. This will be returned to the main program.
Stop Condition
*/
unsigned char STA013_Read(unsigned char address)
begin
unsigned char data, tmpstr[BUF_SIZE];
data = 0;
I2C_START;
I2C_WAIT;
if ((TWSR&0xf8)!=TWI_START)
begin
if (SERIAL_MODE==Nmode) S_Printf("read fail start 1\n\r");
end
TWDR = STA_READ;
I2C_TRANSMIT;
I2C_WAIT;
if ((TWSR&0xf8)!=MT_ADD_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("STA013 not on I2C bus\n\r");
end
TWDR = address;
I2C_TRANSMIT;
I2C_WAIT;
if ((TWSR&0xf8)!=MT_DATA_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("data not ack\n\r");
end
I2C_STOP;
delay_us(100);
I2C_START;
I2C_WAIT;
if ((TWSR&0xf8)!=TWI_START)
begin
if (SERIAL_MODE==Nmode) S_Printf("fail start 2\n\r");
end
TWDR = STA_WRITE;
I2C_TRANSMIT;
I2C_WAIT;
//sprintf(tmpstr,"1.status = %x\n\r", TWSR&0xf8);
//S_Print(tmpstr);
if ((TWSR&0xf8)!=MR_ADD_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("STA013 not on I2C bus\n\r");
end
TWCR = (1<<TWINT)|(1<<TWEN);
I2C_WAIT;
//sprintf(tmpstr,"2.status = %x\n\r",TWSR&0xf8);
//S_Print(tmpstr);
if ((TWSR&0xf8)!=MR_DATA_NO_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("err data not rcved!\n\r");
end
data = TWDR;
I2C_STOP;
delay_us(4);//must have some interval between I2C cmds
//sprintf(tmpstr, "data read %x\n\r", data);
//S_Print(tmpstr);
return data;
end
void STA013_Write(unsigned char address, unsigned char data)
begin
unsigned char tmpstr[BUF_SIZE];
I2C_START;
I2C_WAIT;
if ((TWSR&0xf8)!=TWI_START)
begin
if (SERIAL_MODE==Nmode) S_Printf("unable to start write\n\r");
end
TWDR = STA_READ;
I2C_TRANSMIT;
I2C_WAIT;
if ((TWSR&0xf8)!=MT_ADD_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("STA013 not on I2C bus\n\r");
end
TWDR = address;
I2C_TRANSMIT;
I2C_WAIT;
if ((TWSR&0xf8)!=MT_DATA_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("data not ack 1\n\r");
end
TWDR = data;
I2C_TRANSMIT;
I2C_WAIT;
if ((TWSR&0xf8)!=MT_DATA_ACK)
begin
if (SERIAL_MODE==Nmode) S_Printf("data not ack 2\n\r");
end
I2C_STOP;
delay_us(4);
end
//reads the STA013 configuration data from eeprom
void Read_Eeprom(void)
begin
unsigned char eeprom *conf_data_ptr = STA_CONFIG_ADDR;
unsigned char address,//stores the address of the reg to write to
data;//stores the value to write
unsigned int i;
i=0;
address = conf_data_ptr[i++];
data = conf_data_ptr[i++];
while((address!=0)|(data!=0))//the last item is 0,0
begin
#asm
nop
nop
nop
nop
#endasm//delay between writes
STA013_Write(address,data);
address = conf_data_ptr[i++];
data = conf_data_ptr[i++];
end
end
void STA013_Init(void)
begin
unsigned char data;
//I2C initialization
//set clock rate for I2C
//SCL freq = CPU CLK/(16 + 2(TWBR)*4^TWPS)
//TWPS - prescalar set to 0
//for SCL = 100kHz, TWBR = 72
TWBR = 72;
STA013_HW_Reset();
data = STA013_Read(0x01);
if (data==0xac)
begin
S_Printf("STA013 found\n\r");
end
else
begin
S_Printf("STA013 not found\n\r");
end
Read_Eeprom();
end
void Display_Reg(unsigned char address, unsigned char flash regname[])
begin
unsigned char data, tmpstr[BUF_SIZE];
data = STA013_Read(address);
sprintf(tmpstr," [%d] = %d\n\r",address,data);
while(!OUT_RDY);
S_Printf(regname);
while(!OUT_RDY);
S_Print(tmpstr);
end
void STA013_Show_Info(void)
begin
while(!OUT_RDY);S_Printf("Volume settings\n\r");
Display_Reg(DLA,"DLA");
Display_Reg(DLB,"DLB");
Display_Reg(DRA,"DRA");
Display_Reg(DRB,"DRB");
Display_Reg(MFSFDF_411,"MFSFDF");
Display_Reg(PLLFRAC_411_L,"PLLFRAC_411_L");
Display_Reg(PLLFRAC_411_R,"PLLFRAC_411_R");
Display_Reg(PCMCONF,"PCMCONF");
Display_Reg(MSFDF_X,"MSFDF_X");
Display_Reg(DAC_CLK_MODE,"DAC_CLK_MODE");
Display_Reg(PLLFRAC_L,"PLLFRAC_L");
Display_Reg(PLLFRAC_H,"PLLFRAC_H");
Display_Reg(PLLCTRL,"PLLCTRL");
Display_Reg(ERROR_CODE,"ERROR_CODE");
Display_Reg(7,"Reg 7");//should be 0 by ConfigPLL from STmicro
Display_Reg(6,"Reg 6");//should be 12
Display_Reg(PLAY,"PLAY");
Display_Reg(MUTE,"MUTE");
Display_Reg(84,"PCMDIVIDER");
Display_Reg(DATA_REQ_ENABLE,"DATA_REQ_ENABLE");
Display_Reg(0x0c,"REQ_POL");
Display_Reg(RUN,"RUN");
pause();
end
|