
TI CC1101 Transceiver
Revision 0:9df942ea84f4, committed 2010-11-21
- Comitter:
- tmav123
- Date:
- Sun Nov 21 11:37:56 2010 +0000
- Commit message:
- initial revision
Changed in this revision
diff -r 000000000000 -r 9df942ea84f4 CC1101.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CC1101.cpp Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,539 @@ + +#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); +} +///////////////////////////////////////////////////////////////////////////////////////
diff -r 000000000000 -r 9df942ea84f4 CC1101.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CC1101.h Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,356 @@ +/** + * @author Athanassios Mavrogeorgiadis + * @author TI CC1101 library developed by Athanassios Mavrogeorgiadis (tmav Electronics) as template based on TI C8051 SOURCE CODE swrc021f + * @section LICENSE + * + * Copyright (c) 2010 ARM Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * @section DESCRIPTION + * + * CC1101 Low-Power Sub-1 GHz RF Transceiver CC1101. + * + * Datasheet: + * + * http://focus.ti.com/lit/ds/swrs061f/swrs061f.pdf + */ + +#ifndef MBED_CC1101_H +#define MBED_CC1101_H + +/** + * Includes + */ +#include "mbed.h" + +/** + * Defines + */ +/////////////////////////////////////////////////////////////////////////////////////// +//------------------------------------------------------------------------------------------------------ +// CC2500/CC1100 STROBE, CONTROL AND STATUS REGSITER +#define CCxxx0_IOCFG2 0x00 // GDO2 output pin configuration +#define CCxxx0_IOCFG1 0x01 // GDO1 output pin configuration +#define CCxxx0_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds +#define CCxxx0_SYNC1 0x04 // Sync word, high byte +#define CCxxx0_SYNC0 0x05 // Sync word, low byte +#define CCxxx0_IOCFG0 0x02 // GDO0 output pin configuration +#define CCxxx0_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds +#define CCxxx0_SYNC1 0x04 // Sync word, high byte +#define CCxxx0_SYNC0 0x05 // Sync word, low byte +#define CCxxx0_PKTLEN 0x06 // Packet length +#define CCxxx0_PKTCTRL1 0x07 // Packet automation control +#define CCxxx0_PKTCTRL0 0x08 // Packet automation control +#define CCxxx0_ADDR 0x09 // Device address +#define CCxxx0_CHANNR 0x0A // Channel number +#define CCxxx0_FSCTRL1 0x0B // Frequency synthesizer control +#define CCxxx0_FSCTRL0 0x0C // Frequency synthesizer control +#define CCxxx0_FREQ2 0x0D // Frequency control word, high byte +#define CCxxx0_FREQ1 0x0E // Frequency control word, middle byte +#define CCxxx0_FREQ0 0x0F // Frequency control word, low byte +#define CCxxx0_MDMCFG4 0x10 // Modem configuration +#define CCxxx0_MDMCFG3 0x11 // Modem configuration +#define CCxxx0_MDMCFG2 0x12 // Modem configuration +#define CCxxx0_MDMCFG1 0x13 // Modem configuration +#define CCxxx0_MDMCFG0 0x14 // Modem configuration +#define CCxxx0_DEVIATN 0x15 // Modem deviation setting +#define CCxxx0_MCSM2 0x16 // Main Radio Control State Machine configuration +#define CCxxx0_MCSM1 0x17 // Main Radio Control State Machine configuration +#define CCxxx0_MCSM0 0x18 // Main Radio Control State Machine configuration +#define CCxxx0_FOCCFG 0x19 // Frequency Offset Compensation configuration +#define CCxxx0_BSCFG 0x1A // Bit Synchronization configuration +#define CCxxx0_AGCCTRL2 0x1B // AGC control +#define CCxxx0_AGCCTRL1 0x1C // AGC control +#define CCxxx0_AGCCTRL0 0x1D // AGC control +#define CCxxx0_WOREVT1 0x1E // High byte Event 0 timeout +#define CCxxx0_WOREVT0 0x1F // Low byte Event 0 timeout +#define CCxxx0_WORCTRL 0x20 // Wake On Radio control +#define CCxxx0_FREND1 0x21 // Front end RX configuration +#define CCxxx0_FREND0 0x22 // Front end TX configuration +#define CCxxx0_FSCAL3 0x23 // Frequency synthesizer calibration +#define CCxxx0_FSCAL2 0x24 // Frequency synthesizer calibration +#define CCxxx0_FSCAL1 0x25 // Frequency synthesizer calibration +#define CCxxx0_FSCAL0 0x26 // Frequency synthesizer calibration +#define CCxxx0_RCCTRL1 0x27 // RC oscillator configuration +#define CCxxx0_RCCTRL0 0x28 // RC oscillator configuration +#define CCxxx0_FSTEST 0x29 // Frequency synthesizer calibration control +#define CCxxx0_PTEST 0x2A // Production test +#define CCxxx0_AGCTEST 0x2B // AGC test +#define CCxxx0_TEST2 0x2C // Various test settings +#define CCxxx0_TEST1 0x2D // Various test settings +#define CCxxx0_TEST0 0x2E // Various test settings + +// Strobe commands +#define CCxxx0_SRES 0x30 // Reset chip. +#define CCxxx0_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + // If in RX/TX: Go to a wait state where only the synthesizer is + // running (for quick RX / TX turnaround). +#define CCxxx0_SXOFF 0x32 // Turn off crystal oscillator. +#define CCxxx0_SCAL 0x33 // Calibrate frequency synthesizer and turn it off + // (enables quick start). +#define CCxxx0_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and + // MCSM0.FS_AUTOCAL=1. +#define CCxxx0_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if + // MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: + // Only go to TX if channel is clear. +#define CCxxx0_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit + // Wake-On-Radio mode if applicable. +#define CCxxx0_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer +#define CCxxx0_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio) +#define CCxxx0_SPWD 0x39 // Enter power down mode when CSn goes high. +#define CCxxx0_SFRX 0x3A // Flush the RX FIFO buffer. +#define CCxxx0_SFTX 0x3B // Flush the TX FIFO buffer. +#define CCxxx0_SWORRST 0x3C // Reset real time clock. +#define CCxxx0_SNOP 0x3D // No operation. May be used to pad strobe commands to two + // bytes for simpler software. + +#define CCxxx0_PARTNUM 0x30 +#define CCxxx0_VERSION 0x31 +#define CCxxx0_FREQEST 0x32 +#define CCxxx0_LQI 0x33 +#define CCxxx0_RSSI 0x34 +#define CCxxx0_MARCSTATE 0x35 +#define CCxxx0_WORTIME1 0x36 +#define CCxxx0_WORTIME0 0x37 +#define CCxxx0_PKTSTATUS 0x38 +#define CCxxx0_VCO_VC_DAC 0x39 +#define CCxxx0_TXBYTES 0x3A +#define CCxxx0_RXBYTES 0x3B +#define CCxxx0_RCCTRL1_STATUS 0x3C +#define CCxxx0_RCCTRL0_STATUS 0x3D + +#define CCxxx0_PATABLE 0x3E +#define CCxxx0_TXFIFO 0x3F +#define CCxxx0_RXFIFO 0x3F +/////////////////////////////////////////////////////////////////////////////////////// +// RF_SETTINGS is a data structure which contains all relevant CCxxx0 registers +typedef struct S_RF_SETTINGS +{ + unsigned char FSCTRL1; // Frequency synthesizer control. + unsigned char IOCFG0; // GDO0 output pin configuration + unsigned char FSCTRL0; // Frequency synthesizer control. + unsigned char FREQ2; // Frequency control word, high byte. + unsigned char FREQ1; // Frequency control word, middle byte. + unsigned char FREQ0; // Frequency control word, low byte. + unsigned char MDMCFG4; // Modem configuration. + unsigned char MDMCFG3; // Modem configuration. + unsigned char MDMCFG2; // Modem configuration. + unsigned char MDMCFG1; // Modem configuration. + unsigned char MDMCFG0; // Modem configuration. + unsigned char CHANNR; // Channel number. + unsigned char DEVIATN; // Modem deviation setting (when FSK modulation is enabled). + unsigned char FREND1; // Front end RX configuration. + unsigned char FREND0; // Front end RX configuration. + unsigned char MCSM0; // Main Radio Control State Machine configuration. + unsigned char FOCCFG; // Frequency Offset Compensation Configuration. + unsigned char BSCFG; // Bit synchronization Configuration. + unsigned char AGCCTRL2; // AGC control. + unsigned char AGCCTRL1; // AGC control. + unsigned char AGCCTRL0; // AGC control. + unsigned char FSCAL3; // Frequency synthesizer calibration. + unsigned char FSCAL2; // Frequency synthesizer calibration. + unsigned char FSCAL1; // Frequency synthesizer calibration. + unsigned char FSCAL0; // Frequency synthesizer calibration. + unsigned char FSTEST; // Frequency synthesizer calibration control + unsigned char TEST2; // Various test settings. + unsigned char TEST1; // Various test settings. + unsigned char TEST0; // Various test settings. + unsigned char FIFOTHR; // RXFIFO and TXFIFO thresholds. + unsigned char IOCFG2; // GDO2 output pin configuration + unsigned char PKTCTRL1; // Packet automation control. + unsigned char PKTCTRL0; // Packet automation control. + unsigned char ADDR; // Device address. + unsigned char PKTLEN; // Packet length. + unsigned char MCSM1; // Main Radio Control State Machine configuration. +} RF_SETTINGS; +/////////////////////////////////////////////////////////////////////////////////////// +// Definitions to support burst/single access: +#define WRITE_BURST 0x40 +#define READ_SINGLE 0x80 +#define READ_BURST 0xC0 +/////////////////////////////////////////////////////////////////////////////////////// +#define CRC_OK 0x80 +#define RSSI 0 +#define LQI 1 +#define BYTES_IN_RXFIFO 0x7F +/////////////////////////////////////////////////////////////////////////////////////// +// Definitions for chip status +#define CHIP_RDY 0x80 +#define CHIP_STATE_MASK 0x70 +#define CHIP_STATE_IDLE 0x00 +#define CHIP_STATE_RX 0x10 +#define CHIP_STATE_TX 0x20 +#define CHIP_STATE_FSTON 0x30 +#define CHIP_STATE_CALIBRATE 0x40 +#define CHIP_STATE_SETTLING 0x50 +#define CHIP_STATE_RXFIFO_OVERFLOW 0x60 +#define CHIP_STATE_TXFIFO_UNDERFLOW 0x70 +#define FIFO_BYTES_MASK 0x0F +/////////////////////////////////////////////////////////////////////////////////////// +/** + * CC1101 Low-Power Sub-1 GHz RF Transceiver . + */ + +class CC1101 +{ +public: + /** + * Constructor. + * + * @param mosi mbed pin to use for MOSI line of SPI interface. + * @param miso mbed pin to use for MISO line of SPI interface. + * @param clk mbed pin to use for SCK line of SPI interface. + * @param csn mbed pin to use for not chip select line of SPI interface. + * @param RDmiso mbed pin connected to SPI MISO pin for CC1101 RDY read. + */ + CC1101(PinName mosi, PinName miso, PinName clk, PinName csn, PinName RDmiso); + + /** + * Initialize CC1101 parameters. + */ + void init(void); + + /** + * This function gets the value of a single specified CCxxx0 register. + * + * @param addr Value of the accessed CCxxx0 register + * @return Value of the accessed CCxxx0 register + */ + unsigned char ReadReg(unsigned char addr); + + /** + * This function reads multiple CCxxx0 register, using SPI burst access. + * + * @param addr Value of the accessed CCxxx0 register + * @param *buffer Pointer to a byte array which stores the values read from a + * corresponding range of CCxxx0 registers. + * @param count Number of bytes to be read from the subsequent CCxxx0 registers. + */ + void ReadBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count); + + /** + * Function for writing to a single CCxxx0 register + * + * @param addr Address of the first CCxxx0 register to be accessed. + * @param value Value to be written to the specified CCxxx0 register. + */ + void WriteReg(unsigned char addr, unsigned char value); + + /** + * This function writes to multiple CCxxx0 register, using SPI burst access. + * + * @param addr Address of the first CCxxx0 register to be accessed. + * @param *buffer Array of bytes to be written into a corresponding range of + * CCxx00 registers, starting by the address specified in _addr_. + * @param count Number of bytes to be written to the subsequent CCxxx0 registers. + */ + void WriteBurstReg(unsigned char addr, unsigned char *buffer, unsigned char count); + + /** + * This function can be used to transmit a packet with packet length up to 63 bytes. + * + * @param *txBuffer Pointer to a buffer containing the data that are going to be transmitted + * @param size The size of the txBuffer + */ + void SendPacket(unsigned char *txBuffer, unsigned char size); + + /** + * This function check if the TX FIFO is empty + * + * @return Return value is 1 if the TX FIFO buffer is empty or else 0 + */ + unsigned char TxFifoEmpty(void); + + /** + * 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. + * + * @param *rxBuffer Pointer to the buffer where the incoming data should be stored + * @param *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 Return value is 1 if CRC OK or else 0 if CRC NOT OK (or no packet was put in the RX FIFO due to filtering) + */ + int ReceivePacket(unsigned char *rxBuffer, unsigned char *length); + + /** + * This function check if the RX FIFO is empty + * + * @return Return value is 1 if the RX FIFO buffer is empty or else 0 + */ + unsigned char RxFifoEmpty(void); + + /** + * This function returns the Chip Status RX register + * + * @return Return the Chip Status RX register + */ + unsigned char ReadChipStatusRX(void); + + /** + * This function returns the Chip Status TX register + * + * @return Return the Chip Status TX register + */ + unsigned char ReadChipStatusTX(void); + + /** + * This function returns the RSSI value based from the last packet received + * + * @return Return the RSSI value. + */ + unsigned char RdRSSI(void); + + /** + * This function returns the LQI value based from the last packet received + * + * @return Return the LQI value. + */ + unsigned char RdLQI(void); + + /** + * This function flushes the RX FIFO buffer. + */ + void FlushRX(void); + + /** + * This function flushes the TX FIFO buffer. + */ + void FlushTX(void); + + /** + * This function change the state of CC1101 to RX mode. + */ + void RXMode(void); + +protected: + void RESET_CCxxx0(void); + void POWER_UP_RESET_CCxxx0(void); + unsigned char ReadStatus(unsigned char addr); + unsigned char Strobe(unsigned char strobe); + void WriteRfSettings(RF_SETTINGS *pRfSettings); + + SPI _spi; + DigitalOut _csn; + DigitalIn _RDmiso; + unsigned char rssi; + unsigned char lqi; +}; +/////////////////////////////////////////////////////////////////////////////////////// +#endif \ No newline at end of file
diff -r 000000000000 -r 9df942ea84f4 RingBuffer.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuffer.cpp Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,86 @@ +/* + * mbed library for RingBuffer + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#include "RingBuffer.h" + +RingBuffer::RingBuffer (int p_size) { + size = p_size + 1; + buf = new char[size]; + addr_w = 0; + addr_r = 0; +} +/* +RingBuffer::~RingBuffer () { + delete [] buf; +} +*/ +int RingBuffer::_putc (int dat) { + int next; + + next = (addr_w + 1) % size; + if (next == addr_r) { + return -1; + } + buf[addr_w] = dat; + addr_w = next; + return dat; +} + +int RingBuffer::put (char *dat, int len) { + int next, i; + + + for (i = 0; i < len; i ++) { + next = (addr_w + 1) % size; + if (next == addr_r) { + break; + } + buf[addr_w] = dat[i]; + addr_w = next; + } + return i; +} + +int RingBuffer::_getc (void) +{ + char dat; + if (addr_r == addr_w) { + return 0; + } + dat = buf[addr_r]; + addr_r = (addr_r + 1) % size; + return dat; +} + +int RingBuffer::get (char *dat, int len) { + int i; + + for (i = 0; i < len; i ++) { + if (addr_r == addr_w) { + break; + } + dat[i] = buf[addr_r]; + addr_r = (addr_r + 1) % size; + } + return i; +} + +int RingBuffer::available () { + if (addr_w < addr_r) { + return addr_r - addr_w - 1; + } else { + return (size - addr_w) + addr_r - 1; + } +} + +int RingBuffer::use () { + return size - available() - 1; +} + +void RingBuffer::clear () { + addr_w = 0; + addr_r = 0; +}
diff -r 000000000000 -r 9df942ea84f4 RingBuffer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/RingBuffer.h Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,39 @@ +/* + * mbed library for RingBuffer + * Copyright (c) 2010 Hiroshi Suga + * Released under the MIT License: http://mbed.org/license/mit + */ + +#ifndef RingBuffer_H +#define RingBuffer_H + +#include "mbed.h" + +class RingBuffer : public Stream { +public: + RingBuffer (int p_size); +// ~RingBuffer (); + +#if DOXYGEN_ONLY + int putc(int c); + int printf(const char* format, ...); +#endif +// int putc (char); + int put (char *, int); + char get (); + int get (char *, int); + void clear (); + int available (); + int use (); + +private: + // Stream implementation functions + virtual int _putc(int value); + virtual int _getc(); + + char *buf; + int size; + int addr_w, addr_r; +}; + +#endif
diff -r 000000000000 -r 9df942ea84f4 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,98 @@ +#include "mbed.h" +#include "CC1101.h" +#include "RingBuffer.h" + +/////////////////////////////////////////////////// +Ticker timer; +CC1101 cc1101(p5, p6, p7, p8, p10); +DigitalIn gdo0(p9); // pin connected to gdo0 pin of CC1101 for checking that received a new packet + +DigitalOut led1(LED1); // timer blink led +DigitalOut led2(LED2); // RX led +DigitalOut led3(LED3); // TX led +Serial pc(USBTX, USBRX); // tx, rx +RingBuffer pcRX(512); // ring buffer for the pc RX data +RingBuffer pcTX(512); // ring buffer for the pc TX data +Timeout pcRXtimeout; +Timeout led2timeout; +Timeout led3timeout; +unsigned char buffer[128]; +/////////////////////////////////////////////////// +void led2timeout_func() +{ + led2 = 0; + led2timeout.detach(); +} +/////////////////////////////////////////////////// +void led3timeout_func() +{ + led3 = 0; + led3timeout.detach(); +} +/////////////////////////////////////////////////// +void pcRXtimeout_func() // function for transmiting the RF packets - empty the pcRX ring buffer +{ + unsigned char txlength; + + txlength = 0; + while(pcRX.use() > 0) + { + led2 = 1; + buffer[txlength] = pcRX.getc(); + txlength++; + led2timeout.attach(&led2timeout_func, 0.050); // for switch off the led + } + if (txlength) + cc1101.SendPacket(buffer, txlength); // tx packet + + pcRXtimeout.detach(); +} +/////////////////////////////////////////////////// +void timer_func() // check the status of the CC1101 every 100ms +{ + unsigned char chip_status_rx, chip_status_tx; + + led1 = !led1; + chip_status_rx = cc1101.ReadChipStatusRX(); // check the rx status + if ((chip_status_rx & CHIP_STATE_MASK) == CHIP_STATE_RXFIFO_OVERFLOW) // if rx overflow flush the rx fifo + cc1101.FlushRX(); + if ((chip_status_rx & CHIP_STATE_MASK) == CHIP_STATE_IDLE) // if state is idle go to rx state again + cc1101.RXMode(); + chip_status_tx = cc1101.ReadChipStatusTX(); // check the tx sttus + if ((chip_status_tx & CHIP_STATE_MASK) == CHIP_STATE_TXFIFO_UNDERFLOW) // if tx underflow flush the tx fifo + cc1101.FlushTX(); +} +/////////////////////////////////////////////////// +int main() +{ + unsigned char rxlength, i; + + pcRX.clear(); + pcTX.clear(); + cc1101.init(); + timer.attach(&timer_func, 0.1); + while(1) + { + if(gdo0) // rx finished and CRC OK read the new packet + { + rxlength = sizeof(buffer); + if (cc1101.ReceivePacket(buffer, &rxlength) == 1) // read the rx packet + { + led3 = 1; + for (i = 0; i < rxlength; i++) + pcTX.putc(buffer[i]); // store the packet to the pcTX ring buffer + led3timeout.attach(&led3timeout_func, 0.050); // for switch off the led + } + } + if (pcTX.use() > 0) // check if we have data to transmit to pc + pc.putc(pcTX.getc()); // get the data from the ring buffer and transmit it to the pc + if (pc.readable()) // check if we received new data from the pc + { + pcRX.putc(pc.getc()); // put the data to the pcRX buffer and wait until 20ms passed till the last byte before tx the packet in RF + pcRXtimeout.attach(&pcRXtimeout_func, 0.020); + } + if (pcRX.use() > 20) // if more than 20 bytes received then tx the packet in RF + pcRXtimeout_func(); + } +} +///////////////////////////////////////////////////
diff -r 000000000000 -r 9df942ea84f4 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Nov 21 11:37:56 2010 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e