This is an old revision of the document!


Programming CC1200

The CC1200 wireless transceiver is connected via the “Serial Peripheral Interface (SPI)” to the Beaglebone Black. Therefore, controlling the CC1200 means sending and receiving data from the SPI. The communication over the SPI is already implemented and the code can be accessed by including the file SPIv1.h. The include-file can be found in the directory /usr/local/include and the corresponding library libspi.so can be found in directory /usr/local/lib.

Controlling the SPI

int spi_init(void)
Before accessing the SPI, the function spi_init must be called. spi_init initializes the SPI. On success, the function will return true.

void spi_shutdown(void)
The function spi_shutdown does the opposite of function spi_init and disables the SPI. Therefore, for every call of function spi_init a corresponding call of function spi_shutdown must be called.

Writing and Reading CC1200 Registers

The functions cc1200_reg_write and cc1200_reg_read are provided to access the registers of the CC1200. You can see the registers in SmartRF Studio in the register view (look at Expert Mode Window). Each register has an address. The register names and its addresses can be found at page 11 to page 13 in the User’s Guide of the CC1200. The description and the structure of each register can be found at page 80ff.

It should be pointed out, that there are two types of registers: (basic) registers and extended registers. The basic registers start at address 0x00 and the extended registers start at address 0x2F. So every time you like to access an extended register, The value 0x2F00 needs ta add to the extended register address. E.g. the address of the extended register FREQ1 (see table 5) in the “User’s Guide” is 0x2F0D.

Writing or reading to/from the address '0x3F' will access the internal FIFO's of the CC1200. Writing will push new data to the transmission FIFO and reading will pop data drop the receive FIFO (a more extended explanation will be given later).

int cc1200_reg_write(int adr, int val)
With the function cc1200_reg_write a single register of the CC1200 will be written. The parameter adr must contain the register address and parameter val must contain the register value. On return, the function will provide the written value.

int cc1200_reg_read(int adr, int *val)
Function cc1200_reg_read will read the content of a single register. Parameter adr must contain the register address. The content of the register will be stored in a variable given by parameter val. In addition the return value will provide also the register value.

Controlling CC1200

Switching on the CC1200 will bring the transmitter into idle state. In idle state, only writing and reading the registers are allowed. Bringing the CC1200 in another state (e.g. receiving) a so called command strobe must be given. To issue a command strobe the function cc1200_cmd will be used.

CC1200 Commands

For possible commands #define statements are provided:

/* command strobes */
#define SRES     0x30 /**< CC1200 in den Ausgangszustand setzen (Chip reset). */
#define SFSTXON  0x31 /**< Schalte den Frequenzsynthesizer ein und kalibriere ihn. */
#define SXOFF    0x32 /**< Gehe in den XOFF Zustand. */
#define SCAL     0x33 /**< Kalibriere Frequenzsynthesizer und schalte ihn aus. */
#define SRX      0x34 /**< Kalibriere Chip und schalte in den Empfangsmodus. */
#define STX      0x35 /**< Schalte in den Sendemodus. */
#define SIDLE    0x36 /**< Gehe in den Ruhezustand. */
#define SAFC     0x37 /**< Führe eine automatische Frequenz-Kompensation (AFC) aus. */
#define SWOR     0x38 /**< Starte die automatische RX polling Sequenz. */
#define SPWD     0x39 /**< Gehe in des SLEEP Mode. */
#define SFRX     0x3A /**< Lösche den RX FIFO. */
#define SFTX     0x3B /**< Lösche den TX FIFO. */
#define SWORRST  0x3C /**< Setze die eWOR Zeit. */
#define SNOP     0x3D  /**< Kein Kommando. 
                           * Wird benutzt um den Zustand des CC1200 zu ermitteln */

If the CC1200 received a command, he will automatically enter the state or perform the command. Afterwards, he will mostly come back to idle state.

To test, if the CC1200 has entered a new state, the function get_status_cc1200 will be used. get_status_cc1200 will return the last available status of CC1200. A status update is given, by performing a command or reading/writing a register. If CC1200 changes its state between such action, the state will actual. To be sure, to get the actual state, perform a SNOP command before reading the state. The SNOP command does nothing in the chip, but it will update the status. This ensures to get the correct state. If should also be considered, that the CC1200 is very much slower compared to the program executing the get_status_cc1200 command. So, it needs some time until CC1200 has updated its status.

CC1200 status information

For possible status informations an enumeration type hs been defined:

typedef enum {  
        IDLE          = 0, /**< Ruhe-Zustand */
        RX            = 1, /**< im Empfangsmode */
        TX            = 2, /**< im Sendemode */
        FSTXON        = 3, /**< Schneller Sendemode ist bereit */
        CALLIBRATE    = 4, /**< Frequenz Synthesizer wird kalibriert */
        SETTLING      = 5, /**< PLL rastet ein */
        RX_FIFO_ERROR = 6, /**< RX FIFO Über- bzw. Unterlauf */
        TX_FIFO_ERROR = 7, /**< TX FIFO Über- bzw. Unterlauf */
        UNKNOWN       = -1      /**< unbekannter Status */
} CC1200_STATES;

int cc1200_cmd(int cmd)
With function cc1200_cmd you execute a CC1200 command. Parameter cmd determines the command. Possible commands are listed above.

int get_status_cc1200(void)
Function get_status_cc1200 returns the last available status of CC1200. To be sure to obtain the actual status, execute cc1200_cmd(SNOP) before function get_status_cc1200.

char *get_status_cc1200_str(void)
Funktion get_status_cc1200_str does the same as function get_status_cc1200 but returns the status information as a string.

Integrating SmartRF Studio Export Files

As described in Section 8_smartrf), you are using SmartRF Studio to select a predefined CC1200 register setting and modify this setting to your needs. Afterwards the register settings will be exported. Now, you have to apply theses register setting to the CC1200. This is necessary, because the CC1200 will load default values to its registers after witching on the chip or preforming a reset. This registers have to be reprogrammed to obtain the desired behavior. Reprogramming is done by the use of function cc1200_reg_write.

In the following, we will look at an example:

Open SmartRF Studio and open the device window of the CC1200. Switch to expert mode and select the predefined register setting “Symbolrate 38.4kbps, 2-GFSK, RX BW 100kHz, ETSI Standard (868MHz)”. Select the tab “Continuous RX” in the lower part of the window. Now, open the export file window and select the “SimpleTI setting” template.

Export the setting into the file smartrf_CC1200.h. This file contains all register setting to operate CC1200 with a Symbolrate of 38.4kkbps at 868MHz … The file should look like this:

/***************************************************************
 *  SmartRF Studio(tm) Export
 *
 *  Radio register settings specifed with C-code
 *  compatible #define statements.
 *
 *  RF device: CC1200
 *
 ***************************************************************/
 
#ifndef SMARTRF_CC1200_H
#define SMARTRF_CC1200_H
 
#define SMARTRF_RADIO_CC1200
#define SMARTRF_SETTING_IOCFG2           0x08
#define SMARTRF_SETTING_IOCFG0           0x09
#define SMARTRF_SETTING_SYNC_CFG1        0xBF
#define SMARTRF_SETTING_MODCFG_DEV_E     0x0B
#define SMARTRF_SETTING_PREAMBLE_CFG1    0x01
#define SMARTRF_SETTING_PREAMBLE_CFG0    0x8A
#define SMARTRF_SETTING_IQIC             0xC8
#define SMARTRF_SETTING_CHAN_BW          0x10
#define SMARTRF_SETTING_MDMCFG1          0x02
#define SMARTRF_SETTING_MDMCFG0          0x05
#define SMARTRF_SETTING_SYMBOL_RATE2     0x8F
#define SMARTRF_SETTING_SYMBOL_RATE1     0x75
#define SMARTRF_SETTING_SYMBOL_RATE0     0x10
#define SMARTRF_SETTING_AGC_REF          0x27
#define SMARTRF_SETTING_AGC_CS_THR       0xEE
#define SMARTRF_SETTING_AGC_CFG3         0x11
#define SMARTRF_SETTING_AGC_CFG1         0x11
#define SMARTRF_SETTING_AGC_CFG0         0x94
#define SMARTRF_SETTING_FIFO_CFG         0x00
#define SMARTRF_SETTING_FS_CFG           0x12
#define SMARTRF_SETTING_PKT_CFG2         0x01
#define SMARTRF_SETTING_PKT_CFG1         0x00
#define SMARTRF_SETTING_PKT_CFG0         0x20
#define SMARTRF_SETTING_PKT_LEN          0xFF
#define SMARTRF_SETTING_IF_MIX_CFG       0x1C
#define SMARTRF_SETTING_FREQOFF_CFG      0x22
#define SMARTRF_SETTING_TOC_CFG          0x03
#define SMARTRF_SETTING_MDMCFG2          0x02
#define SMARTRF_SETTING_FREQ2            0x56
#define SMARTRF_SETTING_FREQ1            0xCC
#define SMARTRF_SETTING_FREQ0            0xCC
#define SMARTRF_SETTING_IF_ADC1          0xEE
#define SMARTRF_SETTING_IF_ADC0          0x10
#define SMARTRF_SETTING_FS_DIG1          0x07
#define SMARTRF_SETTING_FS_DIG0          0xAF
#define SMARTRF_SETTING_FS_CAL1          0x40
#define SMARTRF_SETTING_FS_CAL0          0x0E
#define SMARTRF_SETTING_FS_DIVTWO        0x03
#define SMARTRF_SETTING_FS_DSM0          0x33
#define SMARTRF_SETTING_FS_DVC0          0x17
#define SMARTRF_SETTING_FS_PFD           0x00
#define SMARTRF_SETTING_FS_PRE           0x6E
#define SMARTRF_SETTING_FS_REG_DIV_CML   0x1C
#define SMARTRF_SETTING_FS_SPARE         0xAC
#define SMARTRF_SETTING_FS_VCO0          0xB5
#define SMARTRF_SETTING_IFAMP            0x09
#define SMARTRF_SETTING_XOSC5            0x0E
#define SMARTRF_SETTING_XOSC1            0x03
#define SMARTRF_SETTING_SERIAL_STATUS    0x08
 
#endif

Now, modified the “SimpleTI setting”, that the register address will be exported. Save the exported file to smartrf_adr_CC1200.h. smartrf_adr_CC1200.h should look like this:

/***************************************************************
 *  SmartRF Studio(tm) Export
 *
 *  Radio register settings specifed with C-code
 *  compatible #define statements.
 *
 *  RF device: CC1200
 *
 ***************************************************************/
 
#ifndef SMARTRF_CC1200_ADR_H
#define SMARTRF_CC1200_ADR_H
 
#define IOCFG2_ADR           0x0001
#define IOCFG0_ADR           0x0003
#define SYNC_CFG1_ADR        0x0008
#define MODCFG_DEV_E_ADR     0x000B
#define PREAMBLE_CFG1_ADR    0x000D
#define PREAMBLE_CFG0_ADR    0x000E
#define IQIC_ADR             0x000F
#define CHAN_BW_ADR          0x0010
#define MDMCFG1_ADR          0x0011
#define MDMCFG0_ADR          0x0012
#define SYMBOL_RATE2_ADR     0x0013
#define SYMBOL_RATE1_ADR     0x0014
#define SYMBOL_RATE0_ADR     0x0015
#define AGC_REF_ADR          0x0016
#define AGC_CS_THR_ADR       0x0017
#define AGC_CFG3_ADR         0x0019
#define AGC_CFG1_ADR         0x001B
#define AGC_CFG0_ADR         0x001C
#define FIFO_CFG_ADR         0x001D
#define FS_CFG_ADR           0x0020
#define PKT_CFG2_ADR         0x0026
#define PKT_CFG1_ADR         0x0027
#define PKT_CFG0_ADR         0x0028
#define PKT_LEN_ADR          0x002E
#define IF_MIX_CFG_ADR       0x2F00
#define FREQOFF_CFG_ADR      0x2F01
#define TOC_CFG_ADR          0x2F02
#define MDMCFG2_ADR          0x2F05
#define FREQ2_ADR            0x2F0C
#define FREQ1_ADR            0x2F0D
#define FREQ0_ADR            0x2F0E
#define IF_ADC1_ADR          0x2F10
#define IF_ADC0_ADR          0x2F11
#define FS_DIG1_ADR          0x2F12
#define FS_DIG0_ADR          0x2F13
#define FS_CAL1_ADR          0x2F16
#define FS_CAL0_ADR          0x2F17
#define FS_DIVTWO_ADR        0x2F19
#define FS_DSM0_ADR          0x2F1B
#define FS_DVC0_ADR          0x2F1D
#define FS_PFD_ADR           0x2F1F
#define FS_PRE_ADR           0x2F20
#define FS_REG_DIV_CML_ADR   0x2F21
#define FS_SPARE_ADR         0x2F22
#define FS_VCO0_ADR          0x2F27
#define IFAMP_ADR            0x2F2F
#define XOSC5_ADR            0x2F32
#define XOSC1_ADR            0x2F36
#define SERIAL_STATUS_ADR    0x2F91
 
#endif

Transfer these two files to the BeagleBone Black and include them into your C source code file. Following start programming the CC1200 registers:

cc1200_reg_write(IOCFG2_ADR, SMARTRF_SETTING_IOCFG2);
cc1200_reg_write(IOCFG0_ADR, SMARTRF_SETTING_IOCFG0);
 
// ...
 
// Programm the RF frequency
cc1200_reg_write(FREQ2_ADR, SMARTRF_SETTING_FREQ2);
cc1200_reg_write(FREQ1_ADR, SMARTRF_SETTING_FREQ1);
cc1200_reg_write(FREQ0_ADR, SMARTRF_SETTING_FREQ0);
 
// ...
 
cc1200_reg_write(SERIAL_STATUS_ADR, SMARTRF_SETTING_SERIAL_STATUS);

The above example is not complete, because all registers have to be reprogrammed. It should be pointed out, the reprogramming must be done in idle mode of the CC1200.

Summarize

Your program controlling the CC1200 should probably habe the following structure:

/****************************************************************************/
/*                                                                          */
/* Structure of programs controlling CC1200                                 */
/*                                                                          */
/****************************************************************************/
 
#include <stdio.h>
#include <SPIv1.h> // necessary, otherwise CC1200 prototype are not available
#include "smartrf_CC1200.h" // import register settings
#include "smartrf_adr_CC1200.h" // import register addresses
 
int main (void) {
 
 int adr;
 int val;
 
  // first initialize
  if(spi_init()){
    printf("ERROR: Initialization failed\n");
    return -1;
 
  // do some register reading or writing, 
  // performance commands and get status information
 
  // reset CC1200
  cc1200_cmd(SRES);
 
  // CC1200 is now in idle mode, registers have their default values
  // Reprogram the registers
  cc1200_reg_write(IOCFG2_ADR, SMARTRF_SETTING_IOCFG2);
  cc1200_reg_write(IOCFG0_ADR, SMARTRF_SETTING_IOCFG0);
 
  // ... reprogram the remaining registers 
 
  // Programm the RF frequency
  cc1200_reg_write(FREQ2_ADR, SMARTRF_SETTING_FREQ2);
  cc1200_reg_write(FREQ1_ADR, SMARTRF_SETTING_FREQ1);
  cc1200_reg_write(FREQ0_ADR, SMARTRF_SETTING_FREQ0);
 
  // ... reprogram the remaining registers
 
  cc1200_reg_write(SERIAL_STATUS_ADR, SMARTRF_SETTING_SERIAL_STATUS);  
 
 
  // get status information
  cc1200_cmd(SNOP);
  printf("INFO: Status:%s\n", get_status_cc1200_str());
 
  adr = 0x01;
  // register read
  cc1200_reg_read(adr, &val);
  printf("INFO:read Adr:0x%x Val:0x%x\n", adr, val);
 
  // read extended register
  adr = EXT_ADR | 0x0A;
  cc1200_reg_read(adr, &val);
 
  // shutdown SPI
  spi_shutdown();
 
  return 0;
}

This structure has been used by testing the SPI in the page SPI Library. Feel free to use this template in the directory ~/Beaglebone/SPI_test and modify it to your needs.

network_protocol_programming_lab/15.2_cc1200_programming.1617965547.txt.gz · Last modified: 2021/04/09 12:52 by admin
CC Attribution-Noncommercial-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0