sta013.c By Zhi-Hern Loh

Home
Design
Results
A 2nd try
Schematics
Code
Files
Links
Contact

//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

Home | Design | Results | A 2nd try | Schematics | Code | Files | Links | Contact

For problems or questions regarding this web contact Zhi-Hern Loh.
Last updated: 05/02/02.