#include "def.h"
#include "val.h"
#include "wm8987l.h"


WOLFSON Wm8987l;


void Wm8987l_Write( void )
  { SICON |= STA;
    while(( SICON & SI ) != SI );                // Waiting IIC intrrupt flag
    SICON &= ~STA;
    
    SIDAT = Wm8987l.Dev;
    SICON &= ~SI;
    while(( SICON & SI ) != SI );
    
    SIDAT = Wm8987l.RegX.B[0];
    SICON &= ~SI;
    while(( SICON & SI ) != SI );
    
    SIDAT = Wm8987l.RegX.B[1];
    SICON &= ~SI;
    while(( SICON & SI ) != SI );
    
    SICON |= STO;
    SICON &= ~SI;
    while(( SICON & STO ) == STO );              // Waiting IIC intrrupt flag
  }


void Wm8987l_Power_Down( void )
  { Wm8987l.RegX.W = R25;
    Wm8987l.RegX.W |= VMIDSEL_500K;
    Wm8987l_Write();
    
    Wm8987l.RegX.W = R5;
    Wm8987l.RegX.W |= DACMU;                     // Enable Digital soft mute
    Wm8987l_Write();
    
    Wm8987l.RegX.W = R26;
    Wm8987l_Write();
    
    Wm8987l.Power_Stage = POWER_DOWN;
    Wm8987l.Cnt = 1;
  }


void Wm8987l_Power_Up( void )
  { if ( Wm8987l.Power_Stage == POWER_DOWN )
      { Wm8987l.RegX.W = R15;                    // Reset WM8987
        Wm8987l.RegX.W |= 0x005A;                // Not Important Value
        Wm8987l_Write();
      	
      	Wm8987l.RegX.W = R25;
        Wm8987l.RegX.W |= VMIDSEL_5K;
        Wm8987l_Write();
        
        Wm8987l.Power_Stage = POWER_START;
        Wm8987l.Cnt = 500;
      }
    else if ( Wm8987l.Power_Stage == POWER_START )
      { Wm8987l.RegX.W = R25;
      	Wm8987l.RegX.W |= VMIDSEL_50K;
        Wm8987l_Write();
        
        Wm8987l.Power_Stage = POWER_RISING;
        Wm8987l.Cnt = 100;
      }
    else if ( Wm8987l.Power_Stage == POWER_RISING )
      { Wm8987l.RegX.W = R25;
      	Wm8987l.RegX.W |= VMIDSEL_50K;
      	Wm8987l.RegX.W |= VREF;
        Wm8987l_Write();
        
        Wm8987l.Power_Stage = POWER_UP_OK;
        Wm8987l.Cnt = 500;
      }
    else if ( Wm8987l.Power_Stage == POWER_UP_OK )
      { Wm8987l.RegX.W = R25;
      	Wm8987l.RegX.W |= VMIDSEL_50K;
      	Wm8987l.RegX.W |= VREF;
      	Wm8987l.RegX.W |= ( MICB | ADCR | ADCL | AINR | AINL );
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R26;
        Wm8987l.RegX.W |= ( ROUT2 | LOUT2 | DACR | DACL );
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R7;
#ifdef IIS_STD                                   // Standar IIS
        Wm8987l.RegX.W |= IIS;                   // IIS Format
#endif
#ifdef IIS_LJF                                   // Left Justified
        Wm8987l.RegX.W |= LJF;                   // LJF Format
#endif
#ifdef SI_PCM                                    // PCM
       Wm8987l.RegX.W |= PCM;                    // PCM Format
#endif

#ifdef SI_SD16
       Wm8987l.RegX.W |= WL_16;                  // 16bit
#endif
#ifdef SI_SD32
       Wm8987l.RegX.W |= WL_32;                  // 32bit
#endif        
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R0;
        Wm8987l.RegX.W |= ( LINVOL_0DB | LIVU ); // LIVU should be set otherwise " Default
        Wm8987l.RegX.W &= ~LINMUTE;              // Volume " will not be Update
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R1;
        Wm8987l.RegX.W |= ( RINVOL_0DB | RIVU ); // RIVU should be set otherwise " Default
        Wm8987l.RegX.W &= ~RINMUTE;              // Volume " will not be Update
        Wm8987l_Write();
        
#ifdef MIC_IN_MODE
        Wm8987l.RegX.W = R32;
        Wm8987l.RegX.W |= LMICBOOST_29DB;        // For Microphone function
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R33;
        Wm8987l.RegX.W |= RMICBOOST_29DB;        // For Microphone function
        Wm8987l_Write();
#endif
#ifdef LINE_IN_MODE
        Wm8987l.RegX.W = R32;
        Wm8987l.RegX.W |= ( LINPUT2 | LMICBOOST_0DB ); // For Line In function
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R33;
        Wm8987l.RegX.W |= ( RINPUT2 | RMICBOOST_0DB ); // For Line In function
        Wm8987l_Write();
#endif        
        
        Wm8987l.RegX.W = R34;
        Wm8987l.RegX.W |= LD2LO;
        Wm8987l_Write();
        Wm8987l.RegX.W = R37;
        Wm8987l.RegX.W |= RD2RO;
        Wm8987l_Write();
        
        Wm8987l.RegX.W = R5;
        Wm8987l.RegX.W &= ~DACMU;                // Disable Digital soft mute
        Wm8987l_Write();
        
        Wm8987l.Power_Stage = POWER_STABLE;
        Wm8987l.Cnt = 1;
      }
  }


void Wm8987l_Bass( BYTE Vol )
  { Wm8987l.RegX.W = R12;
    Wm8987l.RegX.W |= ( BB | BC );
    Wm8987l.RegX.W += ~Vol;
    Wm8987l_Write();
  }


void Wm8987l_Treble( BYTE Vol )
  { Wm8987l.RegX.W = R13;
    Wm8987l.RegX.W |= TC;
    Wm8987l.RegX.W += ~Vol;
    Wm8987l_Write();
  }


void Initial_Wm8987l( void )
  { Wm8987l.Dev = 0x36;                          // CBS pin state = HIGH
    Wm8987l.Power_Stage = POWER_DOWN;
    Wm8987l_Power_Up();
  }