#include "GLOBAL.H"
#include "USB.H"
#include "SPEAKER.H"


//-----MCU.C-----//
extern void Delay_Xms( BYTE X );

//-----USB.C-----//
extern EP0INFO Ep0;

idata SPK Spk;



void SPK_VOL_Vol_Ctrl( BYTE L , BYTE R )
  { BYTE Cur;
    
    
    Cur = USB[GS_LCO];
    Cur &= 0x1F;
    
    if ( L > Cur )
      { while( L != Cur )
          { Cur++;
            USB[GS_LCO] = Cur;
            Delay_Xms( 1 );
          }
      }
    else if ( L < Cur )
      { while( L != Cur )
          { Cur--;
            USB[GS_LCO] = Cur;
            Delay_Xms( 1 );
          }
      }
    
    Cur = USB[GS_RCO];
    Cur &= 0x1F;
    
    if ( R > Cur )
      { while( R != Cur )
          { Cur++;
            USB[GS_RCO] = Cur;
            Delay_Xms( 1 );
          }
      }
    else if ( R < Cur )
      { while( R != Cur )
          { Cur--;
            USB[GS_RCO] = Cur;
            Delay_Xms( 1 );
          }
      }
  }


void SPK_VOL_Mix_Ctrl( BYTE M )
  { BYTE Cur;
    
    
    Cur = USB[GS_MIX];
    Cur &= 0x1F;
    
    if ( M > Cur )
      { while( M != Cur )
          { Cur++;
            USB[GS_MIX] = Cur;
            Delay_Xms( 1 );
          }
      }
    else if ( M < Cur )
      { while( M != Cur )
          { Cur--;
            USB[GS_MIX] = Cur;
            Delay_Xms( 1 );
          }
      }
  }


void SPK_VOL_Mic_Ctrl( BYTE M )
  { BYTE Cur;
    
    
    Cur = USB[GS_ADI];
    Cur &= 0x1F;
    
    if ( M > Cur )
      { while( M != Cur )
          { Cur++;
            USB[GS_ADI] = Cur;
            Delay_Xms( 1 );
          }
      }
    else if ( M < Cur )
      { while( M != Cur )
          { Cur--;
            USB[GS_ADI] = Cur;
            Delay_Xms( 1 );
          }
      }
  }


void SPK_PLL_Divider_Value( void )
  { if ( Spk.PfTl > 4 )
      { if ( Spk.PfTl == 5 )
          { if ( Spk.HfSeed == 4 )
              Spk.PfTl = 4;
            else
              Spk.PfTl = 6;
          }
        else if ( Spk.PfTl < 7 )
          Spk.PfTl = 6;
        else if ( Spk.PfTl == 7 )
          { if ( Spk.HfSeed == 6 )
              Spk.PfTl = 6;
            else
              Spk.PfTl = 8;
          }
        else if ( Spk.PfTl < 10 )
          Spk.PfTl = 8;
        else if ( Spk.PfTl == 10 )
          { if ( Spk.HfSeed == 8 )
              Spk.PfTl = 8;
            else
              Spk.PfTl = 12;
          }
        else if ( Spk.PfTl < 14 )
          Spk.PfTl = 12;
        else if ( Spk.PfTl == 14 )
          { if ( Spk.HfSeed == 12 )
              Spk.PfTl = 12;
            else
              Spk.PfTl = 16;
          }
        else if ( Spk.PfTl < 20 )
          Spk.PfTl = 16;
        else if ( Spk.PfTl == 20 )
          { if ( Spk.HfSeed == 16 )
              Spk.PfTl= 16;
            else
              Spk.PfTl = 24;
          }
        else if ( Spk.PfTl < 28 )
          Spk.PfTl = 24;
        else if ( Spk.PfTl == 28 )
          { if ( Spk.HfSeed == 24 )
              Spk.PfTl = 24;
            else
              Spk.PfTl = 32;
          }
        else if ( Spk.PfTl < 40 )
          Spk.PfTl = 32;
        else if ( Spk.PfTl == 40 )
          { if ( Spk.HfSeed == 32 )
              Spk.PfTl = 32;
            else
              Spk.PfTl = 48;
          }
        else if ( Spk.PfTl < 72 )
          Spk.PfTl = 48;
        else if ( Spk.PfTl == 72 )
          { if ( Spk.HfSeed == 48 )
              Spk.PfTl = 48;
            else
              Spk.PfTl = 96;
          }
        else
          Spk.PfTl = 96;
      }
  	
    if ( Spk.PfTl == Spk.HfSeed )
      Spk.HitErr = CLR;
    else if ( Spk.HitErr )
      { Spk.HfSeed = Spk.PfTl;
        Spk.HitErr = CLR;
      }
    else
     Spk.HitErr = SET;
  }


void SPK_PLL_Seed_Index( void )
  { switch( Spk.HfSeed )
      { case 1:  Spk.HfCon = 0;
                 break;
        case 2:  Spk.HfCon = 1;
                 break;
        case 3:  Spk.HfCon = 2;
                 break;
        case 4:  Spk.HfCon = 3;
                 break;
        case 6:  Spk.HfCon = 4;
                 break;
        case 8:  Spk.HfCon = 5;
                 break;
        case 12: Spk.HfCon = 6;
                 break;
        case 16: Spk.HfCon = 7;
                 break;
        case 24: Spk.HfCon = 8;
                 break;
        case 32: Spk.HfCon = 9;
                 break;
        case 48: Spk.HfCon = 10;
                 break;
        case 96: Spk.HfCon = 11;
                 break;
        default: Spk.HfCon = 11;
                 break;
      }
  }


void SPK_PLL_Divider( void )
  { BYTE Attr;
    
    
    Spk.PfTl = USB[PFTL];
    
    if ( Spk.PfTl & 0x80 )                       // Less then 0xF3
      { Spk.PfTl = 0xF3 - Spk.PfTl;
        Attr = DECEN;
      }
    else                                         // More then 0xF3
      { Spk.PfTl++;
        Attr = INCEN;
      }
    
    if ( Spk.PfTl > 1 )
      { SPK_PLL_Divider_Value();
 
        SPK_PLL_Seed_Index();                    // Change Spk.HfCon

        Spk.HfCon |= Attr;
      }
    else
      { Spk.HfCon = 0x05;                        // DECEN = 0 , Divider = 8;
        Spk.HfSeed = 0x08;
        Spk.HitErr = CLR;
      }
  }


void SPK_IIC_Write( void )
  { ENSI = SET;
    CR1 = SET;
    CR0 = SET;
    
    STA = SET;
    while( SI == CLR );
    STA = CLR;
    
    SIDAT = 0x34;                                // Device Address
    SI = CLR;
    while( SI == CLR );
    
    SIDAT = Spk.Reg;
    SI = CLR;
    while( SI == CLR );
    
    SIDAT = Spk.Data.B[0];                       // MSB
    SI = CLR;
    while( SI == CLR );
    
    SIDAT = Spk.Data.B[1];                       // LSB
    SI = CLR;
    while( SI == CLR );
    
    STO = SET;
    SI = CLR;
    while( STO == SET );
    
    ENSI = CLR;
  }


void Initial_SPK( void )
  { Spk.Stage = SPK_POWER_ON;
    Delay_Xms( 250 );                            // Wait power stable
    Delay_Xms( 250 );
  }


void SPK_Power_On( void )
  { if ( Spk.Stage == SPK_POWER_ON )
      { Spk.Reg = 0x6A;                          // Index Address
        Spk.Data.W = 0x0039;
        SPK_IIC_Write();
        Spk.Reg = 0x6C;                          // Index Data
        Spk.Data.W = 0x9000;                     // Enable Vref Power Control
        SPK_IIC_Write();
        
        Spk.Reg = 0x3E;                          // Enable "main bias"
        Spk.Data.W = 0x8000;
        SPK_IIC_Write();
        
        Spk.Reg = 0x3A;                          // Power On "Softgen"
        Spk.Data.W = 0x0100;
        SPK_IIC_Write();
        
        Spk.Reg = 0x3C;                          // Enable "Vref" for all analog circuits
        Spk.Data.W = 0x2000;
        SPK_IIC_Write();
        
        Spk.Reg = 0x3E;                          // Enable "L/R Volume control"
        Spk.Data.W = 0x8600;
        SPK_IIC_Write();
        
        Spk.Reg = 0x5E;                          // Enable HP Depop Mode 2
        Spk.Data.W = 0x0200;
        SPK_IIC_Write();
        
        Delay_Xms( 250 );
        Delay_Xms( 250 );
        
        Spk.Reg = 0x34;                          // Slave Mode
        Spk.Data.W = 0x8000;
        SPK_IIC_Write();
        
        Spk.Reg = 0x36;                          // MCLK Select
        Spk.Data.W = 0x066D;
        SPK_IIC_Write();
        
        Spk.Reg = 0x3C;                          // Power On HP "ADC/DAC","Mixer" 
        Spk.Data.W = 0x27F3;                     // for MIC and HP
        SPK_IIC_Write();
        
        Spk.Reg = 0x3E;                          // Enable "MIC1 AD Boost and Differential Mixer"
        Spk.Data.W = 0x8602;
        SPK_IIC_Write();
        
        Spk.Reg = 0x3A;                          // Enable IIS and Microphone Bias
        Spk.Data.W = 0x8900;
        SPK_IIC_Write();
        
        Spk.Reg = 0x0C;                          // UnMute DAC Volume Output to Headphone mixer
        Spk.Data.W = 0x6808;
        SPK_IIC_Write();
        
        Spk.Reg = 0x22;                          // MIC1 boost ( + 40db )
        Spk.Data.W = 0x0C00;
        SPK_IIC_Write();
            
        Spk.Reg = 0x14;                          // UnMute "MIC1" to ADC Record Mixer
        Spk.Data.W = 0x3F3F;
        SPK_IIC_Write();
        
        Spk.Reg = 0x1C;                          // Select HP Mixer to HP Out
        Spk.Data.W = 0xC300;
        SPK_IIC_Write();
            
        Spk.Reg = 0x04;                          // UnMute HP Out
        Spk.Data.W = 0x0000;
        SPK_IIC_Write();
            
        Delay_Xms( 50 );
        
        Spk.Reg = 0x3A;                          // Enable HP Output buffer
        Spk.Data.W = 0x8930;
        SPK_IIC_Write();
        
        Spk.Reg = 0x5E;                          // Disable Depop Mode 2 for HP Out
        Spk.Data.W = 0x0000;
        SPK_IIC_Write();
        
        Spk.Stage = SPK_OK;
     }
  }

/*
void SPK_Power_Off( void )
  { Spk.Reg = 0x00;                              // Reset all registers to their default value
    Spk.Data.W = 0x59B4;
    SPK_IIC_Write();
    
    Delay_Xms( 5 );
    
    Spk.Stage = SPK_POWER_ON; 
  }
*/

void SPK_Power_Off( void )
  { Spk.Reg = 0x3A;                              // Disable HP Output buffer
    Spk.Data.W = 0x8900;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3E;                              // Disable "MIC1 AD Boost and Differential Mixer"
    Spk.Data.W = 0x8600;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3C;                              // Power Of "ADC/DAC","Mixer" for MIC and HP
    Spk.Data.W = 0x2000;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3A;                              // Disable IIS and Microphone Bias
    Spk.Data.W = 0x0100;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3E;                              // Disable "L/R Volume control"
    Spk.Data.W = 0x8000;
    SPK_IIC_Write();
    
    Spk.Reg = 0x6A;                              // Index Address
    Spk.Data.W = 0x0039;
    SPK_IIC_Write();
    Spk.Reg = 0x6C;                              // Index Data
    Spk.Data.W = 0x9800;                         // Disable Vref Power Control
    SPK_IIC_Write();
    
    Spk.Reg = 0x3E;                              // Disable "main bias"
    Spk.Data.W = 0x0000;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3A;                              // Power Off "Softgen"
    Spk.Data.W = 0x0000;
    SPK_IIC_Write();
    
    Spk.Reg = 0x3C;                              // Disable "Vref" for all analog circuits
    Spk.Data.W = 0x0000;
    SPK_IIC_Write();
    
    Spk.Stage = SPK_POWER_ON; 
  }