For a learning experience, I wrote a spectrum analyzer and since the code is pretty short, I’ve just posted it below.
It scans all 256 channels, with the receiver set up in the same way as the other Pololu apps except that sync word detection is disabled. Using the companion app test_radio_signal_tx running on another wixel, one can clearly see the strong overlap between two adjacent channels; close to 100%.
I have not been inspired to come up with a fancy display of the output, so at the moment, the code scans through all channels 10 times (listening about 1.6 ms per scan per channel) and reports those channels with maximum signal strength greater than -90 dBm over the usb serial connection (e.g. Hyperterm). Both average and maximum signal strength values are reported.
All comments, modifications and improvements are welcome.
PS: I want to thank everyone at Pololu who contributed to the thorough wixel user guide. The instructions on using Eclipse were VERY helpful – it is lovely software with some very nice features. I would add only that I found it easier to load apps using the Wixel Configuration Utility, rather than using the command line window, mainly because no typing is required.
Thanks, Jim
/* spectrum analyzer:
*
* The receivers(s) (the Wixel(s) loaded with spectrum_analyzer) will
* report the signal strength on all 256 channels.
*
* Average and maximum signal strength is reported in dBm on the USB serial connection.
* This will be a number typically between -100 and -30, indicating the signal strength.
* Heavily modified from test_radio_signal_rx app by S. James Remington
*
*/
#include <wixel.h>
#include <radio_registers.h>
#include <stdio.h>
#include <usb.h>
#include <usb_com.h>
static volatile int16 DATA i,channel;
static volatile int32 DATA rssiSum;
static volatile uint8 DATA reportLength;
static volatile uint8 XDATA report[20];
static volatile int16 XDATA rssiAvg[256],rssiMax[256],rssiVal=0;
static volatile uint8 XDATA rfdata;
void updateLeds()
{
usbShowStatusWithGreenLed();
LED_YELLOW(0) ;
LED_RED(0);
}
void perTestRxInit()
{
radioRegistersInit();
MCSM0 = 0x14; // Auto-calibrate when going from idle to RX or TX.
MCSM1 = 0x00; // Disable CCA. After RX, go to IDLE. After TX, go to IDLE.
// We leave MCSM2 at its default value = 0x07
MDMCFG2 = 0x70; //disable sync word detection
RFST = 4; //idle radio
}
void CheckRadioChannels()
{
int8 j;
LED_YELLOW(1);
for(channel=0; channel<256; channel++)
{
rssiAvg[channel] = 0;
rssiMax[channel] = -999;
}
for(j=0; j<10; j++) //ten times through all channels
{
usbComService(); //keep usb connection alive
for(channel=0; channel<256; channel++)
{
while(MARCSTATE != 1); //radio should already be idle, but check anyway
CHANNR = channel;
RFST = 2; // radio in RX mode and autocal
while(MARCSTATE != 13); //wait for RX mode
rssiSum = 0;
for (i=0; i<100; i++)
{
if (TCON & 2) //radio byte available?
{
rfdata=RFD; //read byte
TCON &= ~2; //clear ready flag
}
rssiSum += radioRssi();
}
RFST = 4; //idle radio
rssiVal = (int16) (rssiSum/100);
rssiAvg[channel] += rssiVal;
if (rssiMax[channel] < rssiVal) rssiMax[channel] = rssiVal; // save maximum
} // the above loop takes about 414 ms on average, so about 1.6 ms/channel
}
for (channel=0; channel<256; channel++) rssiAvg[channel] /= 10;
LED_YELLOW(0);
}
void reportResults()
{
for (i=0; i<256; i++)
{
if (rssiMax[i] > -90) //report activity on channel if maximum is above -90 dBm
{
while (usbComTxAvailable() < 20) usbComService() ; //wait for usb TX buffer space
reportLength = sprintf(report, "%4d, %4d, %4d\r\n", i, rssiAvg[i], rssiMax[i]);
usbComTxSend(report, reportLength);
}
}
}
void main()
{
systemInit();
usbInit();
perTestRxInit();
usbInit();
while(1)
{
boardService();
usbComService();
updateLeds();
CheckRadioChannels();
reportResults();
}
}