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. http://blog.makezine.com/archive/2007/04/fun_with_xbee_and_arduino.html
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 http://www.rcgroups.com 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: http://www.cypress.com/?app=search&searchType=docs&keyword=CYRF6936&rtID=0&id=10
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:
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.
CYRF6936 TX.
Initialisation.
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.
The Artaflex AWA24S module also needs pins 10, 11 and 12 set for Transmit:
AWA24S only:
Transmit function.
Load the CYRF6936 with the following:
Monitor the following bytes for transmit status:
If TXC IRQ is set without TXE IRQ then the transmission was successful.
The following C code snippet monitors TXC IRQ and TXE IRQ :
RadioState=0x00;
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.
Initialisation.
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.)
Again the Artaflex AWA24S module also needs pins 10, 11 and 12 set for Receive:
AWA24S only:
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.
Monitor the following bytes for receive status:
Providing the data arrived without errors it can be read.
First set the following:
Then read as many bytes as you are expecting from the Receive data buffer:
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 ;
}
else{
// receive RX error missed by cyrf the first time.
return 4 ;
}
}
else{
// CRC errors.
return(5);
}
}
// 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:
Receiving node:
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!
dunk.
mrdunk(at)gmail.com.