Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /** *******************************************************************************************
- THIS FILE CONTAINS ALL THE LOW LEVEL FUNCTIONS SPECIFIC TO THE CC1020
- *******************************************************************************************
- * <p>InitializeCC1020 is just a cozy place to call all of the functions needed to set up
- * the CC1020 on power up. All of these only need to be called at startup and having them
- * here helps tidy up main().</p>
- *
- * @post The CC1020 needs to be placed into a mode. Enter TX mode (SetupCC1020TX), RX mode
- * (SetupCC1020RX) or power down mode (SetupCC1020PD)
- * From power-down mode to RX:
- * 1) WakeUpCC1020ToRX
- * 2) SetupCC1020RX
- * From power-down mode to TX:
- * 1) WakeUpCC1020ToTX
- * 2) SetupCC1020TX
- * Switching from RX to TX mode:
- * 1) SetupCC1020TX
- * Switching from TX to RX mode:
- * 1) SetupCC1020RX
- **/
- #include "CC1020.h"
- char InitializeCC1020(unsigned char *Configuration, unsigned char setconfig)
- {
- unsigned char success;
- if(setconfig)
- {
- *Configuration={MAIN, INTERFACE, RESET, SEQUENCING,
- FREQ_2A, FREQ_1A, FREQ_0A, CLOCK_A,
- FREQ_2B, FREQ_1B, FREQ_0B, CLOCK_B,
- VCO, MODEM, DEVIATION, AFC_CONTROL,
- FILTER, VGA1, VGA2, VGA3, VGA4, LOCK,
- FRONTEND, ANALOG, BUFF_SWING,
- BUFF_CURRENT, PLL_BW, CALIBRATE,
- PA_POWER, MATCH, PHASE_COMP, GAIN_COMP,
- POWERDOWN};
- }
- SetupCC1020PD();
- ResetCC1020();
- ConfigureCC1020(Configuration);
- WakeUpCC1020ToTX();
- //DIO to output code goes here
- success=CalibrateCC1020()<<1;
- WakeUpCC1020ToRX();
- //DIO to input code goes here
- success|=CalibrateCC1020();
- //the two LSB of success let us know if the calibration worked.
- return success;
- }
- /** @} */
- /*
- * This routine calibrates the CC1020. It should be called for both receive and transmit states.
- *
- * @pre All configuration registers have been populated and the CC1020 has been either placed in
- * transmit or receive mode.
- *
- * @post The CC1020 is calibrated for either transmit or receive mode.
- *
- * @return 0 if calibration fails, non-zero otherwise. Checks the LOCK to check for success
- */
- char CalibrateCC1020(void)
- {
- volatile int TimeOutCounter;
- volatile int nCalAttempt;
- // Turn off PA to avoid spurs during calibration in TX mode
- WriteToCC1020Register(CC1020_PA_POWER,0x00);
- // Calibrate, and re-calibrate if necessary:
- for (nCalAttempt = 2 /*CAL_ATTEMPT_MAX*/; (nCalAttempt>0); nCalAttempt--) {
- // Start calibration
- WriteToCC1020Register(CC1020_CALIBRATE,0xB4);
- // Monitor actual calibration start (ref. Errata Note 04 - CC1020)
- for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x80)&&(TimeOutCounter>0); TimeOutCounter--);
- /**
- * @remarks
- * Important note from Chipcon:
- * In active mode the CC1020 should theoretically initiate an internal action/process more or less
- * instantly upon receiving any command from e.g. an MCU. However, upon sending a [calibration start]
- * command to CC1020, tests shows that the [STATUS.CAL_COMPLETE]-signal sometimes remains asserted
- * (or idle) close to 100 usec after the command has been originally issued. Consequently this process
- * must be carefully monitored to avoid premature PLL LOCK monitoring; do not proceed with subsequent
- * PLL LOCK monitoring before the calibration has actually completed inside the CC1020! Errata Note 04
- * suggests that [calibration start] should be monitored by a fixed timeout > 100 usec. However, the
- * above method implements an adaptive monitoring of [calibration start], which basically waits for the
- * [STATUS.CAL_COMPLETE]-signal to initialise/deassert (indicating calibration has actually started)
- * before proceeding with monitoring calibration complete and PLL LOCK. Chipcon considers both methods
- * safe, and thus leaves it up to the user, which one to use.
- */
- // Monitor calibration complete
- for(TimeOutCounter=CAL_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x80)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);
- // Monitor lock
- for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x00)&&(TimeOutCounter>0); TimeOutCounter--);
- // Abort further recalibration attempts if successful LOCK
- if((ReadFromCC1020Register(CC1020_STATUS)&0x10) == 0x10) {
- break;
- }
- }
- // Restore PA setting
- WriteToCC1020Register(CC1020_PA_POWER, PA_POWER);
- // Return state of LOCK_CONTINUOUS bit
- return ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10);
- }
- /**
- * Send configuration data to the CC1020.
- *
- * @pre Default configuration values have been defined in CC1020settings.h
- *
- * @post CC1020 Configuration registers are loaded with configuration values from
- * CC1020settings.h
- */
- void ConfigureCC1020(char* Configuration)
- {
- short val;
- char i;
- for (i=0;i<33;i++)
- {
- val=Configuration[i];
- WriteToCC1020Register(i,val);
- }
- }
- /**
- * Reset the CC1020, clearing all registers.
- *
- * @post CC1020 is reset and all configuration registers are cleared.
- */
- void ResetCC1020(void)
- {
- // Reset CC1020
- WriteToCC1020Register(CC1020_MAIN, 0x0F&~0x01);
- // Bring CC1020 out of reset
- WriteToCC1020Register(CC1020_MAIN, 0x1F);
- }
- /**
- * This routine puts the CC1020 into power down mode. Use WakeUpCC1020ToRX followed by SetupCC1020RX or WakeupCC1020ToTX
- * followed by SetupCC1020TX to wake up from power down.
- *
- * @pre CC1020 is not in Power Down mode
- *
- * @post CC1020 is in Power Down mode. Internal VCO and PA are off.
- */
- void SetupCC1020PD(void)
- {
- // Put CC1020 into power-down
- WriteToCC1020Register(CC1020_MAIN,0x1F);
- // Turn off PA to minimise current draw
- WriteToCC1020Register(CC1020_PA_POWER,0x00);
- }
- /**
- * This routine puts the CC1020 into RX mode.
- *
- * @pre CC1020 is not in receive mode. If the CC1020 is coming out of Power Down mode, WakeupCC1020ToRx must be called first.
- *
- * @post CC1020 is in receive mode.
- *
- * @return Lock status.
- */
- char SetupCC1020RX(void)
- {
- volatile int TimeOutCounter;
- char lock_status;
- char dummy, addr;
- // Switch into RX, switch to freq. reg A
- WriteToCC1020Register(CC1020_MAIN,0x11);
- // Setup bias current adjustment
- WriteToCC1020Register(CC1020_ANALOG,RXANALOG);
- WriteToCC1020Register(CC1020_DEVIATION,RXDEVIATION);
- WriteToCC1020Register(CC1020_AFC_CONTROL,0xC3);
- WriteToCC1020Register(CC1020_VGA3,0x2E);
- WriteToCC1020Register(CC1020_VGA4,0x29);
- // Monitor LOCK
- for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);
- // If PLL in lock
- if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
- // Indicate PLL in LOCK
- lock_status = LOCK_OK;
- // Else (PLL out of LOCK)
- }else{
- // If recalibration ok
- if(CalibrateCC1020()){
- // Indicate PLL in LOCK
- lock_status = LOCK_RECAL_OK;
- // Else (recalibration failed)
- }else{
- // Indicate PLL out of LOCK
- lock_status = LOCK_NOK;
- }
- }
- WriteToCC1020Register(CC1020_MAIN,RXMAIN);
- // Switch RX part of CC1020 on
- return lock_status;
- }
- /**
- * This routine puts the CC1020 into TX mode.
- *
- * @pre CC1020 is not in Tx mode. When switching to TX from PD, use WakeupC1020ToTX first.
- *
- * @post CC1020 is in Tx mode.
- *
- * @return Lock status.
- */
- char SetupCC1020TX(void)
- {
- volatile int TimeOutCounter;
- char lock_status;
- // Turn off PA to avoid frequency splatter
- WriteToCC1020Register(CC1020_PA_POWER,0x00);
- // Setup bias current adjustment
- WriteToCC1020Register(CC1020_ANALOG,TXANALOG);
- WriteToCC1020Register(CC1020_DEVIATION,TXDEVIATION);
- WriteToCC1020Register(CC1020_AFC_CONTROL,0xC1);
- WriteToCC1020Register(CC1020_VGA3,0x2F);
- WriteToCC1020Register(CC1020_VGA4,0x2D);
- // Switch into TX, switch to freq. reg B
- WriteToCC1020Register(CC1020_MAIN,0xC1);
- // Monitor LOCK
- for(TimeOutCounter=LOCK_TIMEOUT; ((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0)&&(TimeOutCounter>0); TimeOutCounter--);
- // If PLL in lock
- if((ReadFromCC1020Register(CC1020_STATUS)&0x10)==0x10){
- // Indicate PLL in LOCK
- lock_status = LOCK_OK;
- // Else (PLL out of LOCK)
- }else{
- // If recalibration ok
- if(CalibrateCC1020()){
- // Indicate PLL in LOCK
- lock_status = LOCK_RECAL_OK;
- // Else (recalibration failed)
- }else{
- // Indicate PLL out of LOCK
- lock_status = LOCK_NOK;
- }
- }
- // Restore PA setting
- WriteToCC1020Register(CC1020_PA_POWER,PA_POWER);
- // Turn OFF DCLK squelch in TX
- WriteToCC1020Register(CC1020_INTERFACE,ReadFromCC1020Register(CC1020_INTERFACE)&~0x10);
- // Return LOCK status to application
- return (lock_status);
- }
- /**
- * This routine wakes the CC1020 up from PD mode to RX mode
- *
- * @pre CC1020 is in Power Down mode.
- *
- * @post CC1020 is ready for SetupCC1020RX()
- */
- void WakeUpCC1020ToRX(void)
- {
- volatile int i;
- // Turn on xtal oscillator core
- WriteToCC1020Register(CC1020_MAIN,0x1B);
- // Setup bias current adjustment
- WriteToCC1020Register(CC1020_ANALOG,RXANALOG);
- WriteToCC1020Register(CC1020_DEVIATION,RXDEVIATION);
- WriteToCC1020Register(CC1020_AFC_CONTROL,0xC3);
- WriteToCC1020Register(CC1020_VGA3,0x2E);
- WriteToCC1020Register(CC1020_VGA4,0x29);
- // Insert wait routine here, must wait for xtal oscillator to stabilise,
- // typically takes 2-5ms.
- _delay_ms(5);
- // for (i=0x0260; i > 0; i--);
- // Turn on bias generator
- WriteToCC1020Register(CC1020_MAIN,0x19);
- // Wait for 150 usec
- _delay_us(150);
- // for (i=0x0010; i > 0; i--);
- // Turn on frequency synthesiser
- WriteToCC1020Register(CC1020_MAIN,0x11);
- }
- /**
- * This routine wakes the CC1020 up from PD mode to TX mode
- *
- * @pre CC1020 is in Power Down mode.
- *
- * @post CC1020 is ready for SetupCC1020TX()
- */
- void WakeUpCC1020ToTX(void)
- {
- volatile int i;
- // Turn on xtal oscillator core
- WriteToCC1020Register(CC1020_MAIN,0xDB);
- // Setup bias current adjustment
- WriteToCC1020Register(CC1020_ANALOG,TXANALOG);
- WriteToCC1020Register(CC1020_DEVIATION,TXDEVIATION);
- WriteToCC1020Register(CC1020_AFC_CONTROL,0xC1);
- WriteToCC1020Register(CC1020_VGA3,0x2F);
- WriteToCC1020Register(CC1020_VGA4,0x2D);
- // Insert wait routine here, must wait for xtal oscillator to stabilise,
- // typically takes 2-5ms.
- _delay_ms(5);
- // for (i=0x0260; i > 0; i--);
- // Turn on bias generator
- WriteToCC1020Register(CC1020_MAIN,0xD9);
- // Wait for 150 usec
- _delay_us(150);
- // for (i=0x0010; i > 0; i--);
- // Turn on frequency synthesiser
- WriteToCC1020Register(CC1020_MAIN,0xD1);
- }
- /**
- * Reads a byte from one of the CC1020 registers.
- *
- * @pre SPI bus is open and configured
- *
- * @param addr The configuaration register address to read from.
- *
- * @return The specified CC1020 register value.
- *
- * @remarks There is a strange timing issue with either the implementation of the
- * C18 SPI library or the CC1020's SPI implementation. This is resolved by writing
- * directly to the registers rather than using the Microchip provided function calls.
- */
- char ReadFromCC1020Register(char addr)
- {
- SS_LOW;
- SPDR = (addr<<1)&0xFE;
- while(!(SPSR & (1<<SPIF)))
- ;
- unsigned char a=SPDR; //have to read this to clear the flag
- SPDR = 0x00; //dummy write
- while(!(SPSR & (1<<SPIF)))
- ;
- a=SPDR;
- SS_HIGH;
- return a;
- }
- /**
- * Writes configuration data given by 'char data' to a register in the CC1020 configuration registers
- * given by 'char addr'
- *
- * @pre SPI bus is open and configured.
- *
- * @post CC1020 register at 'addr' contains value of 'data.'
- *
- * @param addr The register address to write to.
- * @param data Register contents to write.
- */
- void WriteToCC1020Register(char addr, char data)
- {
- SS_LOW;
- SPDR = (addr<<1)|0x01;
- while(!(SPSR & (1<<SPIF)))
- ;
- unsigned char a=SPDR; //have to read this to clear the flag
- SPDR = data;
- while(!(SPSR & (1<<SPIF)))
- ;
- SS_HIGH;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement