Interfacing Cypress CYRF6936 to AVR microcontrollers.

What is this all about then?

If you are not an electronics hobbyist or know much about embedded electronics then be warned, this is going to be very dry reading for you.

The Cypress CYRF6936 is a modern 2.4 GHz Direct Sequence Spread Spectrum (DSSS) radio transceiver.
It is widely used in a huge range of commercial applications but largely unused by hobbyists at the time of writing. (Spring 09.)
While there are easier to use radio modules and transceivers out there i wanted to use the CYRF6936 for it's huge versatility and relatively low cost.

The CYRF6936 can be used to add wireless radio communication to most modern microcontrollers.
I used an Atmel AVR but any of the Microchip PIC or PIC32 range would work as well.

If you want an easy to use solution and don't mind being somewhat tied by the manufacturer's design choices you might want to consider the Xbee.
There are lots of online examples on how to use that platform. eg.

If on the other hand you need a more flexible solution then keep reading.
The reason i started playing with the CYRF6936 was I needed a low latency solution.

Existing documentation on the CYRF6936.

I am writing this page in the absence of any other resource for hobbyists to use this highly useful, high speed 2.4GHz transceiver.
At the time of writing there is very little documentation online about interfacing the various CYRF6936 based RF modules.
I could not find any example code that helped me configure the CYRF6936. If this changes over time please let me know so i can update this section.

The guys at have done some reverse engineering of consumer RC equipment that uses this chip but digging through the forum posts there tends to get you more information about the proprietary RC systems than about the CYRF6936.

The more obvious source of information is the Cypress website.
A bit of digging around on the CYRF6936 specific page will get you the Datasheet
I have a copy of the Datasheet that gives you all the register descriptions but at the moment the one on the Cypress website only gives the a list of the register names.
You will need to go to the Technical Reference Manual for the register descriptions. (Chapter 10.)
Read *all* of the datasheet and all the chapter of the Technical Reference Manual on Registers before you start. Every time you run into problems read it again. It does tell you what you need to get this chip to work but it is not always in the most obvious place on the datasheet or the most obvious register on the CYRF6936.

The other thing i was looking for on the Cypress website are application notes.
Unfortunately all of the source code and configuration examples i could find for the CYRF6936 are written in machine code for a Cypress microcontroller that i have no experience with.
While it was worth reading these the only really useful part are the header files for the pin definitions.

The full range of Cypress documentation relevant to the CYRF6936 is available here:

When it comes to finding documentation on a specific CYRF6936 based module most of the module datasheets are understandably based on the CYRF6936 datasheet.
Artaflex does a reasonable job of documenting any important details that may be different from default when configuring the CYRF6936 in their modules.
The Unigen UGWJ4US datasheet on the other hand sucks. I wasted many weeks searching for the correct way to operate that modules RF switch.

Modules discussed on this page.

Rather than try to solder the CYRF6936 QFN package there are several pre-made modules available that combine the CYRF6936 with various RF switches and amplifiers for greater range.
Here are the ones i have experimented with:
 Module Manufacturer Range Header format
 Transaction mode possible?
 Antenna connector
 UGWJ4US Unigen 1km nonLOS
 2x6 pin. 2mm spacing
 ? mini coaxial 15.6Euro
 UGWG4US Unigen 30m 2x6 pin. 2mm spacing y PCB antenna built in
 AWA24S  Artaflex  1km outdoor LOS 2x6 pin. 2mm spacing n mini coaxial 27Euro

The Artaflex modules have changed to using the CYRF7936 chip.
While the CYRF7936 should be similar to the CYRF6936 i can't say for sure if my code will work with it or not.
At the time of writing there does not appear to be a full datasheet available for the CYRF7936 that documents the configuration registers.

If you have success with any other modules please let me know.

It is worth pointing out all 3 modules i have listed use the same 2x6 pin header. This header has 2mm pin spacing which is annoying as it will not fit common prototyping boards but being the same across modules has the advantage of making the modules relatively interchangeable.

For the most part these modules are controlled by the same header pins which interface directly with the CYRF6936 SPI bus.
The exception to this are pins 10,  11 and 12 on the header have varying functionality.
The UGWG4US is the simplest module to work with. It has no other RF switching or amplifying circuitry to deal with so pins 10, 11 and 12 are unconnected.
The UGWJ4US uses the CYRF6936 to drive the RF switch. It is important to set the correct registers on the CYRF6936 to control the RF switch correctly. (More on this in the configuration section.) Pins 11 and 12 on the module are outputs of the RF switch status so it is important not to set the logic of these pins. (Set your microcontroller to input if it is connected to these pins.)
The AWA24S uses pins 10, 11 and 12 to drive the RF switch. The CYRF6936 has no control over this so it must be done in firmware by the microcontroller. This is a simple addition to the TX and RX code.

There are a few hidden costs when using these modules.
On the UGWJ4US and AWA24S module a  somewhat obscure mini coaxial connector which is difficult to find connectors for.
This connector type is used on a few computer wireless network cards (eg. IBM laptops wireless cards) and can be found on E-bay. Digi-Key stocks ready made up cables as well. (Search for "U.FL")
The UGWG4US has a built in PCB antenna so no additional hardware is needed.

All the modules i have listed also require a 2mm pitch connector unless you want to solder them directly into your project.

Microcontroller requirements.

In theory any microcontroller of operating at 2.7 - 3.3V and with enough IO pins is suitable for interfacing a CYRF6936. A hardware SPI module is an advantage but it would be possible to bit-bang the SPI signals in firmware.

My project uses Atmel AVR atmega2561 microcontrollers for this. These have built in SPI hardware and more than enough program space for my application.

CYRF6936 options.

The CYRF6936 has built in Transaction Mode. This automated the reply of an ACK packet whenever a module receives a packet. The transmitting module listens for this ACK and only reports a successful transmission if it is received.
Not all modules support Transaction Mode however. The AWA24S for example requires the microcontroller to stitch on and off the RF switch on the module using header pins on the module so it does not support Transaction Mode.
The examples shown here presume Transaction Mode is switched off.

The header and data portion of the data packet can both be set with either 32-chips or 64-chips.
Without going into too much detail on how the radio in the CYRF6936 works, 32-chips have less immunity to noise and therefore shorter range but higher speed.

A receiving CYRF6936 should be able to receive data sent by another CYRF6936 with different configuration to it's self.
A CYRF6936 should accept any valid packet (providing CRC16 is compatible).

CYRF6936 initialisation.

Communication between the microcontroller and the CYRF6936 is done over the SPI bus.
The CYRF6936 is controlled by setting various registers via the SPI bus.

There are many ways to set up the CYRF6936. That is one of the things that makes it so versatile.
One of the things i found intimidating when initially starting with these modules was getting an initial working config from which to start tweaking.
Here i will simply list a working configuration and briefly touch on a few of the aspects a hobbyist may want to change.

The following list in the order presented will set the CYRF6936 base configuration.
This setup has transaction mode switched and is suitable for one way communication where the transmitting station does not test for data reception.
It is suggested you use these as an initial working config from which you can experiment with making changes later.

 Register Register Name
 Recommended Value Function 
 1D MODE_OVERRIDE 00000001 RST = Reset. Setting this bit forces a full reset of the device. 
 03 TX_CFG 00101111  Set various Transmit functions here.
 64-chip vs 32-chip codes: 64 = slower but better immunity to noise.
 8DR mode is recommended unless you are connecting to legacy Cypress products (DDR or SDR) or want to do away with all framing and go for speed (GFSK).
The PA setting you will probably want to set to it's highest power.
 05 RX_CTRL 00000000 If you want to use the hardware interrupt pin you will need to set some of the IRQEN bits here.
The method of receiving data described later checks the RX_IRQ_STATUS register for this information so all hardware interrupts are turned off.
 06 RX_CFG 10001010 This register controls some of the built in receive circuitry.
Probably the most likely bit a user might want to change is the RXOW EN bit which if cleared stops the receive buffer from being over written once it contains valid data. (Most users will want to leave this bit set.)
 0F XACT_CFG 00010011 If you want to switch on transaction mode the ACK EN bit here is where you do it.
For initial testing it is recommended to set END STATE to 100 = RX Mode. Once you have things working you can experiment with other lower power options.
 10 FRAMING_CFG 11101110 The recommended value shown is configured for reliability rather than speed.
 11 DATA32_THOLD 00001000 The value here is the recommended from the Datasheet. (Not really needed as the rest of this setup does not use 32-chip correlators.)
 12 DATA64_THOLD 00001110 The value here is the recommended from the Datasheet. 
 15 CRC_SEED_LSB 00010100 CRCs must match at both ends.
 16 CRC_SEED_MSB 00010100  
 1B TX_OFFSET_LSB 01010101 This is the Datasheet's recommended value.
 1C TX_OFFSET_MSB 00000101  
 1E RX_OVERRIDE 00001000 **** check: don't think  FRC RXDR is needed.***
It might be worth setting ACE if you are experiencing allow data with CRC16s that do not match.
 26 XTAL_CFG 00001000 This is the Datasheet's recommended value. 
 32 AUTO_CAL_TIME 00111100 This is the Datasheet's recommended value. 
 35 AUTO_CAL_OFFSET 00010100 This is the Datasheet's recommended value. 
 0C XTAL_CTRL 01000000 UGWJ4US only.
 This is required for the UGWJ4US module. It allows the CYRF6936 to drive the modules RF power amplifier.
The Unigen datasheet does not mention this.

CYRF6936 TX.

The first step is to set the CYRF6936 registers for transmission.
This is as simple as setting the END STATE bytes in the XACT_CFG register to 001 = Idle Mode. This causes the CYRF6936 to sit idle with the crystal and synthesizer running.
An alternative would be to set the default state to 000 = Sleep Mode but this can lead to some complications waiting for the the crystal and synthesizer to start when a transmit is performed.
 Register Register Name Recommended Value Function
 05 RX_CTRL 10000000 Set RXGO. This is counter intuitive. RXGO should only need set when receiving data. I suspect there is a misconfiguration in our clock setup and setting RXGO gets the clock running correctly. Either way, it works if you set it up this way.
 0F XACT_CFG 00100111 Set END STATE to 001 = Idle Mode.
Also set FRC END to make CYRF6936 go to Idle Mode immediately.

The Artaflex AWA24S module also needs pins 10, 11 and 12 set for Transmit:
AWA24S only:

 Radio Mode 
 TXPA (Pin 11)  RXPA (Pin 12) PACTL (Pin 10)
 Transmit High (3.3V) Low (0V) 0.5V - 3.3V

Transmit function.
Load the CYRF6936 with the following:
 Register Register Name Recommended Value Function
 01 TX_LENGTH 00010000 The CYRF6936 transmit buffer is only 16 bytes long so we will only be discussing transmissions up to this length.
 02 TX_CTRL 01000000 Setting the TX CLR bit clears the transmit buffer.
 20 TX_BUFFER 1st data byte.
 Load transmit buffer with data.
 20 TX_BUFFER 2nd data byte. 
 20 TX_BUFFER 16th data byte. 
 02 TX_CTRL 10000000 Set TX GO to start transmit.

Monitor the following bytes for transmit status:
  Register  Register Name Byte Byte name
 04 TX_IRQ_STATUS 00000010 TXC IRQ
 Transmission complete interrupt.
 04 TX_IRQ_STATUS 00000001 TXE IRQ
 Transmission error interrupt.
If TXC IRQ is set without TXE IRQ then the transmission was successful.

The following C code snippet monitors TXC IRQ  and TXE IRQ :
  while (!RadioState){

          RadioState = RadioState | (SpiByteRead(0x04) & (TXE | TXC));
  if (RadioState == 0x02){                            // TXC=1, TXE=0.
          if (!(SpiByteRead(0x04) & TXE)) {    // check TXE again.
                  return 0;                                        // TX succefull! happy days.
  return 1;                                                        // Fail. 

CYRF6936 RX.

The first step is to set the CYRF6936 registers for receiving.
The important one at this time is setting the END STATE but setting RX GO just now will save some time later. (RX GO will be set during the transmit data code if it is not already.)
 Register Register Name Recommended Value Function
 05 RX_CTRL 10000000 Set RX GO which causes the device to transition to receive mode.
 0F XACT_CFG 00010011 Set END STATE to 100 = RX mode.

Again the Artaflex AWA24S module also needs pins 10, 11 and 12 set for Receive:
AWA24S only:
 Radio Mode 
 TXPA (Pin 11)  RXPA (Pin 12) PACTL (Pin 10)
 RecieveLow (0V) High (3.3V) Low (0V)

Receive function.

If it has not already been done in the Initialisation section you need to set RX GO to receive a byte.
RX GO will clear if a byte has been received. Make sure this bit is set when you expect data to be incoming otherwise the data will be missed.
 Register Register Name Recommended Value Function
 05  RX_CTRL 10000000 Set RX GO which causes the device to transition to receive mode.

Monitor the following bytes for receive status:
  Register  Register Name Byte Byte name
  05 RX_CTRL 10000000 RX GO RX GO will clear if a byte has been received.
 If a byte has been received this bit will trigger.
  07 RX_IRQ_STATUS 00000001 RXE IRQ If a received byte has errors this bit will trigger.

Providing the data arrived without errors it can be read.
First set the following:
 Register Register Name Recommended Value Function
 07 RX_IRQ_STATUS 10000000 Bit: RXOW IRQ. This bit must be written ‘1’ by firmware before the new packet may be read from the receive buffer.

Then read as many bytes as you are expecting from the Receive data buffer:
 Register Name
 21 RX_BUFFER 1st received data byte.
 21 RX_BUFFER 2nd received data byte.
 21 etc... up to the number of data bytes sent. The buffer is only 16 bytes long so the method described here will only work up to that length.

Remember to set RX GO again as soon as possible after you are finished if you are expecting more data to arrive.

the following code monitors RXGO to wait for data to be received.
uint8_t cyrf6936_RX_test(CYPRESS_CYRF* cyrf)
   while ((cyrf_SPI_Read(0x05, cyrf) & RXGO)) {}

    // RXGO has cleared so *something* has been received.
    uint8_t RadioState = cyrf_SPI_Read(0x07, cyrf) ;

    if(RadioState & RXE) {
        // receive error flag set.
        return 2;
    else if(RadioState & RXBERR) {
        // Receive Buffer ERRor
        return 3;
    else if(RadioState & RXC) {
        // Receive Complete. (good thing)
        if (!(cyrf_SPI_Read(0x08, cyrf) & badCRC)){
            // no CRC error either.
            if(!(RadioState & RXE)) {
                // second check for receive error. (rare but the datasheet asks for it.)
                // all is good. return 0 means successful reception.
                return 0 ;
                // receive RX error missed by cyrf the first time.
                return 4 ;
            // CRC errors.
    // no errors but RXE not set either.
    // if here on interrupt packet is probably good.
    // if you are poling this function you normally end up here if no data received.
    return 6;

Example projects using the CYRF6936.

Apart from my own project i do not know of any online documentation that shows you how to build a CYRF6936 project from the hobbyist's perspective.

My project is here: DIY RC System. (Including AVR C source code.)
It is a fully functioning radio control system featuring 1 mile range and 2 way communication to allow the collection of sensor data from the controlled vehicle. (An RC aircraft in my case.)
The documentation there comes complete with schematics and down loadable code for an Atmel AVR programmed using GCC.

Please let me know if you know any more links to other projects, source code, programming examples, etc for the CYRF6936.

Using my code.

My project's code can be downloaded here: Downloads.
The sample functions mentioned below should work on any AVR microcontroller. The platform that they were tested on is an ATmega2561 running at 16MHz.
Call the functions in the order listed.
Feel free to use my SPI functions or those provided in WebbotLib. This code works with either.

Transmitting node:
 Function to call:
 This puts the CYRF6936 in Transmit mode.
 cyrf6936_TX_FillBuffer() Tells the CYRF the length of the data being sent and fills the buffer.
 cyrf6936_TX() This actually transmits the data and tests for successful transmission.
 Returns "0" if TX was successful. Returns "1" if TX errors occurred.

Receiving node:
 Function to call:
 This puts the CYRF6936 in Receive mode.
 Incoming data will cause the CYRF6936 interrupt pin to trigger.
cyrf6936_RX_test() Either poll this function often to detect incoming data or run it once when the CYRF6936 interrupt pin triggers.
 This function returns "0" if data has been successfully received.
 Reads data from the CYRF and saves it in an array.

How to contact me.

I'm not interested and will not have time to provide support for anything i have written here. If you have problems you are very much on your own.
My only intention in writing this is to try and make your lives easier. I am not affiliated with any of the companies who's products i have talked about and as such i cannot guarantee everthing here is correct.
If you have constructive ways i could improve this page though, try dropping me an email/

Thanks/praise/job offers/cash donations are always welcome though.

good luck with your projects!