Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
network_protocol_programming_lab:15.2_cc1200_programming [2021/04/09 12:52] – [Integrating SmartRF Studio Export Files] adminnetwork_protocol_programming_lab:15.2_cc1200_programming [2022/04/18 17:16] (current) – [Controlling CC1200] fangenoorth
Line 1: Line 1:
 +====== 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 [[network_protocol_programming_lab:8_smartrf#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 [[http://www.ti.com/lit/ug/swru346b/swru346b.pdf|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:
 +
 +<code C>
 +/* 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 */
 +</code>
 +
 +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:
 +
 +<code C>
 +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;
 +</code>
 + 
 +''**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 [[network_protocol_programming_lab:8_smartrf]]), you are using 4C 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 4C and switch to //RX Synchronous Serial Mode// of the mode menu. This will load the predefined register setting  “Symbolrate 38.4kbps, 2-GFSK, RX BW 100kHz, ETSI Standard (868MHz)” to the CC1200. Now, open the Export Register to C in file menu and export the register values.
 +
 +The beginning of the file should look like this:
 +
 +<code C>
 +/***************************************************************/
 +/* C-file generated by CC1200 Control Center                   */
 +/*                                                             */
 +/*  Generated at x/x/2021  12:26.17                             */
 +/***************************************************************/
 + 
 +#define  IOCFG3             0x00 
 +#define  IOCFG2             0x01 
 +#define  IOCFG1             0x02 
 +#define  IOCFG0             0x03 
 +#define  SYNC3              0x04 
 +#define  SYNC2              0x05 
 +#define  SYNC1              0x06 
 +#define  SYNC0              0x07 
 +#define  SYNC_CFG1          0x08 
 +#define  SYNC_CFG0          0x09 
 +#define  DEVIATION_M        0x0A 
 +#define  MODCFG_DEV_E       0x0B 
 +#define  DCFILT_CFG         0x0C 
 +#define  PREAMBLE_CFG1      0X0D 
 +#define  PREAMBLE_CFG0      0x0E 
 +#define  IQIC               0x0F 
 +#define  CHAN_BW            0x10 
 +#define  MDMCFG1            0x11 
 +#define  MDMCFG0            0x12 
 +#define  SYMBOL_RATE2       0x13 
 +#define  SYMBOL_RATE1       0x14 
 +#define  SYMBOL_RATE0       0x15 
 +#define  AGC_REF            0x16 
 +#define  AGC_CS_THR         0x17 
 +#define  AGC_GAIN_ADJUST    0x18 
 +#define  AGC_CFG3           0x19 
 +#define  AGC_CFG2           0x1A 
 +#define  AGC_CFG1           0x1B 
 +#define  AGC_CFG0           0x1C 
 +#define  FIFO_CFG           0X1D 
 +#define  DEV_ADDR           0x1E 
 +#define  SETTLING_CFG       0x1F 
 +#define  FS_CFG             0x20 
 +#define  WOR_CFG1           0x21 
 +#define  WOR_CFG0           0x22 
 +#define  WOR_EVENT0_MSB     0x23 
 +#define  WOR_EVENT0_LSB     0x24 
 +#define  RXDCM_TIME         0x25 
 +#define  PKT_CFG2           0x26 
 +
 +</code>
 +
 +
 +Transfer this to the BeagleBone Black and include it into your C source code file. Following start programming the CC1200 registers:
 +
 +<code C>
 +cc1200_reg_write(RegSettings[0].adr, RegSettings[0].val); // GPIO3 IO Pin Configuration
 +cc1200_reg_write(RegSettings[1].adr, RegSettings[2].val); // GPIO2 IO Pin Configuration
 +
 +// ...
 +
 +// Programm the RF frequency
 +cc1200_reg_write(ExtRegSettings[12].adr, ExtRegSettings[12].val); //FREQ2
 +cc1200_reg_write(ExtRegSettings[13].adr, ExtRegSettings[13].val); //FREQ1
 +cc1200_reg_write(ExtRegSettings[14].adr, ExtRegSettings[14].val); //FREQ0
 +
 +// ...
 +
 +// you can program the above using a loop
 +</code>
 +
 +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:
 +
 +<code C>
 +/****************************************************************************/
 +/*                                                                          */
 +/* 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;
 +}
 +</code>
 +
 +
 +This structure has been used by testing the SPI in the page [[network_protocol_programming_lab:4_prepareppl#SPI Library]].
 +Feel free to use this template in the directory ''~/Beaglebone/SPI_test'' and modify it to your needs.
CC Attribution-Noncommercial-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0