diff gsm-fw/bsp/abb+spi/abb.c @ 148:63750f70796d

gsm-fw/bsp/abb+spi: initial import from the Leonardo TCS211 version
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sat, 16 Nov 2013 19:03:37 +0000
parents
children 3c850b416c9a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/bsp/abb+spi/abb.c	Sat Nov 16 19:03:37 2013 +0000
@@ -0,0 +1,1163 @@
+/**********************************************************************************/
+/*            TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION              */
+/*                                                                                */
+/*   Property of Texas Instruments -- For  Unrestricted  Internal  Use  Only      */
+/*   Unauthorized reproduction and/or distribution is strictly prohibited.  This  */
+/*   product  is  protected  under  copyright  law  and  trade  secret law as an  */
+/*   unpublished work.  Created 1987, (C) Copyright 1997 Texas Instruments.  All  */
+/*   rights reserved.                                                             */
+/*                                                                                */
+/*                                                                                */
+/*   Filename         : abb.c                                                     */
+/*                                                                                */
+/*   Description      : Functions to drive the ABB device.                        */
+/*                      The Serial Port Interface is used to connect the TI       */
+/*                      Analog BaseBand (ABB).                                    */
+/*                      It is assumed that the ABB is connected as the SPI        */
+/*                      device 0.                                                 */
+/*                                                                                */
+/*   Author           : Pascal PUEL                                               */
+/*                                                                                */
+/*   Version number   : 1.3                                                       */
+/*                                                                                */
+/*   Date and time    : 08/22/03                                                       */
+/*                                                                                */
+/*   Previous delta   : Creation                                                  */
+/*                                                                                */
+/**********************************************************************************/
+
+#include "l1sw.cfg"
+
+#include "chipset.cfg"
+#include "board.cfg"
+#include "rf.cfg"
+#include "swconfig.cfg"
+#include "sys.cfg"
+#include "abb.h"
+#include "l1_macro.h"
+#include "l1_confg.h"
+#include "clkm/clkm.h"         // for wait_ARM_cycles function
+#include "abb_inline.h"
+#include "ulpd/ulpd.h"        // for FRAME_STOP definition
+#include "nucleus.h"      // for NUCLEUS functions and types
+#include "l1_types.h"
+
+#if (OP_L1_STANDALONE == 0)
+  #include "main/sys_types.h"
+  #include "rv/general.h"
+  #include "buzzer/buzzer.h"	     // for BZ_KeyBeep_OFF function
+#else
+  #include "sys_types.h"
+#endif
+
+#if (VCXO_ALGO == 1)
+  #include "l1_ctl.h"
+#endif
+
+#if (RF_FAM == 35)
+  #include "l1_rf35.h"
+#endif
+
+#if (RF_FAM == 12)
+  #include "tpudrv12.h" 
+  #include "l1_rf12.h"
+#endif
+
+#if (RF_FAM == 10)
+  #include "l1_rf10.h"
+#endif
+
+#if (RF_FAM == 8)
+  #include "l1_rf8.h"
+#endif
+
+#if (RF_FAM == 2)
+  #include "l1_rf2.h"
+#endif
+
+#if (ABB_SEMAPHORE_PROTECTION)   
+
+static NU_SEMAPHORE abb_sem;
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Sem_Create()                                                      */
+/*                                                                       */
+/* This function creates the Nucleus semaphore to protect ABB accesses   */
+/* against preemption.                                                   */
+/* No check on the result.                                               */
+/*                                                                       */
+/*-----------------------------------------------------------------------*/
+void ABB_Sem_Create(void)
+{
+  // create a semaphore with an initial count of 1 and with FIFO type suspension. 
+  NU_Create_Semaphore(&abb_sem, "ABB_SEM", 1, NU_FIFO);
+}
+
+#endif  // ABB_SEMAPHORE_PROTECTION   
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Wait_IBIC_Access()                                                */
+/*                                                                       */
+/* This function waits for the first IBIC access.                        */
+/*                                                                       */
+/*-----------------------------------------------------------------------*/
+void ABB_Wait_IBIC_Access(void)
+{
+  #if (ANLG_FAM ==1)
+    // Wait 6 OSCAS cycles (100 KHz) for first IBIC access 
+    // (i.e wait 60us + 10% security marge = 66us)
+    wait_ARM_cycles(convert_nanosec_to_cycles(66000));
+  #elif ((ANLG_FAM ==2) || (ANLG_FAM == 3))
+    // Wait 6 x 32 KHz clock cycles for first IBIC access 
+    // (i.e wait 187us + 10% security marge = 210us)
+    wait_ARM_cycles(convert_nanosec_to_cycles(210000));
+  #endif
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Write_Register_on_page()                                          */
+/*                                                                       */
+/* This function manages all the spi serial transfer to write to an      */
+/* ABB register on a specified page.                                     */
+/*                                                                       */
+/*-----------------------------------------------------------------------*/    
+void ABB_Write_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id, SYS_UWORD16 value)
+{
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // set the ABB page for register access
+  ABB_SetPage(page);
+
+  // Write value in reg_id
+  ABB_WriteRegister(reg_id, value);
+
+  // set the ABB page for register access at page 0
+  ABB_SetPage(PAGE0);
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Read_Register_on_page()                                           */
+/*                                                                       */    
+/* This function manages all the spi serial transfer to read one         */
+/* ABB register on a specified page.                                     */
+/*                                                                       */ 
+/* Returns the real data value of the register.                          */ 
+/*                                                                       */ 
+/*-----------------------------------------------------------------------*/    
+SYS_UWORD16 ABB_Read_Register_on_page(SYS_UWORD16 page, SYS_UWORD16 reg_id)
+{
+  volatile SYS_UWORD16 status;
+  SYS_UWORD16 reg_val;
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  /* set the ABB page for register access */
+  ABB_SetPage(page);
+
+  /* Read selected ABB register */
+  reg_val = ABB_ReadRegister(reg_id);
+
+  /* set the ABB page for register access at page 0 */
+  ABB_SetPage(PAGE0);
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+
+  return (reg_val);     // Return result
+}
+
+/*------------------------------------------------------------------------*/
+/* ABB_free_13M()                                                         */
+/*                                                                        */
+/* This function sets the 13M clock working in ABB. A wait loop           */ 
+/* is required to allow first slow access to ABB clock register.          */
+/*                                                                        */ 
+/* WARNING !! : this function must not be protected by semaphore !!       */ 
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+void ABB_free_13M(void)
+{
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  ABB_SetPage(PAGE0);
+
+  // This transmission frees the CLK13 in ABB.
+  ABB_WriteRegister(TOGBR2, 0x08);
+
+  // Wait for first IBIC access
+  ABB_Wait_IBIC_Access();
+
+  // SW Workaround : This transmission has to be done twice.
+  ABB_WriteRegister(TOGBR2, 0x08);
+
+  // Wait for first IBIC access
+  ABB_Wait_IBIC_Access();
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* ABB_stop_13M()                                                         */
+/*                                                                        */
+/* This function stops the 13M clock in ABB.                              */
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+void ABB_stop_13M(void)
+{
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  ABB_SetPage(PAGE0);
+
+  // Set ACTIVMCLK = 0.
+  ABB_WriteRegister(TOGBR2, 0x04);
+
+  // Wait for first IBIC access
+  ABB_Wait_IBIC_Access();
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+
+/*------------------------------------------------------------------------*/
+/* ABB_Read_Status()                                                      */
+/*                                                                        */
+/* This function reads and returns the value of VRPCSTS ABB register.     */
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+SYS_UWORD16 ABB_Read_Status(void)
+{      
+  volatile SYS_UWORD16 status;
+  SYS_UWORD16 reg_val;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  ABB_SetPage(PAGE0);
+
+  #if (ANLG_FAM == 1) || (ANLG_FAM == 2)
+    ABB_SetPage(PAGE0);
+    reg_val = ABB_ReadRegister(VRPCSTS);
+  #elif (ANLG_FAM == 3)
+    ABB_SetPage(PAGE1);
+    reg_val = ABB_ReadRegister(VRPCCFG);
+  #endif
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+
+  return (reg_val);      
+}
+
+/*------------------------------------------------------------------------*/
+/* ABB_on()                                                               */
+/*                                                                        */
+/* This function configures ABB registers to work in ON condition         */ 
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+void ABB_on(SYS_UWORD16 modules, SYS_UWORD8 bRecoveryFlag)
+{
+  volatile SYS_UWORD16 status;
+  #if ((ANLG_FAM ==2) || (ANLG_FAM == 3))
+    SYS_UWORD32 reg;
+  #endif
+ 
+  // a possible cause of the recovery is that ABB is on Oscas => switch from Oscas to CLK13
+  if (bRecoveryFlag)     
+  {
+    // RESTITUTE 13MHZ CLOCK TO ABB
+    //---------------------------------------------------
+    ABB_free_13M();
+
+    // RESTITUTE 13MHZ CLOCK TO ABB AGAIN (C.F. BUG1719)
+    //---------------------------------------------------
+    ABB_free_13M();
+  }
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  ABB_SetPage(PAGE0);
+
+  // This transmission disables MADC,AFC,VDL,VUL modules.
+  ABB_WriteRegister(TOGBR1, 0x0155);  
+
+  #if (ANLG_FAM == 1)
+    // This transmission disables Band gap fast mode Enable BB charge.
+    ABB_WriteRegister(VRPCCTL2, 0x1fc);  
+
+    /* *********** DC/DC enabling selection ************************************************************** */
+    // This transmission changes the register page in OMEGA for usp to pg1.
+    ABB_SetPage(PAGE1);
+
+    /* Insert here accesses to modify DC/DC parameters. Default is a switching frequency of 240 Khz */
+    {
+      SYS_UWORD8 vrpcctrl3_data;
+
+      #if (CHIPSET == 9) || (CHIPSET == 10) || (CHIPSET == 11)
+        vrpcctrl3_data = 0x007d;  // core voltage 1.4V for C035
+      #else
+        vrpcctrl3_data = 0x00bd;  // core voltage 1.8V for C05
+      #endif
+
+    if(modules & DCDC)    // check if the DCDC is enabled
+    {  
+       vrpcctrl3_data |= 0x0002; // set DCDCEN
+    }  
+       
+    // This access disables the DCDC.
+    ABB_WriteRegister(VRPCCTRL3, vrpcctrl3_data);  
+    }  
+
+    /* ************************  SELECTION OF TEST MODE FOR ABB **************************************** */
+    /* This test configuration allows visibility on BULENA,BULON,BDLON,BDLENA on test pins               */
+    /* ***************************************************************************************************/
+    #if (BOARD==6)&& (ANLG_FAM==1)  //BUG01967 to remove access to TAPCTRL   (EVA4 board and Nausica)                                                                 
+      // This transmission enables Omega test register.
+      ABB_WriteRegister(TAPCTRL, 0x01);  
+
+      // This transmission select Omega test instruction.
+      ABB_WriteRegister(TAPREG, TSPTEST1);  
+
+      // This transmission disables Omega test register.
+      ABB_WriteRegister(TAPCTRL, 0x00);  
+    #endif
+    /* *************************************************************************************************** */
+
+    if (!bRecoveryFlag)    // Check recovery status from L1, prevent G23 SIM issue
+    {
+      // This transmission changes SIM power supply to 3 volts.
+      ABB_WriteRegister(VRPCCTRL1, 0x45);  
+    }
+
+    ABB_SetPage(PAGE0);
+
+    // This transmission enables selected OMEGA modules.
+    ABB_WriteRegister(TOGBR1, (modules & ~DCDC) >> 6);  
+  
+    if(modules & MADC)   // check if the ADC is enabled
+    {  
+      // This transmission connects the resistive divider to MB and BB.
+      ABB_WriteRegister(BCICTL1, 0x0005);  
+    }
+  #elif ((ANLG_FAM == 2) || (ANLG_FAM == 3)) 
+    // Restore the ABB checks and debouncing if start on TESTRESETZ 
+
+    // This transmission changes the register page in the ABB for usp to pg1.
+    ABB_SetPage(PAGE1);
+
+    // This transmission sets the AFCCK to CKIN/2.
+    ABB_WriteRegister(AFCCTLADD, 0x01);  
+    
+    // This transmission enables the tapreg.
+    ABB_WriteRegister(TAPCTRL, 0x01);  
+
+    // This transmission enables access to page 2.
+    ABB_WriteRegister(TAPREG, 0x01b);  
+
+    // This transmission changes the register page in the ABB for usp to pg2.
+    ABB_SetPage(PAGE2);
+
+    #if (ANLG_FAM == 2)
+    // Restore push button environment
+    ABB_WriteRegister(0x3C, 0x07);
+
+    #elif (ANLG_FAM == 3)
+
+    // Restore push button environment
+    ABB_WriteRegister(0x3C, 0xBF);
+
+      /* ************************  SELECTION OF BBCFG CONFIG FOR ABB 3 PG1_0 *******************************/
+        #if (ANLG_PG == S_PG_10)                    // SYREN PG1.0 ON ESAMPLE
+          ABB_WriteRegister(BBCFG, C_BBCFG);         // Initialize transmit register
+        #endif
+    // This transmission enables access to page 0.
+    ABB_SetPage(PAGE0);
+    
+    // reset bit MSKINT1 , if set by TESTRESET
+    reg=ABB_ReadRegister(VRPCSTS) & 0xffe;
+
+    ABB_WriteRegister(VRPCSTS, reg);
+
+    ABB_SetPage(PAGE2);
+
+    // Restore default for BG behavior in sleep mode
+    ABB_WriteRegister(VRPCAUX, 0xBF);  
+
+    // Restore default for deboucing length
+    ABB_WriteRegister(VRPCLDO, 0x00F);  
+
+    // Restore default for INT1 generation, wait time in switch on, checks in switch on
+    ABB_WriteRegister(VRPCABBTST, 0x0002);  
+
+    #endif
+
+    // This transmission changes the register page in the ABB for usp to pg1.
+    ABB_SetPage(PAGE1);
+
+    // This transmission sets tapinst to id code.
+    ABB_WriteRegister(TAPREG, 0x0001);  
+
+    // This transmission disables TAPREG access.
+    ABB_WriteRegister(TAPCTRL, 0x00);  
+
+    // enable BB battery charge BCICONF register, enable test mode to track BDLEN and BULEN windows
+    // This transmission enables BB charge and BB bridge connection for BB measurements.
+    ABB_WriteRegister(BCICONF, 0x060);  
+
+     /* ************************  SELECTION OF BBCFG CONFIG FOR ABB 3 PG2_0 *******************************/
+      #if (ANLG_FAM == 3)
+        #if (ANLG_PG == S_PG_20)                     // SYREN PG2.0 ON EVACONSO
+           ABB_WriteRegister(BBCFG, C_BBCFG);         // Initialize transmit register
+        #endif
+      #endif
+
+    /* ************************  SELECTION OF TEST MODE FOR ABB ******************************************/
+    /* This test configuration allows visibility on test pins  TAPCTRL has not to be reset                */
+    /* ****************************************************************************************************/
+                                    
+    // This transmission enables the tapreg.
+    ABB_WriteRegister(TAPCTRL, 0x01);  
+
+    // This transmission select ABB test instruction.
+    ABB_WriteRegister(TAPREG, TSPEN);  
+
+    // This transmission changes the register page in ABB for usp to pg0.
+    ABB_SetPage(PAGE0);
+
+    // This transmission enables selected ABB modules.
+    ABB_WriteRegister(TOGBR1, modules >> 6);  
+
+    // enable MB & BB resistive bridges for measurements
+    if(modules & MADC)       // check if the ADC is enabled
+    {  
+      // This transmission connects the resistive divider to MB and BB.
+      ABB_WriteRegister(BCICTL1, 0x0001);  
+    }
+
+    /********* Sleep definition part ******************/
+    // This transmission changes the register page in the ABB for usp to pg1.
+    #if (ANLG_FAM == 2)
+      ABB_SetPage(PAGE1);
+
+      // update the Delay needed by the ABB before going in deep sleep, and clear previous delay value.
+      reg = ABB_ReadRegister(VRPCCFG) & 0x1e0;
+
+      ABB_WriteRegister(VRPCCFG, (SLPDLY | reg));  
+
+      // update the ABB mask sleep register (regulator disabled in deep sleep), and clear previous mask value.
+      reg = ABB_ReadRegister(VRPCMSK) & 0x1e0;
+      ABB_WriteRegister(VRPCMSK, (MASK_SLEEP_MODE | reg));  
+    #elif (ANLG_FAM == 3)
+         Syren_Sleep_Config(NORMAL_SLEEP,SLEEP_BG,SLPDLY);
+    #endif
+    //  This transmission changes the register page in the ABB for usp to pg0.
+    ABB_SetPage(PAGE0);
+  #endif 
+
+  // SW workaround for initialization of the audio parts of the ABB to avoid white noise 
+  // C.f. BUG1941
+  // Set VDLR and VULR bits
+  // Write TOGBR1 register
+  // This transmission enables selected ABB modules.
+  ABB_WriteRegister(TOGBR1, 0x0A);  
+  
+  // wait for 1 ms
+  wait_ARM_cycles(convert_nanosec_to_cycles(1000000));
+  
+  // Reset VDLS and VULS bits
+  // Write TOGBR1 register
+  // This transmission enables selected ABB modules.
+  ABB_WriteRegister(TOGBR1, 0x05);  
+  
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock 
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Read_ADC()                                                        */
+/*                                                                       */    
+/* This function manages all the spi serial transfer to read all the     */
+/* ABB ADC conversion channels.                                          */
+/* Stores the result in Buff parameter.                                  */ 
+/*                                                                       */ 
+/*-----------------------------------------------------------------------*/    
+void ABB_Read_ADC(SYS_UWORD16 *Buff)
+{
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // This transmission changes the register page in the ABB for usp to pg0.
+  ABB_SetPage(PAGE0);
+
+  /* Read all ABB ADC registers */
+  *Buff++ = ABB_ReadRegister(VBATREG);
+  *Buff++ = ABB_ReadRegister(VCHGREG);
+  *Buff++ = ABB_ReadRegister(ICHGREG);
+  *Buff++ = ABB_ReadRegister(VBKPREG);
+  *Buff++ = ABB_ReadRegister(ADIN1REG);
+  *Buff++ = ABB_ReadRegister(ADIN2REG);
+  *Buff++ = ABB_ReadRegister(ADIN3REG);
+
+  #if (ANLG_FAM ==1)
+    *Buff++ = ABB_ReadRegister(ADIN4XREG);
+    *Buff++ = ABB_ReadRegister(ADIN5YREG);
+  #elif (ANLG_FAM ==2)
+    *Buff++ = ABB_ReadRegister(ADIN4REG);
+   #elif (ANLG_FAM == 3)
+    *Buff++ = ABB_ReadRegister(ADIN4REG);
+    *Buff++ = ABB_ReadRegister(ADIN5REG);
+  #endif   // ANLG_FAM
+
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Conf_ADC()                                                        */
+/*                                                                       */    
+/* This function manages all the spi serial transfer to:                 */
+/*  - select the ABB ADC channels to be converted                        */
+/*  - enable/disable EOC interrupt                                       */ 
+/*                                                                       */ 
+/*-----------------------------------------------------------------------*/ 
+void ABB_Conf_ADC(SYS_UWORD16 Channels, SYS_UWORD16 ItVal)                              
+{
+  volatile SYS_UWORD16 status;
+  SYS_UWORD16 reg_val;
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // This transmission changes the register page in the ABB for usp to pg0.
+  ABB_SetPage(PAGE0);
+
+  /* select ADC channels to be converted */
+  #if (ANLG_FAM == 1)  
+    ABB_WriteRegister(MADCCTRL1, Channels);  
+  #elif ((ANLG_FAM == 2) || (ANLG_FAM == 3))
+    ABB_WriteRegister(MADCCTRL, Channels);  
+  #endif
+
+  reg_val = ABB_ReadRegister(ITMASK);
+
+  // This transmission configure the End Of Conversion IT without modifying other bits in the same register.
+  if(ItVal == EOC_INTENA)
+    ABB_WriteRegister(ITMASK, reg_val & EOC_INTENA);
+  else if(ItVal == EOC_INTMASK)    
+    ABB_WriteRegister(ITMASK, reg_val | EOC_INTMASK);  
+
+  #if (ABB_SEMAPHORE_PROTECTION == 3)  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+
+
+/*------------------------------------------------------------------------*/
+/* ABB_sleep()                                                            */
+/*                                                                        */
+/* This function disables the DCDC and returns to PAGE 0. It stops then   */
+/* the 13MHz clock in ABB. A wait loop s required to allow                */ 
+/* first slow access to ABB clock register.                               */
+/*                                                                        */ 
+/* WARNING !! : this function must not be protected by semaphore !!       */ 
+/*                                                                        */ 
+/* Returns AFC value.                                                     */ 
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+SYS_UWORD32 ABB_sleep(SYS_UWORD8 sleep_performed, SYS_WORD16 afc)
+{
+  volatile SYS_UWORD16 status;
+  SYS_UWORD32 afcout_index;
+  volatile SYS_UWORD16 nb_it;
+  SYS_UWORD16 reg_val;
+
+  // table for AFC allowed values during Sleep mode. First 5th elements
+  // are related to positive AFC values, last 5th to negative ones.
+  SYS_UWORD32 Afcout_T[10]= {0x0f,0x1f,0x3f,0x7f,0xff,0x00,0x01,0x03,0x07,0x0f};
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  // COMPUTATION AND PROGRAMMING OF AFC VALUE
+  //---------------------------------------------------
+  if(afc & 0x1000)
+    afcout_index = ((afc + 512)>>10) + 1;
+  else  
+    afcout_index = (afc  + 512)>>10;
+
+  if (sleep_performed == FRAME_STOP)   // Big sleep
+  {
+    #if ((ANLG_FAM == 2) || (ANLG_FAM == 3))
+      //////////// ADD HERE IOTA or SYREN CONFIGURATION FOR BIG SLEEP ////////////////////////////
+    #endif
+
+  }
+  else                                  // Deep sleep 
+  {
+    #if(ANLG_FAM == 1) 
+      // SELECTION OF AFC TEST MODE FOR OMEGA 
+      //---------------------------------------------------
+      // This test configuration allows access on the AFCOUT register 
+      ABB_SetPage(PAGE1);
+
+      // This transmission enables OMEGA test register. 
+      ABB_WriteRegister(TAPCTRL, 0x01);  
+
+      // This transmission selects OMEGA test instruction.
+      ABB_WriteRegister(TAPREG, AFCTEST);  
+
+      // Set AFCOUT to 0.
+      ABB_WriteRegister(AFCOUT, 0x00 >> 6);  
+
+      ABB_SetPage(PAGE0);
+
+    #elif (ANLG_FAM == 2)
+      // This configuration allows access on the AFCOUT register 
+      ABB_SetPage(PAGE1);
+
+      // Read AFCCTLADD value and enable USP access to AFCOUT register
+      reg_val = (ABB_ReadRegister(AFCCTLADD) | 0x04);
+
+      ABB_WriteRegister(AFCCTLADD, reg_val);  
+
+      // Set AFCOUT to 0.
+      ABB_WriteRegister(AFCOUT, 0x00);  
+
+      // Read BCICONF value	and cut the measurement bridge of BB cut the BB charge.
+      reg_val = ABB_ReadRegister(BCICONF) & 0x039f;
+
+      ABB_WriteRegister(BCICONF, reg_val);  
+    
+      // Disable the ABB test mode
+      ABB_WriteRegister(TAPCTRL, 0x00);  
+    
+      ABB_SetPage(PAGE0);
+
+      // Read BCICTL1 value and cut the measurement bridge of MB.
+      reg_val = ABB_ReadRegister(BCICTL1) & 0x03fe;
+
+      ABB_WriteRegister(BCICTL1, reg_val);  
+    #endif
+     
+     #if (ANLG_FAM == 3)              // Nothing to be done as MB and BB measurement bridges are automatically disconnected 
+                                              // in Syren during sleep mode. BB charge stays enabled 
+       ABB_SetPage(PAGE1);                    // Initialize transmit reg_num. This transmission
+                                              // change the register page in IOTA for usp to pg1
+
+       ABB_WriteRegister(TAPCTRL, 0x00);      // Disable Syren test mode
+
+       ABB_SetPage(PAGE0);
+     #endif
+
+    // switch off MADC, AFC, AUXDAC, VOICE.
+    ABB_WriteRegister(TOGBR1, 0x155);  
+
+    // Switch off Analog supply LDO
+    //-----------------------------
+    #if (ANLG_FAM == 1)  
+      ABB_SetPage(PAGE1);
+  
+      // Read VRPCCTL3 register value and switch off VR3.  
+      reg_val = ABB_ReadRegister(VRPCCTRL3) & 0x3df;
+
+      ABB_WriteRegister(VRPCCTRL3, reg_val);  
+      
+    #elif (ANLG_FAM == 2)
+      // Read VRPCSTS register value and extract status of meaningfull inputs.  
+      reg_val = ABB_ReadRegister(VRPCSTS) & 0x0070;
+
+      if (reg_val == 0x30)
+      {
+        // start the SLPDLY counter in order to switch the ABB in sleep mode. This transmission sets IOTA sleep bit.
+        ABB_WriteRegister(VRPCDEV, 0x02);  
+      }
+
+      // Dummy transmission to clean of ABB bus. This transmission accesses IOTA address 0 in "read".
+      ABB_WriteRegister(0x0000 | 0x0001, 0x0000);  
+
+    #elif (ANLG_FAM == 3)
+       // In Syren there is no need to check for VRPCCFG as wake up prioritys are changed
+       // start the SLPDLY counter in order to switch the ABB in sleep mode
+       ABB_WriteRegister(VRPCDEV,0x02);     // Initialize transmit reg_num. This transmission
+                                            // set Syren sleep bit
+/*
+      // Dummy transmission to clean of ABB bus. This transmission accesses SYREN address 0 in "read".
+      ABB_WriteRegister(0x0000 | 0x0001, 0x0000);  
+*/
+    #endif
+
+    // Switch to low frequency clock  
+    ABB_stop_13M();
+  }
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+
+#if (OP_L1_STANDALONE == 1)
+   #if (CHIPSET == 12)
+       // GPIO_InitAllPull(ALL_ONE);  // enable all GPIO internal pull
+       // workaround to set APLL_DIV_CLK( internal PU) at high level
+       // by default APLL_DIV_CLK is low pulling 80uA on VRIO
+//       *(SYS_UWORD16*) (0xFFFFFD90)= 0x01;//CNTL_APLL_DIV_CLK -> APLL_CLK_DIV != 0
+//       *(SYS_UWORD16*) (0xFFFEF030)= 0x10;// DPLL mode
+   #endif
+#endif
+  return(Afcout_T[afcout_index]);
+}
+
+
+/*------------------------------------------------------------------------*/
+/* ABB_wakeup()                                                           */
+/*                                                                        */
+/* This function sets the 13MHz clock working in ABB. A wait loop         */    
+/* is required to allow first slow access to ABB clock register.          */
+/* Then it re-enables DCDC and returns to PAGE 0.                         */
+/*                                                                        */ 
+/* WARNING !! : this function must not be protected by semaphore !!       */ 
+/*                                                                        */ 
+/*------------------------------------------------------------------------*/ 
+void ABB_wakeup(SYS_UWORD8 sleep_performed, SYS_WORD16 afc)
+{
+  volatile SYS_UWORD16 status;
+  SYS_UWORD16 reg_val;
+
+  // Start spi clock, mask IT for RD and WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_RDWR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  if (sleep_performed == FRAME_STOP)   // Big sleep
+  { 
+    #if ((ANLG_FAM == 2) || (ANLG_FAM == 3))
+      //////////// ADD HERE IOTA or SYREN CONFIGURATION FOR BIG SLEEP WAKEUP ////////////////////////////
+    #endif
+  }
+  else                                  // Deep sleep 
+  {
+    #if (OP_L1_STANDALONE == 1)
+      #if (CHIPSET == 12)
+         // restore context from     
+         // workaround to set APLL_DIV_CLK( internal PU) at high level
+         // by default APLL_DIV_CLK is low pulling 80uA on VRIO
+//         *(SYS_UWORD16*) (0xFFFFFD90)= 0x00;//CNTL_APLL_DIV_CLK -> APLL_DIV_CLK != 0
+//         *(SYS_UWORD16*) (0xFFFEF030)= 0x00;// DPLL mode
+      #endif
+    #endif
+
+    // Restitutes 13MHZ Clock to ABB
+    ABB_free_13M();
+
+    // Switch ON Analog supply LDO
+    #if (ANLG_FAM == 1)   
+      ABB_SetPage(PAGE1);
+
+      // Read VRPCCTL3 register value and switch on VR3.  
+      reg_val = ABB_ReadRegister(VRPCCTRL3) | 0x020;
+
+      ABB_WriteRegister(VRPCCTRL3, reg_val);  
+      ABB_SetPage(PAGE0);
+    #endif
+
+    // This transmission switches on MADC, AFC.
+    ABB_WriteRegister(TOGBR1, 0x280);  
+
+    // This transmission sets the AUXAFC2. 
+    ABB_WriteRegister(AUXAFC2, ((afc>>10) & 0x7));  
+
+    // This transmission sets the AUXAFC1. 
+    ABB_WriteRegister(AUXAFC1, (afc & 0x3ff));  
+
+    #if (ANLG_FAM == 1)
+      // Remove AFC test mode  
+      ABB_SetPage(PAGE1);
+
+      // This transmission select Omega test instruction.
+      ABB_WriteRegister(TAPREG, TSPTEST1);  
+
+      // Disable test mode selection
+      // This transmission disables Omega test register. 
+      ABB_WriteRegister(TAPCTRL, 0x00 >> 6);  
+
+      ABB_SetPage(PAGE0);
+
+    #elif (ANLG_FAM == 2)
+      ABB_SetPage(PAGE1);
+
+      // Read AFCCTLADD register value and disable USP access to AFCOUT register.  
+      reg_val = ABB_ReadRegister(AFCCTLADD) & ~0x04;
+
+      ABB_WriteRegister(AFCCTLADD, reg_val);  
+
+      // Read BCICONF register value and enable BB measurement bridge enable BB charge.  
+      reg_val = ABB_ReadRegister(BCICONF) | 0x0060;
+
+      ABB_WriteRegister(BCICONF, reg_val);  
+
+
+      /* *************************************************************************************************** */
+      // update the Delay needed by the ABB before going in deep sleep, and clear previous delay value.
+      reg_val = ABB_ReadRegister(VRPCCFG) & 0x1e0;
+      ABB_WriteRegister(VRPCCFG, (SLPDLY | reg_val));
+
+      // Enable the ABB test mode
+      ABB_WriteRegister(TAPCTRL, 0x01);  
+      ABB_WriteRegister(TAPREG, TSPEN);
+      ABB_SetPage(PAGE0);
+
+      // Read BCICTL1 register value and enable MB measurement bridge and cut the measurement bridge of MB.  
+      reg_val = ABB_ReadRegister(BCICTL1) | 0x0001;
+
+      ABB_WriteRegister(BCICTL1, reg_val);  
+    #endif   
+
+  #if (ANLG_FAM == 3)
+
+    ABB_SetPage(PAGE1);
+
+    /* *************************************************************************************************** */
+    // update the Delay needed by the ABB before going in deep sleep, and clear previous delay value.
+    reg_val = ABB_ReadRegister(VRPCCFG) & 0x1e0;
+    ABB_WriteRegister(VRPCCFG, (SLPDLY | reg_val));
+    
+    /* ************************  SELECTION OF TEST MODE FOR ABB=3 *****************************************/
+    /* This test configuration allows visibility on test pins  TAPCTRL has not to be reset                */
+    /* ****************************************************************************************************/
+                                  
+    ABB_WriteRegister(TAPCTRL, 0x01);             // Initialize the transmit register  
+                                                  // This transmission enables IOTA test register 
+
+    ABB_WriteRegister(TAPREG, TSPEN);
+                                                  // This transmission select IOTA test instruction 
+                                                  // This transmission select IOTA test instruction 
+    /**************************************************************************************************** */
+        
+    ABB_SetPage(PAGE0);                          // Initialize transmit reg_num. This transmission
+  #endif
+  } 
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+/*------------------------------------------------------------------------*/
+/* ABB_wa_VRPC()                                                          */
+/*                                                                        */
+/* This function initializes the VRPCCTRL1 or VRPCSIM register            */
+/* according to the ABB used.                                             */
+/*                                                                        */
+/*------------------------------------------------------------------------*/ 
+void ABB_wa_VRPC(SYS_UWORD16 value)
+{
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+
+  // check if the semaphore has been correctly created and try to obtain it.
+  // if the semaphore cannot be obtained, the task is suspended and then resumed 
+  // as soon as the semaphore is released.
+  if(&abb_sem != 0)
+  {
+    NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  ABB_SetPage(PAGE1);
+    
+  #if (ANLG_FAM == 1)  
+    // This transmission initializes the VRPCCTL1 register.
+    ABB_WriteRegister(VRPCCTRL1, value);  
+
+  #elif (ANLG_FAM == 2)
+    // This transmission initializes the VRPCSIM register.
+    ABB_WriteRegister(VRPCSIM, value);  
+
+  #elif (ANLG_FAM == 3)
+    // This transmission initializes the VRPCSIMR register.
+    ABB_WriteRegister(VRPCSIMR, value);  
+
+  #endif
+
+  ABB_SetPage(PAGE0);
+
+  #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3))  
+  // release the semaphore only if it has correctly been created.
+  if(&abb_sem != 0)
+  {
+    NU_Release_Semaphore(&abb_sem);
+  }
+  #endif  // ABB_SEMAPHORE_PROTECTION   
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* ABB_Write_Uplink_Data()                                               */
+/*                                                                       */
+/* This function uses the SPI to write to ABB uplink buffer.             */
+/*                                                                       */
+/*-----------------------------------------------------------------------*/    
+void ABB_Write_Uplink_Data(SYS_UWORD16 *TM_ul_data)
+{
+  SYS_UWORD8 i;
+  volatile SYS_UWORD16 status;
+
+  // Start spi clock, mask IT for WR and read SPI_REG_STATUS to reset the RE and WE flags.   
+  SPI_Ready_for_WR
+  status = * (volatile SYS_UWORD16 *) SPI_REG_STATUS; 
+
+  // Select Page 0 for TOGBR2
+  ABB_SetPage(PAGE0);
+
+  // Initialize pointer of burst buffer 1 : IBUFPTR is bit 10 of TOGBR2
+  ABB_WriteRegister(TOGBR2, 0x10);  
+
+  // Clear, assuming that it works like IBUFPTR of Vega
+  ABB_WriteRegister(TOGBR2, 0x0);  
+
+  // Write the ramp data
+  for (i=0;i<16;i++)
+    ABB_WriteRegister(BULDATA1_2, TM_ul_data[i]>>6);  
+
+  // Stop the SPI clock
+  #ifdef SPI_CLK_LOW_POWER
+    SPI_CLK_DISABLE
+  #endif
+}
+
+//////////////////////// IDEV-INLO integration of sleep mode for Syren ///////////////////////////////////////
+
+#if (ANLG_FAM == 3)
+
+  // Syren Sleep configuration function --------------------------
+  void Syren_Sleep_Config(SYS_UWORD16 sleep_type,SYS_UWORD16 bg_select, SYS_UWORD16 sleep_delay)
+  {
+    volatile SYS_UWORD16 status,sl_ldo_stat;
+
+    ABB_SetPage(PAGE1);                            // Initialize transmit register. This transmission
+                                                   // change the register page in ABB for usp to pg1
+
+    ABB_WriteRegister(VRPCCFG, sleep_delay);       // write delay value   
+
+    sl_ldo_stat = ((sleep_type<<9|bg_select<<8) & 0x0374);
+
+    ABB_WriteRegister(VRPCMSKSLP, sl_ldo_stat);     // write sleep ldo configuration   
+
+    ABB_SetPage(PAGE0);                            // Initialize transmit register. This transmission
+                                                   // change the register page in ABB for usp to pg0
+  }
+#endif
+
+
+#if (OP_L1_STANDALONE == 0)
+/*-----------------------------------------------------------------------*/
+/* ABB_Power_Off()                                                       */
+/*                                                                       */
+/* This function uses the SPI to switch off the ABB.                     */
+/*                                                                       */
+/*-----------------------------------------------------------------------*/    
+void ABB_Power_Off(void)
+{
+  // Wait until all necessary actions are performed (write in FFS, etc...) to power-off the board (empirical value - 30 ticks).
+  NU_Sleep (30);
+
+  // Wait also until <ON/OFF> key is released.
+  // This is needed to avoid, if the power key is pressed for a long time, to switch
+  // ON-switch OFF the mobile, until the power key is released.
+  #if((ANLG_FAM == 1) || (ANLG_FAM == 2)) 
+    while ((ABB_Read_Status() & ONREFLT) == PWR_OFF_KEY_PRESSED) {
+  #elif(ANLG_FAM == 3) 
+    while ((ABB_Read_Register_on_page(PAGE1, VRPCCFG) & PWOND) == PWR_OFF_KEY_PRESSED) {
+  #endif
+  
+  NU_Sleep (1); }
+
+  BZ_KeyBeep_OFF();
+
+  #if(ANLG_FAM == 1) 
+    ABB_Write_Register_on_page(PAGE0, VRPCCTL2, 0x00EE);
+  #elif((ANLG_FAM == 2) || (ANLG_FAM == 3)) 
+    ABB_Write_Register_on_page(PAGE0, VRPCDEV, 0x0001);
+  #endif 
+}
+#endif
+
+
+