//-----------------------------------------------------------------------------
//  char RFReceivePacket(char *rxBuffer, char *length)
//
//  DESCRIPTION:
//  Receives a packet of variable length (first byte in the packet must be the
//  length byte).  The packet length should not exceed the RXFIFO size.  To use
//  this function, APPEND_STATUS in the PKTCTRL1 register must be enabled.  It
//  is assumed that the function is called after it is known that a packet has
//  been received; for example, in response to GDO0 going low when it is
//  configured to output packet reception status.
//
//  The RXBYTES register is first read to ensure there are bytes in the FIFO.
//  This is done because the GDO signal will go high even if the FIFO is flushed
//  due to address filtering, CRC filtering, or packet length filtering.
//
//  ARGUMENTS:
//      char *rxBuffer
//          Pointer to the buffer where the incoming data should be stored
//      char *length
//          Pointer to a variable containing the size of the buffer where the
//          incoming data should be stored. After this function returns, that
//          variable holds the packet length.
//
//  RETURN VALUE:
//      char
//          0x80:  CRC OK
//          0x00:  CRC NOT OK (or no pkt was put in the RXFIFO due to filtering)
//-----------------------------------------------------------------------------
char RFReceivePacket(char *rxBuffer, char *length, char *retStatus)
{
  char status[2];
  char pktLen;

  if ((TI_CC_SPIReadStatus(TI_CCxxx0_RXBYTES) & TI_CCxxx0_NUM_RXBYTES))
  {
    pktLen = TI_CC_SPIReadReg(TI_CCxxx0_RXFIFO); // Read length byte

    if (pktLen <= *length)                  // If pktLen size <= rxBuffer
    {
      TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, rxBuffer, pktLen); // Pull data
      *length = pktLen;                     // Return the actual size
      TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, status, 2); // Read appended status bytes
      if (retStatus){
        retStatus[0]=status[0];
        retStatus[1]=status[1];
      }
      return (char)(status[TI_CCxxx0_LQI_RX]&TI_CCxxx0_CRC_OK);
    }                                       // Return CRC_OK bit
    else
    {
      *length = pktLen;                     // Return the large size
      TI_CC_SPIStrobe(TI_CCxxx0_SFRX);      // Flush RXFIFO
      return 0;                             // Error
    }
  }
  else
      return 0;                             // Error
}
Beispiel #2
0
//-----------------------------------------------------------------------------
//  char RFReceivePacket(char *rxBuffer, char *length)
//
//  DESCRIPTION:
//  Receives a packet of variable length (first byte in the packet must be the
//  length byte).  The packet length should not exceed the RXFIFO size.  To use
//  this function, APPEND_STATUS in the PKTCTRL1 register must be enabled.  It
//  is assumed that the function is called after it is known that a packet has
//  been received; for example, in response to GDO0 going low when it is
//  configured to output packet reception status.
//
//  The RXBYTES register is first read to ensure there are bytes in the FIFO.
//  This is done because the GDO signal will go high even if the FIFO is flushed
//  due to address filtering, CRC filtering, or packet length filtering.
//
//  ARGUMENTS:
//      char *rxBuffer
//          Pointer to the buffer where the incoming data should be stored
//      char *length
//          Pointer to location where length will be returned
//
//  RETURN VALUE:
//      char
//          0x80:  CRC OK
//          0x00:  CRC NOT OK (or no pkt was put in the RXFIFO due to filtering)
//-----------------------------------------------------------------------------
char RFReceivePacket(char *rxBuffer, char *length)
{
  char status[2];
  char pktLen;
  
  if ((TI_CC_SPIReadStatus(TI_CCxxx0_RXBYTES) & TI_CCxxx0_NUM_RXBYTES))
  {
    // Use the appropriate library function to read the first byte in the
    // RX FIFO, which is the length of the packet (the total remaining bytes
    // in this packet after reading this byte).  
    // Hint:  how many bytes are being retrieved?  One or multiple?  
    pktLen = TI_CC_SPIReadReg(TI_CCxxx0_RXFIFO);
    
    // Use the appropriate library function to read the rest of the packet into
    // rxBuffer (i.e., read pktLen bytes out of the FIFO)
    // Hint:  how many bytes are being retrieved?  One or multiple?  
    TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, rxBuffer, pktLen); // Pull data
    *length = pktLen;                       // Return the actual size

    // Our initialization code configured this CC1100 to append two status
    // bytes to the end of the received packets.  These bytes are still in the
    // FIFO.  Use the appropriate library function to read these two bytes into
    // the status array
    TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, status, 2);

    return (char)(status[TI_CCxxx0_LQI_RX]&TI_CCxxx0_CRC_OK);
  }
  else
    return 0;                               // Error
}
Beispiel #3
0
//-----------------------------------------------------------------------------
char RFReceivePacket(char *rxBuffer, char *length)
{
    char pktLen;
    if ((TI_CC_SPIReadStatus(TI_CCxxx0_RXBYTES) & TI_CCxxx0_NUM_RXBYTES)) {
        pktLen = TI_CC_SPIReadReg(TI_CCxxx0_RXFIFO); // Quantes dades hi ha?
#ifdef LSMAKER_BASE
//			LS_USB_printf("\r\nLenR %d LenE %d\r\n", pktLen, *length);
#endif
        if ((pktLen <= *length) && (pktLen > 0)) {   // Suficients=
            TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, rxBuffer, pktLen+2); // Llegeix les dades + 2 d'estat
            *length = pktLen;                     // Returna el tamany real
            RssiAct = rxBuffer[LengthDATA];	// El primer byte indica el RSSI
            LQIAct  = rxBuffer[LengthDATA+TI_CCxxx0_LQI_RX] & 0x7f;	// I el segon l'indicador de qualitat de l'enllaç
            ModeRecepcio();
            return (char)(rxBuffer[LengthDATA+TI_CCxxx0_LQI_RX]&TI_CCxxx0_CRC_OK); // Return CRC_OK bit

        } else {
            *length = pktLen;                   // Return the large size
            TI_CC_SPIStrobe(TI_CCxxx0_SFRX);   	// Flush RXFIFO
            IoWait(2);
            ModeRecepcio();
            return 0;                           // Error
        }
    } else {
        ModeRecepcio();
        return 0;                             	// Error
    }
    return 0;
}
//-----------------------------------------------------------------------------
//  char RFReceivePacket(char *rxBuffer, char *length)
//
//  DESCRIPTION:
//  Receives a packet of variable length (first byte in the packet must be the
//  length byte).  The packet length should not exceed the RXFIFO size.  To use
//  this function, APPEND_STATUS in the PKTCTRL1 register must be enabled.  It
//  is assumed that the function is called after it is known that a packet has
//  been received; for example, in response to GDO0 going low when it is
//  configured to output packet reception status.
//
//  The RXBYTES register is first read to ensure there are bytes in the FIFO.
//  This is done because the GDO signal will go high even if the FIFO is flushed
//  due to address filtering, CRC filtering, or packet length filtering.
//
//  ARGUMENTS:
//      char *rxBuffer
//          Pointer to the buffer where the incoming data should be stored
//      char *length
//          Pointer to a variable containing the size of the buffer where the
//          incoming data should be stored. After this function returns, that
//          variable holds the packet length.
//
//  RETURN VALUE:
//      char
//          0x80:  CRC OK
//          0x00:  CRC NOT OK (or no pkt was put in the RXFIFO due to filtering)
//-----------------------------------------------------------------------------
char RFReceivePacket(char *rxBuffer, char *length)
{
  char status[2];
  char pktLen;

  char rxBytesVerify;
  char rxBytes;

  //mrfi code
  rxBytesVerify = TI_CC_SPIReadReg( TI_CCxxx0_RXBYTES );
  do
  {
    rxBytes = rxBytesVerify;
    rxBytesVerify = TI_CC_SPIReadReg( TI_CCxxx0_RXBYTES );
  }
  while (rxBytes != rxBytesVerify);
  
  if (rxBytes ==0) return 0;
  //end of mrfi code
  
  //if ((TI_CC_SPIReadStatus(TI_CCxxx0_RXBYTES) & TI_CCxxx0_NUM_RXBYTES))
  {
    pktLen = TI_CC_SPIReadReg(TI_CCxxx0_RXFIFO); // Read length byte

    if (pktLen > *length)                  // If pktLen size <= rxBuffer
    {
      *length = pktLen;                     // Return the large size

      TI_CC_SPIStrobe(TI_CCxxx0_SIDLE);	    // set IDLE - MRFI code
      TI_CC_SPIStrobe(TI_CCxxx0_SFRX);      // Flush RXFIFO
      TI_CC_SPIStrobe(TI_CCxxx0_SRX);       // RX state - from MRFI
      return 0;                             // Error
    }
    else 
    {
      TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, rxBuffer, pktLen); // Pull data
      *length = pktLen;                     // Return the actual size
      TI_CC_SPIReadBurstReg(TI_CCxxx0_RXFIFO, status, 2);
                                            // Read appended status bytes
      return (char)(status[TI_CCxxx0_LQI_RX]&TI_CCxxx0_CRC_OK);
    }                                       // Return CRC_OK bit
  }
  //else
      return 0;                             // Error
}
//Perform the scan, returns the amount of bytes stored in the rssiArray
unsigned int scanFreqBands(void) {
	//Amount of bytes stored in the rssiArray
	unsigned int rssiLen=0;

	BYTE i;
	//RSSI value as reported by the CC device
	UINT8 rssi_dec;
	//RSSI value translated to dBm
	INT16 rssi_dBm;
	//Variable to store the current value of the TEST0 register
	BYTE currentTest0;
	//Variable to store the FREQ register value for the current frequency
	UINT32 freqRegs;
	//Temp variables for the FREQ register calculation
	BYTE tempFreq2,tempFreq1,tempFreq0;
	//Variables to store the current frequency to be scanned
	UINT16 currentFreqMhz, currentFreqKhz;
	//Controls if we should perform a calibration before starting RX
	//in the current frequency
	BOOL calNeeded;
	//Copy of the pointer to the RSSI array
	BYTE * rssiPtr=rssiTable;

	//Initialize the value of the frequency counters
	currentFreqMhz = scanParameters.startFreqMhz;
	currentFreqKhz = scanParameters.startFreqKhz;
	//Initialize freqRegs to the value for startFreq
	freqRegs=freqRegsBase;
	//Get reset value of TEST0
	currentTest0=TI_CC_SPIReadReg(TI_CCxxx0_TEST0);
	//For the start frequency a calibration is always needed
	calNeeded=TRUE;

	while (currentFreqMhz<scanParameters.stopFreqMhz || currentFreqKhz<scanParameters.stopFreqKhz) {
		//Find out if we need to change the TEST0 register
		for(i=0; i<NUM_TEST0_RANGES; i++){
			//Find the TEST0 range the current frequency belongs to
			if(currentFreqMhz>=test0RangeLimits[i] && currentFreqMhz<=test0RangeLimits[i+1]){
				if(currentTest0!=test0Values[i]){
					TI_CC_SPIWriteReg(TI_CCxxx0_TEST0, test0Values[i]);
					currentTest0=TI_CC_SPIReadReg(TI_CCxxx0_TEST0);
					//Also change the value of the FSCAL2 register to enable the VCO calibration stage
					TI_CC_SPIWriteReg(TI_CCxxx0_FSCAL2, 0x2A);
					calNeeded=TRUE;
				}
				break;
			}
		}

		//Write the frequency registers FREQ2, FREQ1 and FREQ0
		tempFreq0=(BYTE)freqRegs;
		tempFreq1=(BYTE)(freqRegs>>8);
		tempFreq2=(BYTE)(freqRegs>>16);
		TI_CC_SPIWriteReg(TI_CCxxx0_FREQ2, tempFreq2);
		TI_CC_SPIWriteReg(TI_CCxxx0_FREQ1, tempFreq1);
		TI_CC_SPIWriteReg(TI_CCxxx0_FREQ0, tempFreq0);

		//Calibrate if needed
		if(calNeeded){
			TI_CC_SPIStrobe(TI_CCxxx0_SCAL);
			calNeeded=FALSE;
		}

		//Enter RX mode by issuing an SRX strobe command
		TI_CC_SPIStrobe(TI_CCxxx0_SRX);

		static BYTE state;
		//Wait for radio to enter RX state by checking the status byte
		do {
			//state = TI_CC_GetTxStatus() & TI_CCxxx0_STATUS_STATE_BM;
			state=TI_CC_SPIReadStatus(TI_CCxxx0_MARCSTATE);
			state&=TI_CCxxx0_MARCSTATE_MASK;
			//Flush the FIFO RX buffer in case of overflow
			if(state==TI_CCxxx0_MARCSTATE_SM_RXFIFO_OVERFLOW)
				TI_CC_SPIStrobe(TI_CCxxx0_SFRX);
		} while (state != TI_CCxxx0_MARCSTATE_SM_RX);

		//Wait for RSSI to be valid
		usleep(scanParameters.rssiWait);

		//Enter IDLE state by issuing an SIDLE strobe command
		TI_CC_SPIStrobe(TI_CCxxx0_SIDLE);

		//Read RSSI value and store it in rssi_dec
		rssi_dec = TI_CC_SPIReadStatus(TI_CCxxx0_RSSI);

		//Store the value in the rssi array
		*rssiPtr++=rssi_dec;
		//Update rssiLen
		rssiLen+=sizeof(BYTE);

		//Flush the FIFO buffer, just in case
		TI_CC_SPIStrobe(TI_CCxxx0_SFRX);

		//At the end of the loop, update the frequency counters
		//TODO: Consider using Horner division code
		currentFreqKhz += scanParameters.freqResolution;
		if (currentFreqKhz >= 1000) {
			currentFreqMhz += currentFreqKhz/1000;
			currentFreqKhz %= 1000;
			//According to DN508, a frequency calibration
			//covers all frequencies less than 1Mhz apart
			//from the one we calibrated for
			calNeeded=TRUE;
		}
		//Update the value of the FREQ2:FREQ1:FREQ0 register value
		freqRegs+=freqRegsStep;
	}

	return rssiLen;
}
//This function configures the SPI interface
//to the CC1101, resets the device and
//sets the scanning parameters
//GETS: Pointer to the scan parameters
//and the pointer to the structure
//where the Rssi values will be stored
//RETURNS: NULL if something went wrong
//or pointer to the SCAN_CONFIG structure
//with the parameters actually used by the function
SCAN_CONFIG * configScanner(SCAN_CONFIG * pconfigParameters, BYTE * rssiArray) {
	BYTE reg;

	//Store the array pointer, if it's NULL report failure
	if(rssiArray==NULL)
		return NULL;
	rssiTable = rssiArray;
	//Configure the SPI interface
	TI_CC_SPISetup();
	//Reset the CC1101
	TI_CC_PowerupResetCCxxxx();

	//If pconfigParameters is NULL, use defaults
	if(pconfigParameters==NULL){
		pconfigParameters=&scanParameters;
		scanParameters.startFreqMhz=MIN_FREQ;
		scanParameters.startFreqKhz=0;
		scanParameters.stopFreqMhz=MAX_FREQ;
		//scanParameters.stopFreqMhz=820;
		scanParameters.stopFreqKhz=0;
		scanParameters.freqResolution=DEFAULT_RESOLUTION;
		scanParameters.modFormat=TI_CCxxx0_MDMCFG2_MODFORMAT_ASK;
		scanParameters.rssiWait=AVG_WAIT_WITH_AGC;
		scanParameters.activateAGC=TRUE;
	}

	/**Start parsing parameters**/

	//Parsing startFreq
	if (pconfigParameters->startFreqMhz < MIN_FREQ
			|| pconfigParameters->startFreqMhz > MAX_FREQ) {
		//Use default value: MIN_FREQ
		scanParameters.startFreqMhz = MIN_FREQ;
		scanParameters.startFreqKhz = 0;
	} else {
		scanParameters.startFreqMhz = pconfigParameters->startFreqMhz;
		if (pconfigParameters->startFreqKhz>= 1000
				|| pconfigParameters->startFreqMhz==MAX_FREQ) {
			//Use default value: 0
			scanParameters.startFreqKhz = 0;
		} else{
			scanParameters.startFreqKhz = pconfigParameters->startFreqKhz;
		}
	}

		//Parsing stopFreq
	if (pconfigParameters->stopFreqMhz < MIN_FREQ
			|| pconfigParameters->stopFreqMhz > MAX_FREQ) {
		//Use default value: MAX_FREQ
		scanParameters.stopFreqMhz = MAX_FREQ;
		scanParameters.stopFreqKhz = 0;
	} else {
		scanParameters.stopFreqMhz = pconfigParameters->stopFreqMhz;
		if (pconfigParameters->stopFreqKhz>= 1000
				|| pconfigParameters->stopFreqMhz==MAX_FREQ) {
			//Use default value: 0
			scanParameters.stopFreqKhz = 0;
		} else{
			scanParameters.stopFreqKhz = pconfigParameters->stopFreqKhz;
		}
	}
		//Check if the range limits make sense
	if (scanParameters.startFreqMhz > scanParameters.stopFreqMhz)
		return NULL;
	if (scanParameters.startFreqMhz == scanParameters.stopFreqMhz
			&& scanParameters.startFreqKhz > scanParameters.stopFreqKhz)
		return NULL;
	if (scanParameters.startFreqMhz == MAX_FREQ
			&& scanParameters.startFreqKhz > 0)
		return NULL;

	//Parsing filterBandwidth
	if(pconfigParameters->freqResolution<filterBandwidthList[0][0] ||
			pconfigParameters->freqResolution>filterBandwidthList[3][3])
		scanParameters.freqResolution=DEFAULT_RESOLUTION;

	//Find the valid filter value closest to the one requested
	UINT16 diff, tempDiff;
	BYTE i, j, row, column;
	for (i = 0; i < sizeof(filterBandwidthList); i++) {
		for (j = 0; j < sizeof(*filterBandwidthList); j++) {
			if(filterBandwidthList[i][j] > pconfigParameters->freqResolution)
				tempDiff=filterBandwidthList[i][j] - pconfigParameters->freqResolution;
			else
				tempDiff=pconfigParameters->freqResolution - filterBandwidthList[i][j];
			if (i == 0 && j==0)
				diff = tempDiff;
			if (tempDiff <= diff) {
				diff = tempDiff;
				row = i;
				column = j;
			}
			if (diff == 0)
				break;
		}
		if (diff == 0)
			break;
	}
	scanParameters.freqResolution = filterBandwidthList[row][column];
	//Set the channel filter bandwidth
	reg = TI_CC_SPIReadReg(TI_CCxxx0_MDMCFG4);
	reg &= ~(TI_CCxxx0_MDMCFG4_CHANBW_E + TI_CCxxx0_MDMCFG4_CHANBW_M);
	reg |= (chanBwE[row][column] << 4) + (chanBwM[row][column] << 6);
	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG4, reg);
	//Initialize the variables related to the frequency registers REG2:REG1:REG0
	//Formula: f_carrier=(f_xosc/2^16)*FREQ[23:0]
	//TODO: To optimize, consider using Horner division code from SLAA329
	//Link: http://www.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=slaa329&docCategoryId=1&familyId=4
	freqRegsBase=(((UINT32)scanParameters.startFreqMhz)<<16)/fXoscMhz;
	freqRegsBase+=(((UINT32)scanParameters.startFreqKhz)<<16)/(fXoscMhz*1000);
	freqRegsStep=(((UINT32)scanParameters.freqResolution)<<16)/(fXoscMhz*1000);


	//Set the channel spacing
//	reg = TI_CC_SPIReadReg(TI_CCxxx0_MDMCFG1);
//	reg &= ~TI_CCxxx0_MDMCFG1_CHANSPC_E_MASK;
//	reg |= chanSpcE[row][column];
//	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG1, reg);
//	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG0, chanSpcM[row][column]);
	//Set the number of channels per Mhz
	//Parsing the modulation format
	//If it's a wrong or invalid value, use the first valid modulation format
	if (pconfigParameters->modFormat < sizeof(validModFormats)
			&& validModFormats[pconfigParameters->modFormat])
		scanParameters.modFormat = pconfigParameters->modFormat;
	else {
		for (i = 0; i < sizeof(validModFormats) && !validModFormats[i]; i++)
			;
		scanParameters.modFormat = i;
	}
	//Set the modulation for the current scan
	reg = TI_CC_SPIReadReg(TI_CCxxx0_MDMCFG2);
	reg &= ~TI_CCxxx0_MDMCFG2_MODFORMAT_MASK;
	reg |= modFormatMDMCFG2[scanParameters.modFormat];
	TI_CC_SPIWriteReg(TI_CCxxx0_MDMCFG2, reg);

	//Parse AGC options
	//If the AGC is disabled, we manually set
	//all the gain stages, otherwise we ignore
	//those fields
	if(pconfigParameters->activateAGC){
		scanParameters.activateAGC = TRUE;
		//Parse rssiWait
		if(pconfigParameters->rssiWait<MIN_WAIT_WITH_AGC || pconfigParameters->rssiWait>MAX_WAIT_WITH_AGC){
			//Use default: AVG_WAIT_WITHOUT_AGC
			scanParameters.rssiWait=AVG_WAIT_WITH_AGC;
		}
		else{
			scanParameters.rssiWait=pconfigParameters->rssiWait;
		}
	}
	else{
		scanParameters.activateAGC = FALSE;
		//Freeze the AGC
		reg = TI_CC_SPIReadReg(TI_CCxxx0_AGCCTRL0);
		reg &= ~TI_CCxxx0_AGCCTRL0_AGCFREEZE_MASK;
		reg |= TI_CCxxx0_AGCCTRL0_AGCFREEZE_ALL;
		TI_CC_SPIWriteReg(TI_CCxxx0_AGCCTRL0, reg);
		//Parse static gain options
		if (pconfigParameters->agcLnaGain < LNA_MIN_GAIN
				&& pconfigParameters->agcLnaGain > LNA_MAX_GAIN)
			scanParameters.agcLnaGain = pconfigParameters->agcLnaGain;
		else
			scanParameters.agcLnaGain = LNA_MAX_GAIN;
		if (pconfigParameters->agcLna2Gain > LNA2_MIN_GAIN
				&& pconfigParameters->agcLna2Gain < LNA2_MAX_GAIN)
			scanParameters.agcLna2Gain = pconfigParameters->agcLna2Gain;
		else
			scanParameters.agcLna2Gain = LNA2_MAX_GAIN;
		if (pconfigParameters->agcDvgaGain > DVGA_MIN_GAIN
				&& pconfigParameters->agcDvgaGain < DVGA_MAX_GAIN)
			scanParameters.agcDvgaGain = pconfigParameters->agcDvgaGain;
		else
			scanParameters.agcDvgaGain = DVGA_MAX_GAIN;
		//Set static gain value
		reg = scanParameters.agcDvgaGain | (scanParameters.agcLna2Gain << 3)
				| (scanParameters.agcLna2Gain << 6);
		TI_CC_SPIWriteReg(TI_CCxxx0_AGCTEST, reg);

		//Parse rssiWait
		if(pconfigParameters->rssiWait<MIN_WAIT_WITHOUT_AGC || pconfigParameters->rssiWait>MAX_WAIT_WITHOUT_AGC){
			//Use default: AVG_WAIT_WITH_AGC
			scanParameters.rssiWait=AVG_WAIT_WITH_AGC;
		}
		else{
			scanParameters.rssiWait=pconfigParameters->rssiWait;
		}
	}
	/**Finished parsing parameters**/

	//Everything OK, return pointer to the parameter structure
	return &scanParameters;
}