This is modified program from original CC1101_Transceiver. CC1101 Test succeeded STM32-F407 platform. Feature are improved little bit.
Dependencies: mbed
TI CC1101 chip is embedded along with STM32-F407 MCU.
CC1101.cpp
- Committer:
- tmav123
- Date:
- 2010-11-21
- Revision:
- 0:9df942ea84f4
- Child:
- 1:e96096a7b90b
File content as of revision 0:9df942ea84f4:
#include "CC1101.h" #define RF_0db //#define RF_10db /////////////////////////////////////////////////////////////////////////////////////// CC1101::CC1101(PinName mosi, PinName miso, PinName clk, PinName csn, PinName RDmiso): _spi(mosi, miso, clk), _csn(csn), _RDmiso(RDmiso) { _csn = 1; // Setup the spi for 8 bit data, high steady state clock, // second edge capture, with a 1MHz clock rate _spi.format(8,0); _spi.frequency(1000000); POWER_UP_RESET_CCxxx0(); Strobe(CCxxx0_SRX); } /////////////////////////////////////////////////////////////////////////////////////// RF_SETTINGS rfSettings = // 433Mhz, 9600Bauds { 0x06, // FSCTRL1 Frequency Synthesizer Control - IF:152.343Khz 0x07, // IOCFG0 GDO0 Output Pin Configuration - Packet received and CRC OK 0x00, // FSCTRL0 Frequency Synthesizer Control - Freq offset 0x10, // FREQ2 Frequency Control Word, High Byte - 433.999 Mhz 0xB1, // FREQ1 Frequency Control Word, Middle Byte 0x3B, // FREQ0 Frequency Control Word, Low Byte 0xF8, // MDMCFG4 Modem Configuration - BW: 58.035Khz 0x83, // MDMCFG3 Modem Configuration - 9595 Baud 0x13, // MDMCFG2 Modem Configuration - 30/32 sync word bits - Manchester disable - GFSK - Digital DC filter enable 0x22, // MDMCFG1 Modem Configuration - num of preamble bytes:4 - FEC disable 0xF8, // MDMCFG0 Modem Configuration - Channel spacing: 199.951Khz 0x00, // CHANNR Channel Number 0x15, // DEVIATN Modem Deviation Setting - 5.157Khz 0x56, // FREND1 Front End RX Configuration 0x10, // FREND0 Front End TX Configuration 0x18, // MCSM0 Main Radio Control State Machine Configuration - PO timeout: 64(149-155us) - Auto calibrate from idle to rx/tx 0x16, // FOCCFG Frequency Offset Compensation Configuration 0x6C, // BSCFG Bit Synchronization Configuration 0x03, // AGCCTRL2 AGC Control - target amplitude: 33dB - Maximum possible LNA + LNA 2 gain - All gain settings can be used 0x40, // AGCCTRL1 AGC Control - LNA gain decreased first 0x91, // AGCCTRL0 AGC Control - Medium hysterisis - Filter Samples: 16 - Normal AGC operation 0xE9, // FSCAL3 Frequency Synthesizer Calibration 0x2A, // FSCAL2 Frequency Synthesizer Calibration 0x00, // FSCAL1 Frequency Synthesizer Calibration 0x1F, // FSCAL0 Frequency Synthesizer Calibration 0x59, // FSTEST Frequency Synthesizer Calibration Control 0x88, // TEST2 Various Test Settings 0x31, // TEST1 Various Test Settings 0x09, // TEST0 Various Test Settings 0x07, // FIFOTHR RX FIFO and TX FIFO Thresholds - Bytes in TX FIFO:33 - Bytes in RX FIFO:32 0x06, // IOCFG2 GDO2 Output Pin Configuration - Sync word received/sent - end of packet 0x04, // PKTCTRL1 Packet Automation Control - No address check - Automatic flush of RX FIFO is disable - sync word is always accepted 0x05, // PKTCTRL0 Packet Automation Control - whitening is off - RX/TX data normal mode - CRC calculation in TX and CRC check in RX - Variable packet length 0x00, // ADDR Device Address 0xFF, // PKTLEN Packet Length 0x3F, // MCSM1 Main Radio Control State Machine Configuration }; #ifdef RF_0db // PATABLE (0 dBm output power) char paTable[] = {0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif #ifdef RF_10db // PATABLE (10 dBm output power) char paTable[] = {0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif /////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////// // Macro to reset the CCxxx0 and wait for it to be ready void CC1101::RESET_CCxxx0(void) { // while (_RDmiso); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(CCxxx0_SRES); wait(0.000002); _csn = 1; } /////////////////////////////////////////////////////////////////////////////////////// // Macro to reset the CCxxx0 after power_on and wait for it to be ready // IMPORTANT NOTICE: // The file Wait.c must be included if this macro shall be used // The file is located under: ..\Lib\Chipcon\Hal\CCxx00 // // min 40 us // <-----------------------> // CSn |--| |--------------------| |----------- // | | | | | // -- ---------- // // MISO |--------------- // - - - - - - - - - - - - - - - -| | // -- // Unknown / don't care // // MOSI - - - - - - - - - - - - - - - ---------- - - - - - // | SRES | // - - - - - - - - - - - - - - - ---------- - - - - - // void CC1101::POWER_UP_RESET_CCxxx0(void) { _csn = 1; wait(1e-6); _csn = 0; wait(1e-6); _csn = 1; wait(41e-6); RESET_CCxxx0(); } /////////////////////////////////////////////////////////////////////////////////////// // void Strobe(unsigned char strobe) // // DESCRIPTION: // Function for writing a strobe command to the CCxxx0 // // ARGUMENTS: // unsigned char strobe // Strobe command /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::Strobe(unsigned char strobe) { unsigned char x; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); x = _spi.write(strobe); wait(0.000002); _csn = 1; return x; }// Strobe /////////////////////////////////////////////////////////////////////////////////////// // unsigned char ReadStatus(unsigned char addr) // // DESCRIPTION: // This function reads a CCxxx0 status register. // // ARGUMENTS: // unsigned char addr // Address of the CCxxx0 status register to be accessed. // // RETURN VALUE: // unsigned char // Value of the accessed CCxxx0 status register. /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::ReadStatus(unsigned char addr) { unsigned char x; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(addr | READ_BURST); x = _spi.write(0); wait(0.000002); _csn = 1; return x; }// ReadStatus /////////////////////////////////////////////////////////////////////////////////////// // void WriteRfSettings(RF_SETTINGS *pRfSettings) // // DESCRIPTION: // This function is used to configure the CCxxx0 based on a given rf setting // // ARGUMENTS: // RF_SETTINGS *pRfSettings // Pointer to a struct containing rf register settings /////////////////////////////////////////////////////////////////////////////////////// void CC1101::WriteRfSettings(RF_SETTINGS *pRfSettings) { // Write register settings WriteReg(CCxxx0_FSCTRL1, pRfSettings->FSCTRL1); WriteReg(CCxxx0_FSCTRL0, pRfSettings->FSCTRL0); WriteReg(CCxxx0_FREQ2, pRfSettings->FREQ2); WriteReg(CCxxx0_FREQ1, pRfSettings->FREQ1); WriteReg(CCxxx0_FREQ0, pRfSettings->FREQ0); WriteReg(CCxxx0_MDMCFG4, pRfSettings->MDMCFG4); WriteReg(CCxxx0_MDMCFG3, pRfSettings->MDMCFG3); WriteReg(CCxxx0_MDMCFG2, pRfSettings->MDMCFG2); WriteReg(CCxxx0_MDMCFG1, pRfSettings->MDMCFG1); WriteReg(CCxxx0_MDMCFG0, pRfSettings->MDMCFG0); WriteReg(CCxxx0_CHANNR, pRfSettings->CHANNR); WriteReg(CCxxx0_DEVIATN, pRfSettings->DEVIATN); WriteReg(CCxxx0_FREND1, pRfSettings->FREND1); WriteReg(CCxxx0_FREND0, pRfSettings->FREND0); WriteReg(CCxxx0_MCSM0 , pRfSettings->MCSM0 ); WriteReg(CCxxx0_FOCCFG, pRfSettings->FOCCFG); WriteReg(CCxxx0_BSCFG, pRfSettings->BSCFG); WriteReg(CCxxx0_AGCCTRL2, pRfSettings->AGCCTRL2); WriteReg(CCxxx0_AGCCTRL1, pRfSettings->AGCCTRL1); WriteReg(CCxxx0_AGCCTRL0, pRfSettings->AGCCTRL0); WriteReg(CCxxx0_FSCAL3, pRfSettings->FSCAL3); WriteReg(CCxxx0_FSCAL2, pRfSettings->FSCAL2); WriteReg(CCxxx0_FSCAL1, pRfSettings->FSCAL1); WriteReg(CCxxx0_FSCAL0, pRfSettings->FSCAL0); WriteReg(CCxxx0_FSTEST, pRfSettings->FSTEST); WriteReg(CCxxx0_TEST2, pRfSettings->TEST2); WriteReg(CCxxx0_TEST1, pRfSettings->TEST1); WriteReg(CCxxx0_TEST0, pRfSettings->TEST0); WriteReg(CCxxx0_FIFOTHR, pRfSettings->FIFOTHR); WriteReg(CCxxx0_IOCFG2, pRfSettings->IOCFG2); WriteReg(CCxxx0_IOCFG0, pRfSettings->IOCFG0); WriteReg(CCxxx0_PKTCTRL1, pRfSettings->PKTCTRL1); WriteReg(CCxxx0_PKTCTRL0, pRfSettings->PKTCTRL0); WriteReg(CCxxx0_ADDR, pRfSettings->ADDR); WriteReg(CCxxx0_PKTLEN, pRfSettings->PKTLEN); WriteReg(CCxxx0_MCSM1 , pRfSettings->MCSM1 ); RXMode(); }// WriteRfSettings /////////////////////////////////////////////////////////////////////////////////////// void CC1101::init(void) { WriteRfSettings(&rfSettings); WriteReg(CCxxx0_PATABLE, paTable[0]); } /////////////////////////////////////////////////////////////////////////////////////// // unsigned char ReadReg(unsigned char addr) // // DESCRIPTION: // This function gets the value of a single specified CCxxx0 register. // // ARGUMENTS: // unsigned char addr // Address of the CCxxx0 register to be accessed. // // RETURN VALUE: // unsigned char // Value of the accessed CCxxx0 register. /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::ReadReg(unsigned char addr) { unsigned char x; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(addr | READ_SINGLE); x = _spi.write(0); wait(0.000002); _csn = 1; return x; }// ReadReg /////////////////////////////////////////////////////////////////////////////////////// // void ReadBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count) // // DESCRIPTION: // This function reads multiple CCxxx0 register, using SPI burst access. // // ARGUMENTS: // unsigned char addr // Address of the first CCxxx0 register to be accessed. // unsigned char *buffer // Pointer to a byte array which stores the values read from a // corresponding range of CCxxx0 registers. // unsigned char count // Number of bytes to be read from the subsequent CCxxx0 registers. /////////////////////////////////////////////////////////////////////////////////////// void CC1101::ReadBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count) { unsigned char i; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(addr | READ_BURST); for (i = 0; i < count; i++) { buffer[i] = _spi.write(0); } wait(0.000002); _csn = 1; }// ReadBurstReg /////////////////////////////////////////////////////////////////////////////////////// // void WriteReg(unsigned char addr, unsigned char value) // // DESCRIPTION: // Function for writing to a single CCxxx0 register // // ARGUMENTS: // unsigned char addr // Address of a specific CCxxx0 register to accessed. // unsigned char value // Value to be written to the specified CCxxx0 register. /////////////////////////////////////////////////////////////////////////////////////// void CC1101::WriteReg(unsigned char addr, unsigned char value) { wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(addr); _spi.write(value); wait(0.000002); _csn = 1; }// WriteReg /////////////////////////////////////////////////////////////////////////////////////// // void WriteBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count) // // DESCRIPTION: // This function writes to multiple CCxxx0 register, using SPI burst access. // // ARGUMENTS: // unsigned char addr // Address of the first CCxxx0 register to be accessed. // unsigned char *buffer // Array of bytes to be written into a corresponding range of // CCxx00 registers, starting by the address specified in _addr_. // unsigned char count // Number of bytes to be written to the subsequent CCxxx0 registers. /////////////////////////////////////////////////////////////////////////////////////// void CC1101::WriteBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count) { unsigned char i; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); _spi.write(addr | WRITE_BURST); for (i = 0; i < count; i++) { _spi.write(buffer[i]); } wait(0.000002); _csn = 1; }// WriteBurstReg /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::RdRSSI(void) { unsigned char crssi; if (rssi >= 128) { crssi = 255 - rssi; crssi /= 2; crssi += 74; } else { crssi = rssi/2; crssi += 74; } return crssi; } /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::RdLQI(void) { unsigned char clqi; clqi = 0x3F - (lqi & 0x3F); return clqi; } /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::RxFifoEmpty(void) { unsigned char RxFifoStatus; Strobe(CCxxx0_SRX); RxFifoStatus = ReadStatus(CCxxx0_RXBYTES); if (RxFifoStatus & 0x80) // check for RXFIFO overflow { // Make sure that the radio is in IDLE state before flushing the FIFO // (Unless RXOFF_MODE has been changed, the radio should be in IDLE state at this point) Strobe(CCxxx0_SIDLE); // Flush RX FIFO Strobe(CCxxx0_SFRX); } if (RxFifoStatus & ~0x80) { return 0; } else return 1; } /////////////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------------------------------------------------- // BOOL ReceivePacket(unsigned char *rxBuffer, unsigned char *length) // // DESCRIPTION: // This function can be used to receive a packet of variable packet length (first byte in the packet // must be the length byte). The packet length should not exceed the RX FIFO size. // // ARGUMENTS: // unsigned char *rxBuffer // Pointer to the buffer where the incoming data should be stored // unsigned 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: // BOOL // 1: CRC OK // 0: CRC NOT OK (or no packet was put in the RX FIFO due to filtering) /////////////////////////////////////////////////////////////////////////////////////// int CC1101::ReceivePacket(unsigned char *rxBuffer, unsigned char *length) { unsigned char status[2]; unsigned char packetLength; packetLength = ReadStatus(CCxxx0_RXBYTES); if (packetLength & BYTES_IN_RXFIFO) { // Read length byte packetLength = ReadReg(CCxxx0_RXFIFO); // Read data from RX FIFO and store in rxBuffer if (packetLength <= *length) { ReadBurstReg(CCxxx0_RXFIFO, rxBuffer, packetLength); *length = packetLength; // Read the 2 appended status bytes (status[0] = RSSI, status[1] = LQI) ReadBurstReg(CCxxx0_RXFIFO, status, 2); rssi = status[RSSI]; lqi = status[LQI]; // MSB of LQI is the CRC_OK bit // return (status[LQI] & CRC_OK); if(status[LQI] & CRC_OK) { return 1; } } else { *length = packetLength; // Make sure that the radio is in IDLE state before flushing the FIFO // (Unless RXOFF_MODE has been changed, the radio should be in IDLE state at this point) Strobe(CCxxx0_SIDLE); // Flush RX FIFO Strobe(CCxxx0_SFRX); return 0; } } else return 0; return 0; }// halRfReceivePacket /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::TxFifoEmpty(void) { unsigned char TxFifoStatus; Strobe(CCxxx0_STX); TxFifoStatus = ReadStatus(CCxxx0_TXBYTES); if (TxFifoStatus & 0x80) // check for TXFIFO underflow { // Make sure that the radio is in IDLE state before flushing the FIFO Strobe(CCxxx0_SIDLE); // Flush TX FIFO Strobe(CCxxx0_SFTX); } if (TxFifoStatus & ~0x80) { return 0; } else return 1; } /////////////////////////////////////////////////////////////////////////////////////// // void halRfSendPacket(unsigned char *txBuffer, unsigned char size) // // DESCRIPTION: // This function can be used to transmit a packet with packet length up to 63 bytes. // // ARGUMENTS: // unsigned char *txBuffer // Pointer to a buffer containing the data that are going to be transmitted // // unsigned char size // The size of the txBuffer /////////////////////////////////////////////////////////////////////////////////////// void CC1101::SendPacket(unsigned char *txBuffer, unsigned char size) { unsigned char i; for (i = size; i > 0; i--) txBuffer[i] = txBuffer[i-1]; txBuffer[0] = size; WriteBurstReg(CCxxx0_TXFIFO, txBuffer, size+1); Strobe(CCxxx0_SIDLE); Strobe(CCxxx0_STX); }// halRfSendPacket /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::ReadChipStatusTX(void) { unsigned char x; x = Strobe(CCxxx0_SNOP); return x; } /////////////////////////////////////////////////////////////////////////////////////// unsigned char CC1101::ReadChipStatusRX(void) { unsigned char x; wait(0.000005); _csn = 0; wait(0.000002); while (_RDmiso); x = _spi.write(CCxxx0_PARTNUM | READ_BURST); wait(0.000002); _csn = 1; return x; } /////////////////////////////////////////////////////////////////////////////////////// void CC1101::FlushRX(void) { // Make sure that the radio is in IDLE state before flushing the FIFO Strobe(CCxxx0_SIDLE); // Flush RX FIFO Strobe(CCxxx0_SFRX); } /////////////////////////////////////////////////////////////////////////////////////// void CC1101::FlushTX(void) { // Make sure that the radio is in IDLE state before flushing the FIFO Strobe(CCxxx0_SIDLE); // Flush TX FIFO Strobe(CCxxx0_SFTX); } /////////////////////////////////////////////////////////////////////////////////////// void CC1101::RXMode(void) { Strobe(CCxxx0_SIDLE); Strobe(CCxxx0_SRX); } ///////////////////////////////////////////////////////////////////////////////////////