FreeCalypso > hg > fc-tourmaline
view src/cs/drivers/drv_core/abb/abb.c @ 267:10b3a6876273
fc-target.h preprocessor symbols: introduce CONFIG_TARGET_LEO_RFFE
Out of our currently existing supported targets, Leonardo and Tango
use TI's classic Leonardo RFFE wiring. However, we would like to
use the same quadband RFFE with the same classic wiring on our
FreeCalypso Libre Dumbphone handset, and also on the planned
development board that will serve as a stepping stone toward that
goal. Therefore, we introduce the new CONFIG_TARGET_LEO_RFFE
preprocessor symbol, and conditionalize on this symbol in tpudrv12.h,
instead of a growing || of different targets.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 09 Jun 2021 07:26:51 +0000 |
parents | 160a5b3a076c |
children |
line wrap: on
line source
/**********************************************************************************/ /* 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 /* * The following conditional compilation control is a FreeCalypso addition. * TI's original code always configured the BCICONF register with * MESBB and BBCHGEN bits set, enabling both charging and the measurement * resistive divider for the backup battery. However, on our primary * hw targets (Openmoko GTA02 and our own FCDEV3B) Iota's VBACKUP pin * is unconnected, whereas on Mot C139 and Pirelli DP-L10 "alien" hw * the VBACKUP situation is unclear. But at least on our known hw * with VBACKUP unconnected, it is better to leave backup battery charging * and measurement OFF - TI's original config seems to be a drain on * the main battery. Therefore, we are going to leave MESBB and BBCHGEN * off until and unless we have a hw target where backup battery charging * and measurement are appropriate. */ #define ENABLE_BACKUP_BATTERY 0 /* * The following ABB_sleep_allowed global variable is yet another FreeCalypso * addition. Here is the issue: some handset boards have the controller/driver * chip in the LCD powered from Iota VRIO, which is generally a very sensible * arrangement. As one reference example, our 176x220 pixel TFT LCDs which * we are considering for our own FC handset draw about 3 mA from their Vci * supply which we connect to VRIO - perfectly fine when the regulators are * in their normal Active mode. But what about sleep mode? Sleep mode VRIO * current limit is only 1 mA, thus the combination of the LCD being on and * drawing 3 mA with the ABB in sleep mode is invalid. TI's original code * already had a check for VRPCSTS: PWON and RPWON need to be released and * the charger needs to be unplugged in order to enter ABB superdeep sleep. * We are extending this check with one more condition: ABB_sleep_allowed * needs to be nonzero; the intent is that this variable will be set by the * code responsible for putting the LCD into its own powerdown mode. * This logic is included only for affected targets with LCDs. */ #ifdef ABB_SLEEP_RESTRICTION int ABB_sleep_allowed = 0; #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; STATUS sem_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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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; // 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); // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } /*-----------------------------------------------------------------------*/ /* 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; STATUS sem_status; SYS_UWORD16 reg_val; #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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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; /* 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); // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION 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; STATUS sem_status; SYS_UWORD16 reg_val; #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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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); #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 // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION 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; STATUS sem_status; #if ((ANLG_FAM == 2) || (ANLG_FAM == 3)) SYS_UWORD32 reg; #endif #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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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; 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. #if ENABLE_BACKUP_BATTERY ABB_WriteRegister(BCICONF, 0x060); #else ABB_WriteRegister(BCICONF, 0x000); #endif /* ************************ 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); // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if (ABB_SEMAPHORE_PROTECTION == 3) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } /*-----------------------------------------------------------------------*/ /* 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; STATUS sem_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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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; // 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 // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if (ABB_SEMAPHORE_PROTECTION == 3) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } /*-----------------------------------------------------------------------*/ /* 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; STATUS sem_status; SYS_UWORD16 reg_val; #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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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; // 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); // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if (ABB_SEMAPHORE_PROTECTION == 3) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } /*------------------------------------------------------------------------*/ /* 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); #if ENABLE_BACKUP_BATTERY // 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); #endif // 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; #ifdef ABB_SLEEP_RESTRICTION if (reg_val == 0x30 && ABB_sleep_allowed) #else if (reg_val == 0x30) #endif { // 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); #if ENABLE_BACKUP_BATTERY // Read BCICONF register value and enable BB measurement bridge enable BB charge. reg_val = ABB_ReadRegister(BCICONF) | 0x0060; ABB_WriteRegister(BCICONF, reg_val); #endif /* *************************************************************************************************** */ // 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; STATUS sem_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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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(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); // Stop the SPI clock #ifdef SPI_CLK_LOW_POWER SPI_CLK_DISABLE #endif #if ((ABB_SEMAPHORE_PROTECTION == 1) || (ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } /*-----------------------------------------------------------------------*/ /* 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; STATUS sem_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. sem_status = NU_Obtain_Semaphore(&abb_sem, NU_SUSPEND); #endif // ABB_SEMAPHORE_PROTECTION // 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 #if ((ABB_SEMAPHORE_PROTECTION == 2) || (ABB_SEMAPHORE_PROTECTION == 3)) // release the semaphore only if it has correctly been created. if(sem_status == NU_SUCCESS) { NU_Release_Semaphore(&abb_sem); } #endif // ABB_SEMAPHORE_PROTECTION } //////////////////////// 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