Hello,
I am trying to create a wireless link between the evalbot and a msp430 launchpad populated with the g2553 chip.
The evalbot has the c1101 868MHz - 915MHz EM kit plugged in, the launchpad is using the anaren air booster pack which uses he cc110L rf chip.
Some background;
Before attempting to setup the link bewteen the evalbot and msp430, I tested two msp430's with air booster packs attached and successfully sent a packet of data from one to the other to turn on/off the launchpad leds. I did this by using register settings from smart studio and reading the datasheet to adjust the packet length register to send only 1 byte.
I am only sending 1 byte of data with CRC and RSSI appended to it. I just want to get things up an running before I move onto larger packet sizes. I am using GDO0 as my interrupt source for the evalbot. It will go low when the end of the 3 byte packet is received (1 byte CRC, 1 byte data, 1 byte RSSI).
The code on the MSP430 simply increments a counter when on board switch is pressed. This value is then sent over the air and if the evalbot receives a "4" it turns on the LEDS. I used this with the two msp430s and it worked perfectly.
I thought it would be an easy case of just pasting the code into my evalbot project to get up and running. This was definitely not the case ;)
I am using IAR embedded workbench 6.60 to setup the evalbot. I used ccs to setup the msp430->msp430 link.
The problem;
I moved my code over to my evalbot project on IAR and it seems that I cannot receive a packet from the msp430 module. Literally nothing happens on the GDO0 line, I have checked this line by setting it up to use a clock source (IOCFG0=0x30) . I verified the clock signal using an oscilloscope and it is working.
Below are the files I am using
The first is my main file - In it,I first include my necessary files from the stellaris ware library and my own header files (RF_SPI_FUNCTIONS.h,Air_Booster_Pack.h)
the second is the functions I use to read/write to the cc1101 chip - these are the functions pointed to by my header file RF_SPI_FUNCTIONS.h.
the third is my startup ewarm file - which just shows I have set the interrupt up correctly (or so I believe)
Questions;
1. What am I missing here? Honestly I know it's probably something minute but my brain is fried. Or maybe ti's something huge and I'm blind?
2. I use the char Buf to store the value from the SSI1 RX FIFO (or so I believe) to show the values returned by reading status registers of the cc1101. I did this because I had a hard time understanding what was being returned to the evalbot spi interface. This proved to be more confusing because the value in the debug register window was different that that in the local window for Buf.....did I miss something in my CC1101_ST_REG()? Maybe I implemented it incorrectly? When I used the msp430 it was no problem reading the spi FIFO because there was two separate values in the debug window. With the evalbot however I can't figure out whether the value shown in SSIDR is the RX or TX FIFO value.
3. I have read about WOR and from what I understand it only applies when the radio is put in a power save mode.
My concern is that I am missing some other timeout mechanism? or that I have to constantly place the unit in RX mode if I don't set a bit in the main state machine register.
I have tried to give all the information I can in this initial post. If I have left something out please let me know. This is my first post and I hold my hands up if I missed something.
//////////////////////////////////////////////////MAIN FILE BEGIN////////////////////////////////////////////////////////////////////////////////////////////
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "driverlib/interrupt.h"
#include "driverlib/ssi.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "utils/uartstdio.h"
#include "RF_SPI_FUNCTIONS.h"
#include "Air_Booster_Pack.h"
int main(void)
{
char Buf =0; // used for reading SSI1 RX FIFO
//Setup system clock
SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN |
SYSCTL_XTAL_16MHZ);
//Setup Ports and SSI1
SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI1);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOH);
//Configure pins on port H for SSI1 function
GPIOPinConfigure(GPIO_PH4_SSI1CLK); //CLK
GPIOPinConfigure(GPIO_PH6_SSI1RX); //MISO
GPIOPinConfigure(GPIO_PH7_SSI1TX); //MOSI
GPIOPinTypeSSI(GPIO_PORTH_BASE, GPIO_PIN_6 | GPIO_PIN_4 |GPIO_PIN_7);
//Setup SSI1 for 8 bits SPI master running at 200KHz
SSIConfigSetExpClk(SSI1_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_0,
SSI_MODE_MASTER, 200000, 8);
//Enable SSI1
SSIEnable(SSI1_BASE);
//Setup input for interrupt from cc1101 GDO0 pin
GPIOPinTypeGPIOInput(GPIO_PORTH_BASE,GPIO_PIN_2);
// GPIOPadConfigSet(GPIO_PORTH_BASE,GPIO_PIN_2,GPIO_STRENGTH_2MA,GPIO_PIN_TYPE_STD_WPU);
//Setup Port F pins 4&% as outputs to drive LEDS
GPIOPinTypeGPIOOutput(GPIO_PORTH_BASE, GPIO_PIN_5);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_4 | GPIO_PIN_5);
//Power on Reset for cc1101
CC1101_POR_RES();
//Configure registers for cc1101
CC1101_SETUP();
CC1101_Write(PATABLE,0x50);
//Set cc1101 into IDLE state to flush RX and TX FIFO
CC1101_CMD_REG(SIDLE);
CC1101_CMD_REG(SFRX);
CC1101_CMD_REG(SFTX);
//Check current state
Buf = CC1101_ST_REG(MARCSTATE);
//Set cc1101 in RX mode
CC1101_CMD_REG(SRX);
//Check cc1101 is in RX mode
Buf = CC1101_ST_REG(MARCSTATE);
//Clear Interuppts for PORTH
GPIOPinIntClear(GPIO_PORTH_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|
GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
//Setup interrupt properties for pin 2 port H
GPIOIntTypeSet(GPIO_PORTH_BASE, GPIO_PIN_2, GPIO_FALLING_EDGE);
//Enable interrupt for pin2 PortH
GPIOPinIntEnable(GPIO_PORTH_BASE, GPIO_PIN_2);
//Clear pending interrupts to processor
IntPendClear(INT_GPIOH);
//Enable interrupt for portH
IntEnable(INT_GPIOH);
//Check state of cc1101 and value of bytes in RX/TX FIFOs
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(TXBYTES);
Buf = CC1101_ST_REG(RXBYTES);
//Set cc1101 in RX mode and read state
CC1101_CMD_REG(SRX);
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(MARCSTATE);
Buf = CC1101_ST_REG(MARCSTATE);
while(1){
}
////////////////
}
//Port H interrupt Handler
void PortHIntHandler (void)
{
char a,i;
//Clear interrupt source
GPIOPinIntClear(GPIO_PORTH_BASE,GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|
GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
//Read CRC byte, Data byte, then RSSI byte
for (i=0;i<3;i++){
//Store value from RX fifo in a
a= CC1101_Read(0x3F);
if (a==4)
{
GPIOPinWrite(GPIO_PORTF_BASE,(GPIO_PIN_4 | GPIO_PIN_5 ),0xFF);
//blink LED if =4
}
else
{
GPIOPinWrite(GPIO_PORTF_BASE,(GPIO_PIN_4 | GPIO_PIN_5 ),0x00);
//leds off
}
}
//Put cc1101 in RX state to await another packet
CC1101_CMD_REG(SRX);
}
//////////////////////////////////////////////////MAIN FILE END////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////RF SPI FUNCTIONS FILE BEGIN/////////////////////////////////////////////////////////////////
#include "RF_SPI_FUNCTIONS.h"
#include "inc/hw_memmap.h"
#include "inc/hw_ssi.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_nvic.h"
#include "driverlib/interrupt.h"
#include "driverlib/ssi.h"
#include "driverlib/gpio.h"
#include "driverlib/pin_map.h"
#include "utils/uartstdio.h"
#include "Air_Booster_Pack.h"
//Setup configuration for cc1101 registers
//Set for 868MHz,GFSK, packet length =1,no address checking,0dB power,1.2KBaud
void CC1101_SETUP(void){
CC1101_Write(IOCFG2,0x29);
CC1101_Write(IOCFG1,0x2E);
CC1101_Write(IOCFG0,0x41);
CC1101_Write(FIFOTHR,0x47);
CC1101_Write(SYNC1,0xD3);
CC1101_Write(SYNC0,0x91);
CC1101_Write(PKTLEN,0x01);
CC1101_Write(PKTCTRL1,0x04);
CC1101_Write(PKTCTRL0,0x04);
CC1101_Write(ADDR,0x00);
CC1101_Write(CHANNR,0x00);
CC1101_Write(FSCTRL1,0x06);
CC1101_Write(FSCTRL0,0x00);
CC1101_Write(FREQ2,0x21);
CC1101_Write(FREQ1,0x62);
CC1101_Write(FREQ0,0x76);
CC1101_Write(MDMCFG4,0xF5);
CC1101_Write(MDMCFG3,0x83);
CC1101_Write(MDMCFG2,0x13);
CC1101_Write(MDMCFG1,0x42);
CC1101_Write(MDMCFG0,0xF8);
CC1101_Write(DEVIATN,0x15);
CC1101_Write(MCSM2,0x07);
CC1101_Write(MCSM1,0x30);
CC1101_Write(MCSM0,0x18);
CC1101_Write(FOCCFG,0x16);
CC1101_Write(BSCFG,0x6C);
CC1101_Write(AGCCTRL2,0x03);
CC1101_Write(AGCCTRL1,0x40);
CC1101_Write(AGCCTRL0,0x91);
CC1101_Write(0x20,0xFB);
CC1101_Write(FREND1,0x56);
CC1101_Write(FREND0,0x10);
CC1101_Write(FSCAL3,0xE9);
CC1101_Write(FSCAL2,0x2A);
CC1101_Write(FSCAL1,0x00);
CC1101_Write(FSCAL0,0x1F);
CC1101_Write(0x27,0x41);
CC1101_Write(0x28,0x00);
CC1101_Write(0x29,0x59);
CC1101_Write(0x2A,0x7F);
CC1101_Write(0x2B,0x3F);
CC1101_Write(TEST2,0x81);
CC1101_Write(TEST1,0x35);
CC1101_Write(TEST0,0x09);
}
//Power on reset funciton
void CC1101_POR_RES()
{
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0x00); // CS FOR SPI INTERFACE ENABLE
SysCtlDelay(55);
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0xFF); // CS FOR SPI INTERFACE DISABLE
SysCtlDelay(215); //~40uS delay
CC1101_CMD_REG(SRES);//Reset command
}
//Command register access fucntion
void CC1101_CMD_REG(char address)
{
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0x00); // CS FOR SPI INTERFACE ENABLE
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, address| 0x80);// Send address with burst bit set
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0xFF); // CS FOR SPI INTERFACE DISABLE
}
//Read status register function
char CC1101_ST_REG(char address)
{
unsigned long x = 0;
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0x00); // CS FOR SPI INTERFACE ENABLE
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, address| 0xC0);// Send address
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, 0x00);// Send address
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataGet(SSI1_BASE,&x); // Read data
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0xFF); // CS FOR SPI INTERFACE DISABLE
return (char) x;
}
void CC1101_Write(char address,char data) // writes to a register at an address specified
{
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0x00); // CS FOR SPI INTERFACE ENABLE
while(SSIBusy(SSI1_BASE)==1);// Wait for TXBUF ready
SSIDataPut(SSI1_BASE, address );
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, data ); // Send data
while(SSIBusy(SSI1_BASE)==1); // Wait for TX complete
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0xFF); // CS FOR SPI INTERFACE DISABLE
}
char CC1101_Read(char address) // reads from a register at an address specified
{
unsigned long x = 0;
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0x00); // CS FOR SPI INTERFACE ENABLE
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, address| 0x80);// Send address
while(SSIBusy(SSI1_BASE)==1); // Wait for TXBUF ready
SSIDataPut(SSI1_BASE, 0x00 ); // Dummy write so we can read data
while(SSIBusy(SSI1_BASE)==1); // Wait for TX complete
SSIDataGet(SSI1_BASE,&x); // Read data
GPIOPinWrite(GPIO_PORTH_BASE, GPIO_PIN_5,0xFF); // CS FOR SPI INTERFACE DISABLE
return (char) x;
}
//////////////////////////////////////////////////RF SPI FUNCTIONS FILE END/////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////START UP EWARM FILE BEGIN/////////////////////////////////////////////////////////////////
//*****************************************************************************
//
// startup_ewarm.c - Startup code for use with IAR's Embedded Workbench,
// version 5.
//
// Copyright (c) 2009-2012 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 9107 of the EK-LM3S9B92 Firmware Package.
//
//*****************************************************************************
//*****************************************************************************
//
// Enable the IAR extensions for this source file.
//
//*****************************************************************************
#pragma language=extended
//*****************************************************************************
//
// Forward declaration of the default fault handlers.
//
//*****************************************************************************
void ResetISR(void);
static void NmiSR(void);
static void FaultISR(void);
static void IntDefaultHandler(void);
//*****************************************************************************
//
// The entry point for the application startup code.
//
//*****************************************************************************
extern void __iar_program_start(void);
extern void PortHIntHandler(void);
//*****************************************************************************
//
// Reserve space for the system stack.
//
//*****************************************************************************
static unsigned long pulStack[64] @ ".noinit";
//*****************************************************************************
//
// A union that describes the entries of the vector table. The union is needed
// since the first entry is the stack pointer and the remainder are function
// pointers.
//
//*****************************************************************************
typedef union
{
void (*pfnHandler)(void);
unsigned long ulPtr;
}
uVectorEntry;
//*****************************************************************************
//
// The vector table. Note that the proper constructs must be placed on this to
// ensure that it ends up at physical address 0x0000.0000.
//
//*****************************************************************************
__root const uVectorEntry __vector_table[] @ ".intvec" =
{
{ .ulPtr = (unsigned long)pulStack + sizeof(pulStack) },
// The initial stack pointer
ResetISR, // The reset handler
NmiSR, // The NMI handler
FaultISR, // The hard fault handler
IntDefaultHandler, // The MPU fault handler
IntDefaultHandler, // The bus fault handler
IntDefaultHandler, // The usage fault handler
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
IntDefaultHandler, // SVCall handler
IntDefaultHandler, // Debug monitor handler
0, // Reserved
IntDefaultHandler, // The PendSV handler
IntDefaultHandler, // The SysTick handler
IntDefaultHandler, // GPIO Port A
IntDefaultHandler, // GPIO Port B
IntDefaultHandler, // GPIO Port C
IntDefaultHandler, // GPIO Port D
IntDefaultHandler, // GPIO Port E
IntDefaultHandler, // UART0 Rx and Tx
IntDefaultHandler, // UART1 Rx and Tx
IntDefaultHandler, // SSI0 Rx and Tx
IntDefaultHandler, // I2C0 Master and Slave
IntDefaultHandler, // PWM Fault
IntDefaultHandler, // PWM Generator 0
IntDefaultHandler, // PWM Generator 1
IntDefaultHandler, // PWM Generator 2
IntDefaultHandler, // Quadrature Encoder 0
IntDefaultHandler, // ADC Sequence 0
IntDefaultHandler, // ADC Sequence 1
IntDefaultHandler, // ADC Sequence 2
IntDefaultHandler, // ADC Sequence 3
IntDefaultHandler, // Watchdog timer
IntDefaultHandler, // Timer 0 subtimer A
IntDefaultHandler, // Timer 0 subtimer B
IntDefaultHandler, // Timer 1 subtimer A
IntDefaultHandler, // Timer 1 subtimer B
IntDefaultHandler, // Timer 2 subtimer A
IntDefaultHandler, // Timer 2 subtimer B
IntDefaultHandler, // Analog Comparator 0
IntDefaultHandler, // Analog Comparator 1
IntDefaultHandler, // Analog Comparator 2
IntDefaultHandler, // System Control (PLL, OSC, BO)
IntDefaultHandler, // FLASH Control
IntDefaultHandler, // GPIO Port F
IntDefaultHandler, // GPIO Port G
PortHIntHandler, // GPIO Port H
IntDefaultHandler, // UART2 Rx and Tx
IntDefaultHandler, // SSI1 Rx and Tx
IntDefaultHandler, // Timer 3 subtimer A
IntDefaultHandler, // Timer 3 subtimer B
IntDefaultHandler, // I2C1 Master and Slave
IntDefaultHandler, // Quadrature Encoder 1
IntDefaultHandler, // CAN0
IntDefaultHandler, // CAN1
IntDefaultHandler, // CAN2
IntDefaultHandler, // Ethernet
IntDefaultHandler, // Hibernate
IntDefaultHandler, // USB0
IntDefaultHandler, // PWM Generator 3
IntDefaultHandler, // uDMA Software Transfer
IntDefaultHandler, // uDMA Error
IntDefaultHandler, // ADC1 Sequence 0
IntDefaultHandler, // ADC1 Sequence 1
IntDefaultHandler, // ADC1 Sequence 2
IntDefaultHandler, // ADC1 Sequence 3
IntDefaultHandler, // I2S0
IntDefaultHandler, // External Bus Interface 0
IntDefaultHandler // GPIO Port J
};
//*****************************************************************************
//
// This is the code that gets called when the processor first starts execution
// following a reset event. Only the absolutely necessary set is performed,
// after which the application supplied entry() routine is called. Any fancy
// actions (such as making decisions based on the reset cause register, and
// resetting the bits in that register) are left solely in the hands of the
// application.
//
//*****************************************************************************
void
ResetISR(void)
{
//
// Call the application's entry point.
//
__iar_program_start();
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives a NMI. This
// simply enters an infinite loop, preserving the system state for examination
// by a debugger.
//
//*****************************************************************************
static void
NmiSR(void)
{
//
// Enter an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives a fault
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
FaultISR(void)
{
//
// Enter an infinite loop.
//
while(1)
{
}
}
//*****************************************************************************
//
// This is the code that gets called when the processor receives an unexpected
// interrupt. This simply enters an infinite loop, preserving the system state
// for examination by a debugger.
//
//*****************************************************************************
static void
IntDefaultHandler(void)
{
//
// Go into an infinite loop.
//
while(1)
{
}
}
//////////////////////////////////////////////////START UP EWARM FILE END/////////////////////////////////////////////////////////////////