@Harshad Italiya • 25 Mar, 2011 • 3 likes
DIY: - Do It Yourself


Wireless Data Transmission
Wireless Chat using RFM70


RFM70 is a GFSK transceiver module operating in the world wide ISM frequency band at 2400 - 2483.5 MHz. Burst mode transmission and up to 2Mbps air data rate make them suitable for applications requiring ultra low power consumption.

The embedded packet processing engines enable their full operation with a very simple MCU as a radio system. Auto re-transmission and auto acknowledge give reliable link without any MCU interference.

Block Diagram:-

Block diagram
[FONT=&amp]
[/FONT]


This is the basic Block Diagram for the project in which you have to catch the data from any device or you can use Personal Computer or Laptop to send the data for that you need to interface the Computer with the project board and here it is Serial Communication as now a days serial port are not available on Laptop you can also use USB to Serial cable and that data is given to the Microcontroller.

For the communication between Microcontroller and RFM70 module you have to use SPI protocol many controller gives the Hardware SPI but in this project we are going to use Software SPI.

Data which is received by the Microcontroller is now transffered to the RFM70 and RFM70 transmit that data in RF.

This is all about the Transmitter and for the Receiver it will do the same procedure but in reverse order first RFM70 Module collects the Data from RF and then on the request from Microcontroller via SPI Command it gives the received data to Microcontroller and the same data now also available on the other Computer or Laptop.

Interfacing PC with Microcontroller
To interface PC with microcontroller you have to use the MAX232 or any equivalent IC have a look at Post # 2 for the other details.

Here is the Circuit Diagram for the same.
max232

Microcontroller Section


[​IMG]
This is the Circuit Section for Microcontroller Here I have used Freescale Microcontroller but you can use any Microcontroller. Now if you see that there is Name given to every Pin which shows that pin's Connection.
Now as we are going to interface controller with MAX232 and RFM70 there are CE,CSN,SCK,MOSI,MISO and IRQ signals are used to communicate with RF Module and RXD,TXD to communicate with Serial Port of PC.

Now Before we start SPI Communication with RF Module you must have knowledge of SPI. for that again refer Post # 2 for Some basic Information about SPI.

Note:- Remember as the RF module is working on 3.3Volt you must have to choose MCU which is working on 3.3 Volt. Here MCU_SUP is 3.3Volt
RFM70 Connection

[​IMG]
This is the connection detail for RFM70. Now we have to make a software which communicate with RFM70 using microcontroller. For More information about RFM70 and its internal register please refer datasheet.
@Harshad Italiya • 25 Mar, 2011 Re: DIY :- Wireless Chat Using

Important Link for your Study

1) USB to Serial Cable
2) Freescale Microcontroller MC9S08SG8 or IB4 or Any Other Controller or SG Series Overview
3) RF Module RFM70 from HopeRF or Datasheet of RFM70
4) SPI --
Must Read this one its very important for Communication between Controller and RF Module
5) MAX232 Datasheet
@Harshad Italiya • 25 Mar, 2011 Re: DIY :- Wireless Chat Using

Reserved.............
@Harshad Italiya • 26 Mar, 2011 Guys if you have any doubt in this Block diagram then please shoot your questions.
@narayana murthy • 26 Mar, 2011 nice project buddy
@Harshad Italiya • 26 Mar, 2011
narayana murthy
nice project buddy
Thanks NM.
@Harshad Italiya • 30 Mar, 2011 Should i go ahead? I think people are not interested in RF project.
Ok lets See. 😔
@Harshad Italiya • 01 Apr, 2011 Updated the Serial Communication circuit. please have a look.
@yanivx • 02 Apr, 2011 ok lets start godfather...... but let me sum up my final year project bro its an awesome project go ahead and if u are determined you will surely succeed All the best!!! God bless us all
Regards Yanivx
https://yanivx.wordpress.com
@Harshad Italiya • 02 Apr, 2011
yanivx
ok lets start godfather...... but let me sum up my final year project bro its an awesome project go ahead and if u are determined you will surely succeed All the best!!! God bless us all
Regards Yanivx
https://yanivx.wordpress.com
I have already developed this project this is for the Ceans who want to do something by themselves.
@narayana murthy • 02 Apr, 2011
godfather
I have already developed this project this is for the Ceans who want to do something by themselves.
hey gf i had a doubt
how much distance is it working
i mean how much distance we can use it
@Harshad Italiya • 02 Apr, 2011
narayana murthy
hey gf i had a doubt
how much distance is it working
i mean how much distance we can use it
It will give 30 Meter but mostly depends on the environment you use. but you can easily cover a HOME with this.
@narayana murthy • 02 Apr, 2011
godfather
It will give 30 Meter but mostly depends on the environment you use. but you can easily cover a HOME with this.
thanks brother i think this may useful to me
@Harshad Italiya • 02 Apr, 2011
narayana murthy
thanks brother i think this may useful to me
Sure you can use it. 😀
@narayana murthy • 02 Apr, 2011
godfather
Sure you can use it. 😀
but i think this is very useful for the sending only personal information because for just 30m we can use mikes lol
just kidding anyway good project but is it in compact size
@Harshad Italiya • 02 Apr, 2011
narayana murthy
but i think this is very useful for the sending only personal information because for just 30m we can use mikes lol
just kidding anyway good project but is it in compact size
This is not only application i choose this because this will make interest in people there are lot of other application based on the same.

yes you can compact it use the SMD component. 😉
@Harshad Italiya • 07 Apr, 2011 One of my friend is also working on small GUI for this Chat. 😁
@prathap07 • 06 May, 2011 hi,
it's really glad to see this project....it's too nice...hey and even we too are working on rfm70 for our project...we got few doubts...
1. Some where i read that using RFM70 in wi-fi zone will hinder the performance..is it so?
2. How to access the data in Rx FIFO register.
@Harshad Italiya • 06 May, 2011 @Prathap~

Its my pleasure if you really want to do this project by yourself i am sure you will get good knowledge too.

Well For your Answer:-

1) I think it will not effect the functionality of RFM70 as the address for the WIFI and RF devices are different i have tested it in company and at time we are using WIFI MODEM but it was working good so i don't think it might cause problem.
2) To access RX FIFO from RFM70 module, If you have reference code of that Module then you will find a function Receive_packate after that function the data is available in RX_FIFO and via SPI you can read it. 😀

PS:- Guys i am not sure much about the first thing if anyone knows please pour your knowledge.
@yanivx • 20 Jul, 2011 ok am here will be soon woking on this project have written down the components and will bring it by the coming week....
@Harshad Italiya • 28 Jul, 2011
yanivx
ok am here will be soon woking on this project have written down the components and will bring it by the coming week....
Good Yanivx,
Let me know if you have any difficulty in finding Components. I will make your process fast. 😀
@Harshad Italiya • 08 Sep, 2011 I have updated the First Post. Controller section is added and also the connection which will be useful for RF module connectivity.
@Harshad Italiya • 13 Sep, 2011 Post is updated with RFM70 Connector next step will be of writing software. please refer datasheet before you go through software section.
@tai86 • 15 Sep, 2011 I am trying to use RFM70 module but the software interface is gone me crazy...😕
@Harshad Italiya • 15 Sep, 2011
tai86
I am trying to use RFM70 module but the software interface is gone me crazy...😕
So do you have ready Hardware? Can you post it here?
@tai86 • 16 Sep, 2011
godfather
So do you have ready Hardware? Can you post it here?
Sorry, but I have only breadboard minimal hardware setting for testing the RFM70 capabilities...I'm woking with PIC18F, implementing the sample software provided by RFM70's manufacturer...

Unforntunately this not working fine as it should : the packets are transmitted but never received! 😔
@Harshad Italiya • 16 Sep, 2011
tai86
Sorry, but I have only breadboard minimal hardware setting for testing the RFM70 capabilities...I'm woking with PIC18F, implementing the sample software provided by RFM70's manufacturer...

Unforntunately this not working fine as it should : the packets are transmitted but never received! 😔
You are using same code, It should be work please check your hardware again.
@tai86 • 16 Sep, 2011 Could you post your code? I have modified the orignal code (for PIC16) to run on PIC18...
Which uC are you using?
@Harshad Italiya • 16 Sep, 2011
tai86
Could you post your code? I have modified the orignal code (for PIC16) to run on PIC18...
Which uC are you using?
I have used ATMEL and Freescale. You can try with the code given on site.
@tai86 • 16 Sep, 2011 I have try https://www.hoperf.com/upload/rf/RFM70_receiver_code.zip and https://www.hoperf.com/upload/rf/RFM70_transmiter_code.zip
but only RED_LED on tx blink at 1Hz...GREEN_LED on rx/tx (receive packets) never blink! I don't know what to do to understand what is the main issue...
@Harshad Italiya • 16 Sep, 2011
tai86
I have try https://www.hoperf.com/upload/rf/RFM70_receiver_code.zip and https://www.hoperf.com/upload/rf/RFM70_transmiter_code.zip
but only RED_LED on tx blink at 1Hz...GREEN_LED on rx/tx (receive packets) never blink! I don't know what to do to understand what is the main issue...
If you have used that code without any changes then it should work. as i too tested same code. even you can check your SPI first by reading any register. if it works then you can debug.

Do you have Debugger for PIC?
@tai86 • 17 Sep, 2011
godfather
If you have used that code without any changes then it should work. as i too tested same code. even you can check your SPI first by reading any register. if it works then you can debug.

Do you have Debugger for PIC?
I use the original code with minimal correction for running it on PIC18F...I have ICD2 Clone prog/debug setup : RFM70 run at 3.3v and is not possible to debug at this voltage supply...damn it!

Now, I'm trying to read a generic register...
@tai86 • 17 Sep, 2011
guptssumeet482
Good project pal.
I saw some good pictures and its working onthis site...

Wireless Data Transmission using RFM70
Unfortunately there are only prototype board photos about Wireless Data Transmission using RFM70...no schematic, no code...😕
@Harshad Italiya • 17 Sep, 2011
tai86
I use the original code with minimal correction for running it on PIC18F...I have ICD2 Clone prog/debug setup : RFM70 run at 3.3v and is not possible to debug at this voltage supply...damn it!

Now, I'm trying to read a generic register...
Try to read some register and blink LED according to that. so you come to know that your SPI is working or not. Let me know if still you have any doubt.
@tai86 • 19 Sep, 2011
godfather
Try to read some register and blink LED according to that. so you come to know that your SPI is working or not. Let me know if still you have any doubt.
I read the 01 register and I find 0x3F agreed with RFM70's datasheet...So SPI_Read_Reg() is working!! 😁

Then I try to display the variable "sta=SPI_Read_Reg(STATUS);" in function "Receive_Packet()" and the returned value is 0x0E (not depending on tx module on/off)...what is meaning of STATUS = 0x0E? 😕
@Harshad Italiya • 19 Sep, 2011
tai86
I read the 01 register and I find 0x3F agreed with RFM70's datasheet...So SPI_Read_Reg() is working!! 😁

Then I try to display the variable "sta=SPI_Read_Reg(STATUS);" in function "Receive_Packet()" and the returned value is 0x0E (not depending on tx module on/off)...what is meaning of STATUS = 0x0E? 😕
That is status register and in that one bit is set and reset according to reception.

now try and check this condition
if((STATUS_RX_DR&sta) == 0x40) // if receive data ready (RX_DR) interrupt
becomes TRUE or not? If this condition becomes true when you receive perfect data then you can read length of the bytes received.

Yes one more important thing. Have you Swapped address RX0_Address and Tx_address ?
@tai86 • 20 Sep, 2011
godfather
now try and check this condition becomes TRUE or not? If this condition becomes true when you receive perfect data then you can read length of the bytes received.
The condition never becomes true because sta = 0x0E and STATUS_RX_DR&sta = 0x40 & 0x0E = 0

godfather
Yes one more important thing. Have you Swapped address RX0_Address and Tx_address ?
??? Swapping address...what do you mean? 😀 Maybe could it be THE problem!
@Harshad Italiya • 20 Sep, 2011
tai86
The condition never becomes true because sta = 0x0E and STATUS_RX_DR&sta = 0x40 & 0x0E = 0



??? Swapping address...what do you mean? 😀 Maybe could it be THE problem!
Yes that is the problem.
Here is small example

for Transmitter
Tx_Address = 0x01;
RX0_address = 0x02;

then for Receiver you have to swap these two
Tx_Address = 0x02;
RX0_address = 0x01;

Please give it a try and let me know.
@tai86 • 20 Sep, 2011
godfather
for Transmitter
Tx_Address = 0x01;
RX0_address = 0x02;

then for Receiver you have to swap these two
Tx_Address = 0x02;
RX0_address = 0x01;
You may be right BUT in the RFM70's example codes Tx_Address = RX0_Address = {0x34,0x43,0x10,0x10,0x01} and RX1_Address = {0x39,0x38,0x37,0x36,0xc2} for both receiver and transmitter...why? 😐

Could you send me or publish your code? Thank you
@Harshad Italiya • 20 Sep, 2011
//Bank1 register initialization value

//In the array RegArrFSKAnalog,all the register value is the byte reversed!!!!!!!!!!!!!!!!!!!!!
const unsigned long Bank1_Reg0_13[]={ //latest config txt
0xE2014B40,
0x00004BC0,
0x028CFCD0,
0x41390099,
0x0B869Ef9,
0xA67F0624,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00127300,
0x36B48000,
};

const UINT8 Bank1_Reg14[]=
{
0x41,0x20,0x08,0x04,0x81,0x20,0xCF,0xF7,0xFE,0xFF,0xFF
};

//Bank0 register initialization value
const UINT8 Bank0_Reg[][2]={
{0,0x0F},//reflect RX_DR\TX_DS\MAX_RT,Enable CRC ,2byte,POWER UP,PRX
{1,0x3F},//Enable auto acknowledgement data pipe5\4\3\2\1\0
{2,0x3F},//Enable RX Addresses pipe5\4\3\2\1\0
{3,0x03},//RX/TX address field width 5byte
{4,0xff},//auto retransmission dalay (4000us),auto retransmission count(15)
{5,0x17},//23 channel
{6,0x1f/*0x17*/},//air data rate-1M,out power 5dbm,setup LNA gain
{7,0x07},//
{8,0x00},//
{9,0x00},
{12,0xc3},//only LSB Receive address data pipe 2, MSB bytes is equal to RX_ADDR_P1[39:8]
{13,0xc4},//only LSB Receive address data pipe 3, MSB bytes is equal to RX_ADDR_P1[39:8]
{14,0xc5},//only LSB Receive address data pipe 4, MSB bytes is equal to RX_ADDR_P1[39:8]
{15,0xc6},//only LSB Receive address data pipe 5, MSB bytes is equal to RX_ADDR_P1[39:8]
{17,0x20},//Number of bytes in RX payload in data pipe0(32 byte)
{18,0x20},//Number of bytes in RX payload in data pipe1(32 byte)
{19,0x20},//Number of bytes in RX payload in data pipe2(32 byte)
{20,0x20},//Number of bytes in RX payload in data pipe3(32 byte)
{21,0x20},//Number of bytes in RX payload in data pipe4(32 byte)
{22,0x20},//Number of bytes in RX payload in data pipe5(32 byte)
{23,0x00},//fifo status
{28,0x3F},//Enable dynamic payload length data pipe5\4\3\2\1\0
{29,0x07}//Enables Dynamic Payload Length,Enables Payload with ACK,Enables the W_TX_PAYLOAD_NOACK command
};


const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x02};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0xc2};////Receive address data pipe 1

UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x01}; // Transmitter Address.

extern UINT8 test_data;
extern UINT8 channel;
extern UINT8 power;
extern UINT8 data_rate;
extern UINT8 rx_buf[MAX_PACKET_LEN];


extern void delay_200ms(void);
extern void delay_50ms(void);
///////////////////////////////////////////////////////////////////////////////
// SPI access //
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
// Function: SPI_RW();
//
//Description:
// Writes one UINT8 to RFM70, and return the UINT8 read
//////////////////////////////////////////////////////////

UINT8 SPI_RW(UINT8 value)
{
UINT8 bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
{
if(value & 0x80)
{
MOSI = 1;
}
else
{
MOSI=0;
}
value = (value << 1); // shift next bit into MSB..
SCK = 1; // Set SCK high..
// asm(nop);
value |= MISO; // capture current MISO bit
SCK = 0; // ..then set SCK low again
}
return(value); // return read UINT8
}

//**************************************************
//Function: SPI_Write_Reg();
//
//Description:
// Writes value 'value' to register 'reg'
//**************************************************/
void SPI_Write_Reg(UINT8 reg, UINT8 value) //--unsigned int UINT8
{
CSN = 0; // CSN low, init SPI transaction
op_status = SPI_RW(reg); // select register
op_status = SPI_RW(value); // ..and write value to it..
CSN = 1; // CSN high again
}


//**************************************************/

//**************************************************
//Function: SPI_Read_Reg();
//
//Description:
// Read one UINT8 from BK2421 register, 'reg'
//**************************************************/
UINT8 SPI_Read_Reg(UINT8 reg)
{

UINT8 value;
CSN = 0; // CSN low, initialize SPI communication...
op_status=SPI_RW(reg); // Select register to read from..
value = SPI_RW(0); // ..then read register value
CSN = 1; // CSN high, terminate SPI communication
asm(NOP);
return(value); // return register value
}
//**************************************************/

//**************************************************
//Function: SPI_Read_Buf();
//
//Description:
// Reads 'length' #of length from register 'reg'
//**************************************************/
void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 status,byte_ctr;

CSN = 0; // Set CSN l
status = SPI_RW(reg); // Select register to write, and read status UINT8

for(byte_ctr=0;byte_ctr<length;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); // Perform SPI_RW to read UINT8 from RFM70

CSN = 1; // Set CSN high again

}
//**************************************************/

//**************************************************
//Function: SPI_Write_Buf();
//
//Description:
// Writes contents of buffer '*pBuf' to RFM70
//**************************************************/
void SPI_Write_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 byte_ctr;

CSN = 0; // Set CSN low, init SPI tranaction
op_status = SPI_RW(reg); // Select register to write to and read status UINT8
for(byte_ctr=0; byte_ctr<length; byte_ctr++) // then write all UINT8 in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again

}
//**************************************************
//Function: SwitchToRxMode();
//Description:
// switch to Rx mode
//**************************************************/
void SwitchToRxMode()
{
UINT8 value;

SPI_Write_Reg(FLUSH_RX,0);//flush Rx

value=SPI_Read_Reg(STATUS); // read register STATUS's value
SPI_Write_Reg(WRITE_REG|STATUS,value);// clear RX_DR or TX_DS or MAX_RT interrupt flag

CE=0;

value=SPI_Read_Reg(CONFIG); // read register CONFIG's value
test = value;

//PRX
value=value|0x01;//set bit 1
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled..
CE=1;
}

//**************************************************
//Function: SwitchToTxMode();
//Description:
// switch to Tx mode
///**************************************************/
void SwitchToTxMode()
{
UINT8 value;
SPI_Write_Reg(FLUSH_TX,0);//flush Tx

CE=0;
value=SPI_Read_Reg(CONFIG); // read register CONFIG's value
//PTX
value=value&0xfe; //set bit 0
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled.

CE=1;
}

//**************************************************
//Function: SwitchCFG();
//
//Description:
// access switch between Bank1 and Bank0

///Parameter:
// _cfg 1:register bank1
// 0:register bank0
//Return:
// None
//**************************************************/
void SwitchCFG(char _cfg)//1:Bank1 0:Bank0
{
UINT8 Tmp;

Tmp=SPI_Read_Reg(7);
Tmp=Tmp&0x80;

if( ( (Tmp)&&(_cfg==0) )
||( ((Tmp)==0)&&(_cfg) ) )
{
SPI_Write_Reg(ACTIVATE_CMD,0x53);
}
}

///**************************************************
//Function: SetChannelNum();
//Description:
// set channel number
//
//**************************************************/
void SetChannelNum(UINT8 ch)
{
SPI_Write_Reg((UINT8)(WRITE_REG|5),(UINT8)(ch));
}



///////////////////////////////////////////////////////////////////////////////
// RFM70 initialization //
///////////////////////////////////////////////////////////////////////////////
//**************************************************
//Function: RFM70_Initialize();
///
//Description:
// register initialization
//**************************************************/
void RFM70_Initialize()
{
UINT8 i,j;
// UINT8 temp;
UINT8 WriteArr[12];

//DelayMs(100);//delay more than 50ms.
delay_200ms();

SwitchCFG(0);

for(i=0;i<20;i++)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
}

for(j=0;j<5;j++)
{
WriteArr[j]=RX0_Address[j];
}
SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);

//REG 11 - Rx1 addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX1_Address[j];
}
SPI_Write_Buf((WRITE_REG|11),&(WriteArr[0]),5);

//REG 16 - TX addr
for(j=0;j<5;j++)
{
WriteArr[j]=Tx_address[j];
}
SPI_Write_Buf((WRITE_REG|16),&(WriteArr[0]),5);

// printf("\nEnd Load Reg");

i=SPI_Read_Reg(29);//read Feature Register Èç¹ûÒªÖ§³Ö¶¯Ì¬³¤¶È»òÕß Payload With ACK£¬ÐèÒªÏȸøоƬ·¢ËÍ ACTIVATEÃüÁÊý¾ÝΪ0x73),È»ºóʹÄܶ¯Ì¬³¤¶È»òÕß Payload With ACK (REG28,REG29).

if(i==0) // i!=0 showed that chip has been actived.so do not active again.
SPI_Write_Reg(ACTIVATE_CMD,0x73);// Active

for(i=22;i>=21;i--)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
//SPI_Write_Reg_Bank0(Bank0_Reg[0],Bank0_Reg[1]);
}

//********************Write Bank1 register******************
SwitchCFG(1);

for(i=0;i<=8;i++)//reverse
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

for(i=9;i<=13;i++)
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(3-j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

//SPI_Write_Buf((WRITE_REG|14),&(Bank1_Reg14[0]),11);
for(j=0;j<11;j++)
{
WriteArr[j]=Bank1_Reg14[j];
}
SPI_Write_Buf((WRITE_REG|14),&(WriteArr[0]),11);

//toggle REG4<25,26>
for(j=0;j<4;j++)
//WriteArr[j]=(RegArrFSKAnalog[4]>>(8*(j) ) )&0xff;
WriteArr[j]=(Bank1_Reg0_13[4]>>(8*(j) ) )&0xff;

WriteArr[0]=WriteArr[0]|0x06;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

WriteArr[0]=WriteArr[0]&0xf9;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

//**************************Test spi*****************************//
//SPI_Write_Reg((WRITE_REG|Bank0_Reg[2][0]),0x0f);
//test_data = SPI_Read_Reg(0x02);


//DelayMs(10);
delay_50ms();

//********************switch back to Bank0 register access******************
SwitchCFG(0);
SwitchToRxMode();//switch to RX mode

//------------------------- Code to check SPI--------------------------------
test = SPI_Read_Reg(EN_AA);
delay_50ms();
if(test != 0x3f)
{
serialsend("Communication Error!!",21);
serialsend("\r\n",1);

while(1)
{
LED0 = ~ LED0;
delay_50ms();
delay_5ms();
delay_5ms();
}
}
//---------------------------------------------------------------------------
}



You have to swap address of RED marked Address only.
@tai86 • 21 Sep, 2011 Finally I find the issue!!! 😁
The MISO pin of RFM70 module on tx was fault...changed the module and ALL WORKS GREAT!
Thank you godfather! 😁
@Harshad Italiya • 24 Sep, 2011
tai86
Finally I find the issue!!! 😁
The MISO pin of RFM70 module on tx was fault...changed the module and ALL WORKS GREAT!
Thank you godfather! 😁
You are most welcome.
Do share Project video if possible. 😀
@parth 127 • 24 Sep, 2011 nice project buddy
@nakres • 22 Oct, 2011 I edit RFM70 code for MSP430. But i have the same error like tai86.
I read 0x0e as status register. I write something to bank0 registers
and when i read back from the same register i can not have the same
value that i wrote (I think i can not reach the registers). I check
the hardware several times. The code is in the attachment. Iwill be
please to discuss about...

PS : When i debug i can stop on line 547 with a breakpoint



Source Code :

#include "msp430x26x.h" // Line 1
// Line 2
/********************** Preprocessor Definitions ******************/
#define TRUE 1
#define FALSE 0

#define INT8 char
#define INT16 int
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long

#define CE_Out SetBit(P3DIR,4)
#define Clr_CE ClrBit(P3OUT,4)
#define Set_CE SetBit(P3OUT,4)

#define CSN_Out SetBit(P3DIR,0)
#define Clr_CSN ClrBit(P3OUT,0)
#define Set_CSN SetBit(P3OUT,0)

#define IRQ_In SetBit(P3DIR,5)
#define IRQ (P3IN&0x20)

#define MAX_PACKET_LEN 32// max value is 32

#define ClrBit(Reg,Bit) (Reg&=((1<<Bit)^0xFF))
#define SetBit(Reg,Bit) (Reg|=(1<<Bit))
#define TogBit(Reg,Bit) (Reg = Reg^1<<Bit)

//************************FSK COMMAND and REGISTER****************************************//
// SPI(RFM70) commands
#define READ_REG 0x00 // Define read command to register
#define WRITE_REG 0x20 // Define write command to register
#define RD_RX_PLOAD 0x61 // Define RX payload register address
#define WR_TX_PLOAD 0xA0 // Define TX payload register address
#define FLUSH_TX 0xE1 // Define flush TX register command
#define FLUSH_RX 0xE2 // Define flush RX register command
#define REUSE_TX_PL 0xE3 // Define reuse TX payload register command
#define W_TX_PAYLOAD_NOACK_CMD 0xb0
#define W_ACK_PAYLOAD_CMD 0xa8
#define ACTIVATE_CMD 0x50
#define R_RX_PL_WID_CMD 0x60
#define NOP_NOP 0xFF // Define No Operation, might be used to read status register

// SPI(RFM70) registers(addresses)
#define CONFIG 0x00 // 'Config' register address
#define EN_AA 0x01 // 'Enable Auto Acknowledgment' register address
#define EN_RXADDR 0x02 // 'Enabled RX addresses' register address
#define SETUP_AW 0x03 // 'Setup address width' register address
#define SETUP_RETR 0x04 // 'Setup Auto. Retrans' register address
#define RF_CH 0x05 // 'RF channel' register address
#define RF_SETUP 0x06 // 'RF setup' register address
#define STATUS 0x07 // 'Status' register address
#define OBSERVE_TX 0x08 // 'Observe TX' register address
#define CD 0x09 // 'Carrier Detect' register address
#define RX_ADDR_P0 0x0A // 'RX address pipe0' register address
#define RX_ADDR_P1 0x0B // 'RX address pipe1' register address
#define RX_ADDR_P2 0x0C // 'RX address pipe2' register address
#define RX_ADDR_P3 0x0D // 'RX address pipe3' register address
#define RX_ADDR_P4 0x0E // 'RX address pipe4' register address
#define RX_ADDR_P5 0x0F // 'RX address pipe5' register address
#define TX_ADDR 0x10 // 'TX address' register address
#define RX_PW_P0 0x11 // 'RX payload width, pipe0' register address
#define RX_PW_P1 0x12 // 'RX payload width, pipe1' register address
#define RX_PW_P2 0x13 // 'RX payload width, pipe2' register address
#define RX_PW_P3 0x14 // 'RX payload width, pipe3' register address
#define RX_PW_P4 0x15 // 'RX payload width, pipe4' register address
#define RX_PW_P5 0x16 // 'RX payload width, pipe5' register address
#define FIFO_STATUS 0x17 // 'FIFO Status Register' register address
#define PAYLOAD_WIDTH 0x1f // 'payload length of 256 bytes modes register address

//interrupt status
#define STATUS_RX_DR 0x40
#define STATUS_TX_DS 0x20
#define STATUS_MAX_RT 0x10

#define STATUS_TX_FULL 0x01

//FIFO_STATUS
#define FIFO_STATUS_TX_REUSE 0x40
#define FIFO_STATUS_TX_FULL 0x20
#define FIFO_STATUS_TX_EMPTY 0x10

#define FIFO_STATUS_RX_FULL 0x02
#define FIFO_STATUS_RX_EMPTY 0x01


typedef struct {
unsigned char reach_1s : 1;
unsigned char reach_5hz : 1;
} FlagType;

unsigned long us_counter; // for delay functions
UINT8 op_status;

//Bank1 register initialization value

//In the array RegArrFSKAnalog,all the register value is the byte reversed!!!!!!!!!!!!!!!!!!!!!
const unsigned long Bank1_Reg0_13[]={ //latest config txt
0xE2014B40,
0x00004BC0,
0x028CFCD0,
0x41390099,
0x0B869Ef9,
0xA67F0624,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00127300,
0x36B48000,
};

const UINT8 Bank1_Reg14[]=
{
0x41,0x20,0x08,0x04,0x81,0x20,0xCF,0xF7,0xFE,0xFF,0xFF
};

//Bank0 register initialization value
const UINT8 Bank0_Reg[][2]={
{0,0x0F},
{1,0x3F},
{2,0x3F},
{3,0x03},
{4,0xff},
{5,0x17},
{6,0x17},
{7,0x07},
{8,0x00},
{9,0x00},
{12,0xc3},
{13,0xc4},
{14,0xc5},
{15,0xc6},
{17,0x20},
{18,0x20},
{19,0x20},
{20,0x20},
{21,0x20},
{22,0x20},
{23,0x00},
{28,0x3F},
{29,0x07}
};

//const UINT8 TX_Address[]={0x34,0x43,0x10,0x10,0x01};//For device PRX
//const UINT8 RX0_Address[]={0x34,0x43,0x10,0x10,0x02};//For device PRX
//const UINT8 TX_Address[]={0x34,0x43,0x10,0x10,0x02};//For device PTX
//const UINT8 RX0_Address[]={0x34,0x43,0x10,0x10,0x01};//For device PTX

const UINT8 RX0_Address[]={0x34,0x43,0x10,0x10,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x39,0x38,0x37,0x36,0xc2};////Receive address data pipe 1
const UINT8 tx_buf[17]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x78};
UINT8 rx_buf[MAX_PACKET_LEN];
UINT8 count_50hz;
FlagType Flag;

void BoardInit(void);

/************************ Timer Functions **********************/
void TimerAInit();
void TimerBInit(const unsigned periodPulse);

/********************** SPI Functions *************************/
void spi_init(void);
void spi_write(UINT8 spi_data);
UINT8 spi_read(void);

/************************* RF Functions ************************/
UINT8 SPI_RW(UINT8 value);
void SPI_Write_Reg(UINT8 reg, UINT8 value);
UINT8 SPI_Read_Reg(UINT8 reg);
void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length);
void SPI_Write_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length);
void SwitchToRxMode(void);
void SwitchToTxMode(void);
void SwitchCFG(char _cfg); //1:Bank1 0:Bank0
void SetChannelNum(UINT8 ch);
void RFM70_Initialize(void);
void sub_program_1hz(void);
void Send_Packet(UINT8 type,UINT8* pbuf,UINT8 len);
void Receive_Packet(void);

/******************** Delay Functions *************************/
void delay_200ms(void);
void delay_50ms(void);
void delay_5ms(void);
void delay_20us(void);
void delay_1ms(void);
void DelayMs(unsigned ms);

void main(void)
{
BoardInit();

while(1)
{
sub_program_1hz();
Receive_Packet();
}
}

void BoardInit(void)
{
WDTCTL = WDTTMSEL + WDTPW + WDTHOLD;

if (CALBC1_8MHZ ==0xFF || CALDCO_8MHZ == 0xFF)
{
while(1); // If calibration constants erased // do not load, trap CPU!!
}

BCSCTL1 = CALBC1_8MHZ; // Set DCO
DCOCTL = CALDCO_8MHZ; // Set DCO to 8MHz

SetBit(P3DIR,7); // Led
SetBit(P3OUT,7); // Turn off the led

spi_init();
TimerAInit(); // For delay functions
TimerBInit(20000); // ~20ms for 50 Hz

__bis_SR_register(GIE);

count_50hz = 0;
Flag.reach_1s = 0;

RFM70_Initialize();
}

/************************ Timer Functions **********************/

void TimerAInit()
{
TACTL |= TACLR; /* Set the TACLR - Reset the timer */


TACTL = 0x0; /* Clear all settings */

TACCR0 = 20; // ~20us
TACTL = TASSEL_2 + MC_1 + ID_3 + TAIE; // SMCLK, /8
}

void TimerBInit(const unsigned periodPulse)
{
TBCTL |= TBCLR; /* Set the TACLR - Reset the timer */


TBCTL = 0x0; /* Clear all settings */

TBCCR0 = periodPulse; //
TBCTL = TBSSEL_2 + MC_1 + ID_3 + TBIE; // SMCLK, /8

}

#pragma vector=TIMERA1_VECTOR
__interrupt void TimerA_ISR(void) // interrupt service routine for time functions
{
TAIV;

us_counter++;
}

#pragma vector=TIMERB1_VECTOR
__interrupt void TimerB_ISR(void)
{
TBIV;

count_50hz++;

if(count_50hz==50) // REACH 1S
{
count_50hz=0;
Flag.reach_1s = 1;
}
else if(count_50hz == 5)
{
Flag.reach_5hz = 1;
}
}

/********************** SPI Functions *************************/

void spi_init(void)
{
IRQ_In;
CE_Out;
CSN_Out;

Set_CE;
Set_CSN;

P3SEL |= 0x0E; // P3.3,2,1 option select
UCB0CTL0 |= UCMST+UCSYNC+UCMSB; //3-pin, 8-bit SPI master
UCB0CTL1 |= UCSSEL_2; // SMCLK
UCB0BR0 = 0x08; // /8
UCB0BR1 = 0;
UCB0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
}

void spi_write(unsigned char spi_data)
{
while (!(IFG2 & UCB0TXIFG)||UCB0STAT&UCBUSY); // USCI_B0 TX buffer ready?
UCB0TXBUF = spi_data; // Send next value; "TX/RX of master happens here"
while (!(IFG2 & UCB0TXIFG)||UCB0STAT&UCBUSY); // USCI_B0 TX buffer ready?
}

unsigned char spi_read(void)
{
while(!(IFG2 & UCB0RXIFG)||UCB0STAT&UCBUSY||UCB0STAT&UCOE);
return UCB0RXBUF;
}

/************************* RF Functions ************************/

unsigned char SPI_RW(unsigned char value)
{
spi_write(value);

return spi_read();
}

void SPI_Write_Reg(UINT8 reg, UINT8 value)
{
Clr_CSN;
op_status = SPI_RW(reg); // select register
SPI_RW(value); // ..and write value to it..
Set_CSN;
}

UINT8 SPI_Read_Reg(UINT8 reg)
{
UINT8 value;
Clr_CSN;
op_status=SPI_RW(reg); // Select register to read from..

value = SPI_RW(0); // ..then read register value
Set_CSN;

return(value); // return register value
}

void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 /*status,*/byte_ctr;

Clr_CSN; // Set CSN l
/*status = */SPI_RW(reg); // Select register to write, and read status UINT8

for(byte_ctr=0;byte_ctr<length;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); // Perform SPI_RW to read UINT8 from RFM70

Set_CSN; // Set CSN high again

}

void SPI_Write_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 byte_ctr;

Clr_CSN; // Set CSN low, init SPI tranaction
op_status = SPI_RW(reg); // Select register to write to and read status UINT8
for(byte_ctr=0; byte_ctr<length; byte_ctr++) // then write all UINT8 in buffer(*pBuf)
SPI_RW(*pBuf++);
Set_CSN; // Set CSN high again

}

void SwitchToRxMode()
{
UINT8 value;

SPI_Write_Reg(FLUSH_RX,0);//flush Rx

value=SPI_Read_Reg(STATUS); // read register STATUS's value
SPI_Write_Reg(WRITE_REG|STATUS,value);// clear RX_DR or TX_DS or MAX_RT interrupt flag

Clr_CE;

value=SPI_Read_Reg(CONFIG); // read register CONFIG's value

//PRX
value=value|0x01;//set bit 1
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled..
Set_CE;
}

void SwitchToTxMode()
{
UINT8 value;
SPI_Write_Reg(FLUSH_TX,0);//flush Tx

Clr_CE;
value=SPI_Read_Reg(CONFIG); // read register CONFIG's value
//PTX
value=value&0xfe;//set bit 0
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled.

Set_CE;
}

void SwitchCFG(char _cfg)//1:Bank1 0:Bank0
{
UINT8 Tmp;

Tmp=SPI_Read_Reg(7);
Tmp=Tmp&0x80;

if( ( (Tmp)&&(_cfg==0) )
||( ((Tmp)==0)&&(_cfg) ) )
{
SPI_Write_Reg(ACTIVATE_CMD,0x53);
}
}

void SetChannelNum(UINT8 ch)
{
SPI_Write_Reg((UINT8)(WRITE_REG|5),(UINT8)(ch));
}

void RFM70_Initialize()
{
UINT8 i,j/*,temp*/;
UINT8 WriteArr[12];

delay_200ms();

SwitchCFG(0);

for(i=0;i<20;i++)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
}

//reg 10 - Rx0 addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX0_Address[j];
}
SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);

//REG 11 - Rx1 addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX1_Address[j];
}
SPI_Write_Buf((WRITE_REG|11),&(WriteArr[0]),5);
//REG 16 - TX addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX0_Address[j];
}
SPI_Write_Buf((WRITE_REG|16),&(WriteArr[0]),5);

// printf("\nEnd Load Reg");

i=SPI_Read_Reg(29);//read Feature Register Èç¹ûÒªÖ§³Ö¶¯Ì¬³¤¶È»òÕß Payload With ACK£¬ĞèÒªÏȸøоƬ·¢ËÍ ACTIVATEÃüÁÊı¾İΪ0x73),È»ºóʹÄܶ¯Ì¬³¤¶È»òÕß Payload With ACK (REG28,REG29).
if(i==0) // i!=0 showed that chip has been actived.so do not active again.
SPI_Write_Reg(ACTIVATE_CMD,0x73);// Active
for(i=22;i>=21;i--)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
//SPI_Write_Reg_Bank0(Bank0_Reg[0],Bank0_Reg[1]);
}

//********************Write Bank1 register******************
SwitchCFG(1);

for(i=0;i<=8;i++)//reverse
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

for(i=9;i<=13;i++)
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(3-j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

//SPI_Write_Buf((WRITE_REG|14),&(Bank1_Reg14[0]),11);
for(j=0;j<11;j++)
{
WriteArr[j]=Bank1_Reg14[j];
}
SPI_Write_Buf((WRITE_REG|14),&(WriteArr[0]),11);

//toggle REG4<25,26>
for(j=0;j<4;j++)
//WriteArr[j]=(RegArrFSKAnalog[4]>>(8*(j) ) )&0xff;
WriteArr[j]=(Bank1_Reg0_13[4]>>(8*(j) ) )&0xff;

WriteArr[0]=WriteArr[0]|0x06;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

WriteArr[0]=WriteArr[0]&0xf9;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

//**************************Test spi*****************************//
//SPI_Write_Reg((WRITE_REG|Bank0_Reg[2][0]),0x0f);
//test_data = SPI_Read_Reg(0x02);


//DelayMs(10);
delay_50ms();

//********************switch back to Bank0 register access******************
SwitchCFG(0);
SwitchToRxMode();//switch to RX mode
}

void sub_program_1hz(void)
{
UINT8 i;
UINT8 temp_buf[32];

if(Flag.reach_1s)
{
Flag.reach_1s = 0;

for(i=0;i<17;i++)
{
temp_buf=tx_buf;
}

Send_Packet(W_TX_PAYLOAD_NOACK_CMD,temp_buf,17);
SwitchToRxMode(); //switch to Rx mode
}
}

void Send_Packet(UINT8 type,UINT8* pbuf,UINT8 len)
{
UINT8 fifo_sta;

SwitchToTxMode(); //switch to tx mode

fifo_sta=SPI_Read_Reg(FIFO_STATUS); // read register FIFO_STATUS's value
if((fifo_sta&FIFO_STATUS_TX_FULL)==0)//if not full, send data (write buff)
{
SPI_Write_Buf(type, pbuf, len); // Writes data to buffer

delay_50ms(); // Line 547
delay_50ms();
}
}

void Receive_Packet(void)
{
UINT8 len,i,sta,fifo_sta/*,value*/,chksum/*,aa*/;
UINT8 rx_buf[MAX_PACKET_LEN];

sta=SPI_Read_Reg(STATUS); // read register STATUS's value

if((STATUS_RX_DR&sta) == 0x40) // if receive data ready (RX_DR) interrupt
{
TogBit(P3DIR,7);

do
{
len=SPI_Read_Reg(R_RX_PL_WID_CMD); // read len

if(len<=MAX_PACKET_LEN)
{
SPI_Read_Buf(RD_RX_PLOAD,rx_buf,len);// read receive payload from RX_FIFO buffer
}
else
{
SPI_Write_Reg(FLUSH_RX,0);//flush Rx
}

fifo_sta=SPI_Read_Reg(FIFO_STATUS); // read register FIFO_STATUS's value

}while((fifo_sta&FIFO_STATUS_RX_EMPTY)==0); //while not empty

chksum = 0;
for(i=0;i<16;i++)
{
chksum +=rx_buf;
}
if(chksum==rx_buf[16]&&rx_buf[0]==0x30)
{
//GREEN_LED = 1;
delay_50ms();
delay_50ms();
//GREEN_LED = 0;

//Send_Packet(W_TX_PAYLOAD_NOACK_CMD,rx_buf,17);
//SwitchToRxMode();//switch to RX mode
}
}
SPI_Write_Reg(WRITE_REG|STATUS,sta);// clear RX_DR or TX_DS or MAX_RT interrupt flag
}

/******************** Delay Functions *************************/

void delay_200ms(void)
{
us_counter = 0;
while(us_counter<10000);
}

void delay_50ms(void)
{
us_counter = 0;
while(us_counter<2500);
}

void delay_5ms(void)
{
us_counter = 0;
while(us_counter<250);
}

void delay_20us(void)
{
us_counter = 0;
while(us_counter<1);
}

void delay_1ms(void)
{
us_counter = 0;
while(us_counter<50);
}

void DelayMs(unsigned ms)
{
unsigned long wait_time;
wait_time = 50*ms;
us_counter = 0;
while(us_counter<wait_time);
}
@Harshad Italiya • 05 Nov, 2011 First check your SPI whether its working proper or not.
@fantomas2002ro • 07 Jan, 2012 Hello,
I edit RFM70 code for lpcxpresso(lpc1343).
But i have the same error like nakres . I sniffer the spi protocol with an logicport and it seems that the SPI communication is working.
I modify the SPI_RW function in 2 different ways:

1).
uint32_t SSPSend( uint8_t *buf, uint32_t Length )
{
  uint32_t i;
  uint8_t Dummy = Dummy;
 
  for ( i = 0; i < Length; i++ )
  {
    /* Move on only if NOT busy and TX FIFO not full. */
    while ( (LPC_SSP->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
    LPC_SSP->DR = *buf;
    //printf("reg: %d, val(0): %d\n ", LPC_SSP->DR, *buf);
    buf++;
#if !LOOPBACK_MODE
    while ( (LPC_SSP->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
    /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO
    on MISO. Otherwise, when SSP0Receive() is called, previous data byte
    is left in the FIFO. */
    //Dummy = LPC_SSP->DR;//commented this line
#else
    /* Wait until the Busy bit is cleared. */
    while ( LPC_SSP->SR & SSPSR_BSY );
#endif
  }
  return LPC_SSP->DR;/added this one
}
 
UINT8 SPI_RW(UINT8 value)
{
  return(SSPSend(&value, 1));                    // return read UINT8
}
 
2).
void SSPSend( uint8_t *buf, uint32_t Length )
{
  uint32_t i;
  uint8_t Dummy = Dummy;
 
  for ( i = 0; i < Length; i++ )
  {
    /* Move on only if NOT busy and TX FIFO not full. */
    while ( (LPC_SSP->SR & (SSPSR_TNF|SSPSR_BSY)) != SSPSR_TNF );
    LPC_SSP->DR = *buf;
    //printf("reg: %d, val(0): %d\n ", LPC_SSP->DR, *buf);
    buf++;
#if !LOOPBACK_MODE
    while ( (LPC_SSP->SR & (SSPSR_BSY|SSPSR_RNE)) != SSPSR_RNE );
    /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO
    on MISO. Otherwise, when SSP0Receive() is called, previous data byte
    is left in the FIFO. */
    Dummy = LPC_SSP->DR;
#else
    /* Wait until the Busy bit is cleared. */
    while ( LPC_SSP->SR & SSPSR_BSY );
#endif
  }
  //return LPC_SSP->DR;
}
 
UINT8 SPI_RW(UINT8 value)
{
    SSPSend(&value, 1);//will not modify the value
    SSPReceive(&value, 1);//it will modify the value
  return(value);                    // return read UINT8
}
I get the same results: 0x00 or 0x0E. I don't know what to do. If is anybody that can help me(knowswith lpcxpresso, or not), please do 😁 😀.
I attached the hole project.

Best regards.😁
@Harshad Italiya • 07 Jan, 2012 @Fantomas : please give me some time to review your code i'll get back to you soon. Have you checked that your SPI is working fine? Whatever you're writing to Config register are you able to read that content back?
@fantomas2002ro • 08 Jan, 2012 Hello.

I think the SPI comunication is running well because I tested it with logicport.

I set a breakpoint at this line of code to see the values.

At some point theese values ​​have been received.
   
    SPI_Write_Reg((WRITE_REG|Bank0_Reg[2][0]),0x0f);
    test_data1[0] =  SPI_Read_Reg(0x02);//don't remember

    for(j=0;j<0x17;j++)
        test_data1[j] = SPI_Read_Reg(Bank0_Reg[j][0]);
   
    The results are:
    //aprox the same as Bank0_Reg
    test_data1[0]    0xf
    test_data1[1]    0x3f
    test_data1[2]    0x3f
    test_data1[3]    0x3
    test_data1[4]    0xff
    test_data1[5]    0x17
    test_data1[6]    0x17
    test_data1[7]    0xe
    test_data1[8]    0x0
    test_data1[9]    0x0
    test_data1[10]    0xc3
    test_data1[11]    0xc4
    test_data1[12]    0xc5
    test_data1[13]    0xc6
    test_data1[14]    0x20
    test_data1[15]    0x20
    test_data1[16]    0x20
    test_data1[17]    0x20
    test_data1[18]    0x20
    test_data1[19]    0x20
    test_data1[20]    0x1
    test_data1[21]    0x3f
    test_data1[22]    0x7    
After a while I receives another values

    SPI_Write_Reg((WRITE_REG|Bank0_Reg[2][0]),0x0f);
    test_data1[0] = SPI_Read_Reg(0x02);//received 0x03

    for(j=0;j<0x17;j++)
        test_data1[j] = SPI_Read_Reg(Bank0_Reg[j][0]);
   
    The results are:
    // not all
    test_data1[0]    0x8
    test_data1[1]    0x3f
    test_data1[2]    0x3
    test_data1[3]    0x3
    test_data1[4]    0x3
    test_data1[5]    0x2
    test_data1[6]    0x3f
    test_data1[7]    0xe
    test_data1[8]    0x0
    test_data1[9]    0x0
    test_data1[10]    0xc3
    test_data1[11]    0xc4
    test_data1[12]    0xc5
    test_data1[13]    0xc6
    test_data1[14]    0x0
    test_data1[15]    0x0
    test_data1[16]    0x0
    test_data1[17]    0x0
    test_data1[18]    0x0
    test_data1[19]    0x0
    test_data1[20]    0x11
    test_data1[21]    0x0
    test_data1[22]    0x0
I do not know what happened, because it seems to work.

Thank you for thisquick response.👍

P.S. : I added this line of code into the main, and modify the functions: SSPSend and SPI_RW.

CE_OUT();
CE(0);
I attached the new project.
@Harshad Italiya • 08 Jan, 2012 May i know which microcontroller you are using and why there is need to change the read write function if you've used the reference code given with module then it should work properly with freescale, ti, atmel microcontrollers. I've tested same code without any change in software. To check SPI my first step is write any one register and read it back if it's perfect then it should work. And main thing is swapping of addresss between transmitter and receiver is most important.
@fantomas2002ro • 08 Jan, 2012 As I said in my first post. I am using the board lpcxpresso(with lpc1343) and the CodeRed IDE . I modified the reference code to fit lpc1343, but it did not work. So I modify the software SPI read/write function with the SPI functions provided with the IDE. I still don't know if my read/write function it's working properly.
My current read/write function is this:
UINT8 SPI_RW(UINT8 value) {
SSPSend(&value, 1);//provided with CodeRed
SSPReceive(&value, 1);//provided with CodeRed
return(value); // return read UINT8
}
.
As I said at the second post I think I was writing and reading well from the registers, then after I modify something I don't remember then the values changed. I looked closely at the code and it seems that everything is as before(I undo the changes ). But still It's not OK. So I don't know what I did.
When it was reading well from the register this line of code:
i=SPI_Read_Reg(29);//read Feature Register
returns 0x07. Now it returns 0x00(so it's not configured).
Thank you for your respons
@Kaustubh Katdare • 08 Jan, 2012 Tip: Always wrap your 'code' in [ code] --- [ /code] tags.[/code]
@Harshad Italiya • 08 Jan, 2012 That means your software SPI is not proper yet. Do one thing take the reference code again and then change it according to your compiler and controller.
To save versions in backup is good thing 😉. So can do this please and let me know. And also follow Big_K's tip. 😀
@fantomas2002ro • 08 Jan, 2012 I will addapt the code again for lpc1343 and I will post here the output 😁.
About that tip... I wanted but I could not add nothing because the site didn't let me( "More Option" button didn't work).

Thank you again. 😁

The source from where I was inspired are here https://www.hoperf.com/rf_fsk/24g/RFM70.htm
@Harshad Italiya • 08 Jan, 2012
fantomas2002ro
I will addapt the code again for lpc1343 and I will post here the output 😁.
About that tip... I wanted but I could not add nothing because the site didn't let me( "More Option" button didn't work).

Thank you again. 😁

The source from where I was inspired are here https://www.hoperf.com/rf_fsk/24g/RFM70.htm
You can use that text directly paste your code as said by Big K and let me know your controller operating speed and SPI clock speed.
@BIG_K check please why he is not able to get more options. 😀
@fantomas2002ro • 08 Jan, 2012 The controller operating speed is72MHz and the clock speed of the SPI block is 72/2= 36MHz.

P.S. : I changed the speed to 1MHz for SPI block. No difference.
@Harshad Italiya • 08 Jan, 2012 Keep it bellow 1Mhz when you're updating code again. Ok. So your first task is to write and read properly from the module. 😀
@fantomas2002ro • 09 Jan, 2012 Hello.

I recreated the hole code(spi main speed is 0.72 MHz) and inserted into the schematic a logic port analyzer(https://www.pctestinstruments.com/) to sniffer the protocol.
I create a while loop to see if the communication is working:
while(1){
        for(j=0;j<5;j++)
        {
            WriteArr[j]=RX0_Address[j];
        }
        SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);
    }
(WRITE_REG|10) = 0x2a;
WriteArr[0] = 0x34
WriteArr[1] = 0x43
WriteArr[2] = 0x10
WriteArr[3] = 0x10
WriteArr[4] = 0x1
[​IMG]

As you can see, in to the picture the protocol is running well, but the values read from registers are the same as the last time.

P.S: I also aded this line of code to read all of the registers
for(j=0;j<0x17;j++)
            test_data1[j] = SPI_Read_Reg(j);
What to think?

And the output is the same as yesterday 😔.
[​IMG]

I added the project.
@Harshad Italiya • 09 Jan, 2012 • 1 like Well seems this time have to check all things again. Have to check your whole project too. Right now not able to access internet on desktop or laptop surfing from mobile only. But noted down your task will get back to you very soon. Sorry for the delay.
@fantomas2002ro • 09 Jan, 2012 Thank you very much. I don't know what is going wrong. I ported the program for lpc1343, that's all.
I have two lpcxpresso boards and two rfm70 module. I do not think I fried my two modules connected to different lpcxpresso board.
@AaiRIz • 10 May, 2012 Sir, I am a new bee in RFM70

so sir please help me to communicate with rfm70.
please provide me the schematic & also the procedure for how to configure RFM70 as transmitter or as a receiver.

Waiting for your reply.
Thanks.
@Harshad Italiya • 10 May, 2012
AaiRIz
Sir, I am a new bee in RFM70

so sir please help me to communicate with rfm70.
please provide me the schematic & also the procedure for how to configure RFM70 as transmitter or as a receiver.

Waiting for your reply.
Thanks.
Which microcontroller you are going to use? Have you gone through the RFM70 Datasheet?
@fantomas2002ro • 10 May, 2012 After all the trouble I didn't manage to have a communication between these 2 modules. I outher words I can't help you 😔
@Harshad Italiya • 11 May, 2012
fantomas2002ro
After all the trouble I didn't manage to have a communication between these 2 modules. I outher words I can't help you 😔
Still you want to give it a try? then Lets start again.
@ky3orr • 02 Jul, 2012 Hello Gents,

I am working now on project that incorporates RFM70 modules.
I was reading what You'd posted here and I am concerned about modules addressing scheme.

You state that TX address should be different that RX_0 on the same module and that those should be crossed between two connecting modules: TX addx (PTX)= RX_0 addr (PRX) and RX_0 addr (PTX) = TX addr (PRX).

In documentation of the RFM70 it is stated that TX addr of PTX should be the same as RX address of the pipe You want to send data for selected PRX module. Also if You'd like to make use of ACK packets in PTX module its RX_0 addr should be the same sa TX addx (because PRX module takes address of the pipe on which it received packet with ACK request and sends ACK back to the same address).

So it such configuration we would have two modules with the same address sets. Why It should work? At the same time both modules are in oposite modes (PTX, PRX), so they are not listening from/sending to themselves 😀

That's my concern about crossing addresses, You say it's working. 😀

Anyway - I am trying to get receiver working. I believe transmitter is sending data, but there is nothing on receiver side, so I really don't know where is the problem.
My question is: For PTX is it needed to generate positive CE pulse each time I am sending data to TX_FIFO, or it is sufficient if I just hold it logical 1 all the time I am in TX mode?
Is packet generated and aired just after payload data was put in TX_FIFO?

thanks for any hints.

regards
@Harshad Italiya • 02 Jul, 2012 ky3orr I have tried to make it working with same address field and few days back I come to know that it is working.

now regarding your problem have you checked that your SPI is properly working? By writing and reading one Register you can check it out.

you can keep CE pin active high everytime.
@ky3orr • 03 Jul, 2012 godfather,

thanks for answer. My SPI is working and all the stuff i am writing is readable 😀

Today I was going again through list of examples and I've found that in datasheet for bank1 manufacturer is saying:
"Must write with 0xD99E860B(High Power), For single carrier mode:0xD99E8621".
It is not said which values are for which occasions and if use only one or both...
In software example they initialize it with 0xf99E860B that looks like nothing fron datasheet 😛
Moreover they also write, after that, to bank1 address 4 such two weird things: 0x(f9 | 0x6)9E860B and later on 0x(f9 & ~0x6)9E860B.

what tha...?

Anyone could explain me, please, where such things are explained and why in example initialization is different than in datasheet? 😀

Weird - isn't it?

regards
@Harshad Italiya • 03 Jul, 2012
ky3orr
godfather,

thanks for answer. My SPI is working and all the stuff i am writing is readable 😀

Today I was going again through list of examples and I've found that in datasheet for bank1 manufacturer is saying:
"Must write with 0xD99E860B(High Power), For single carrier mode:0xD99E8621".
It is not said which values are for which occasions and if use only one or both...
In software example they initialize it with 0xf99E860B that looks like nothing fron datasheet 😛
Moreover they also write, after that, to bank1 address 4 such two weird things: 0x(f9 | 0x6)9E860B and later on 0x(f9 & ~0x6)9E860B.

what tha...?

Anyone could explain me, please, where such things are explained and why in example initialization is different than in datasheet? 😀

Weird - isn't it?

regards
Ah that is weird I never give it attention. You can mail HopeRF they will surely reply to your this query.
@Harshad Italiya • 03 Jul, 2012 I'll spare some time for this but not possible in next few days..
@ky3orr • 10 Jul, 2012 Ok then,

Is it possible for You to do a dump of RFMs register values after power up and after successful configuration?
I can't bring those modules to life so maybe there is some bug in my initialization.

I did it partly this morning and I see that there are some registers (bank1) that give all 0's while reading them but anyway It would be nice just to print out values of ALL registers (both banks) found in spec and just compare those.

I hope it is not so much effort for You, as You do have already running modules.

I asked HopeRF for detailed description of the registers, and mentioned the difference in spec and example code, but they say "use sample code" and "go to max supply voltage".

If anyone could help I will appreciate.
Is it needed to post sample code of dump routine in C?

regards
@ky3orr • 10 Jul, 2012 This is my configuration for receiver (decimal notation).
--- Bank 0 ---
0 -> 127
1 -> 63
2 -> 63
3 -> 3
4 -> 63
5 -> 40
6 -> 48
7 -> 14
8 -> 0
9 -> 0
10 -> 231
11 -> 165
12 -> 195
13 -> 196
14 -> 197
15 -> 198
16 -> 231
17 -> 0
18 -> 0
19 -> 0
20 -> 0
21 -> 0
22 -> 0
23 -> 17
24 -> 0
25 -> 0
26 -> 0
27 -> 0
28 -> 63
29 -> 4
--- Bank 1 ---
0 -> 0, 0, 0, 0,
1 -> 0, 0, 0, 0,
2 -> 0, 0, 0, 0,
3 -> 0, 0, 0, 0,
4 -> 0, 0, 0, 0,
5 -> 0, 0, 0, 0,
6 -> 0, 0, 0, 0,
7 -> 142, 0, 0, 0,
8 -> 99, 0, 0, 0,
9 -> 0, 0, 0, 0,
10 -> 0, 0, 0, 0,
11 -> 0, 0, 0, 0,
12 -> 0, 18, 115, 0,
13 -> 54, 180, 128, 0,
14 -> 65, 32, 8, 4, 129, 32, 207, 247, 254, 255, 255,
Transmitter gets the same with difference that PRX=0.

Could You take a look if all is ok or post Yours register dump?

regards
@Harshad Italiya • 10 Jul, 2012 I'm using same sample code just one or two changes I have implemented it was range only. so I think try to run Sample code first if it is working properly you can add your changes step by step and check where exactly your code stops working. this is the procedure I follow every time I start working on any new Modules.
@ky3orr • 11 Jul, 2012 @godfather I was trying to run sample code but it didn;t worked.
Is it some special way of setting CE after sending payload to the buffer?
I am asking because right now CE is always high after initialization, but it seems not working as I do not see anything received on receiver side.

As I understand after initialization if I use write payload with no ack receiver should get aired data?

could You share Your library with init and important routines code?

Mine is below:

static uint8_t init_values_bank0_addresses[][6] = {
{0x10, 0xE7, 0x18, 0xE7, 0x18, 0xFF},    //default transmit address (packets go to PRX with that addr)
{0x0A, 0xE7, 0x18, 0xE7, 0x18, 0xFF},    //default receive address for pipe0 (the same as above for ACK's)
{0x0B, 0xA5, 0x5A, 0xA5, 0x5A, 0x01}    //default receive address for pipe1
};
 
static uint8_t init_values_bank0[][2] = {
    #if PRX_MODULE == 1
        {0x00, 0x7F},    //no interrupts, 2-byte CRC, power up, PRX
    #else
        {0x00, 0x7E},    //no interrupts, 2-byte CRC, power up, PTX
    #endif
    {0x01, 0x3F},    //auto acknowledgment for all pipes
    {0x02, 0x3F},    //enable RX for all pipes
    {0x03, 0x03},    //address length 5 bytes
    {0x04, 0x3F},    //up to 15 retransmissions with delay of 1000[us]
    {0x05, 0x28},    //initial channel 40 (2440[MHz])
    //{0x06, 0x35},    //LNA high gain, TX power 0[dBm], burst air rate 1[Mbit]
    {0x06, 0x30},    //LNA low gain, TX power -10[dBm], burst air rate 1[Mbit]
    {0x07, 0x07},    //status written with default value (reset int flags)
    {0x0C, 0xC3},    //default RX address LSB for pipe2
    {0x0D, 0xC4},    //default RX address LSB for pipe3
    {0x0E, 0xC5},    //default RX address LSB for pipe4
    {0x0F, 0xC6},    //default RX address LSB for pipe5
    {0x11, 0x00},  //payload length not used for pipe0 (dynamic payload)
    {0x12, 0x00},  //payload length not used for pipe1 (dynamic payload)
    {0x13, 0x00},  //payload length not used for pipe2 (dynamic payload)
    {0x14, 0x00},  //payload length not used for pipe3 (dynamic payload)
    {0x15, 0x00},  //payload length not used for pipe4 (dynamic payload)
    {0x16, 0x00},  //payload length not used for pipe5 (dynamic payload)
    {0x1C, 0x3F},    //enable reception with dynamic payload for all pipes
    {0x1D, 0x04}    //enable transmissions with dynamic payload, no ACK
};
 
static uint8_t init_values_bank1[][5] = {
    {0x00, 0x40, 0x4B, 0x01, 0xE2},    //default
    {0x01, 0xC0, 0x4B, 0x00, 0x00},    //default
    {0x02, 0xD0, 0xFC, 0x8C, 0x02},    //default
    {0x03, 0x99, 0x00, 0x39, 0x41},    //default
    //{0x04, 0xD9, 0x9E, 0x86, 0x0B},    //High Power
    {0x04, 0xF9, 0x9E, 0x86, 0x0B},
    {0x05, 0x24, 0x06, 0x7F, 0xA6},    //Disable RSSI
        //reversed
    {0x0C, 0x00, 0x12, 0x73, 0x00}, //default
    {0x0D, 0x36, 0xB4, 0x80, 0x00}    //default
};
 
static uint8_t init_values_bank1_14[12] = {0x0E, 0x41, 0x20, 0x08, 0x04, 0x81, 0x20, 0xCF, 0xF7, 0xFE, 0xFF, 0xFF};    //default
 
void RFM70_set_CS(uint8_t value) {
    if (value) {
        RFM70_PORT_CS |= (1<<RFM70_CS);
    } else {
        RFM70_PORT_CS &= ~(1<<RFM70_CS);
    }
}
 
void RFM70_set_CE(uint8_t value) {
    if (value) {
        RFM70_PORT_CE |= (1<<RFM70_CE);
    } else {
        RFM70_PORT_CE &= ~(1<<RFM70_CE);
    }
}
 
uint8_t RFM70_byte_io(uint8_t data_byte) {
    SPDR = data_byte;                        //load data into buffer
    while(!(SPSR & (1<<SPIF)));                //wait for transmission to finish
    return SPDR;                            //read data back and return it
}
 
void RFM70_use_bank(uint8_t bank_no) {
    uint8_t active_bank;
 
    bank_no = (bank_no) ? 1 : 0;
    RFM70_set_CS(0);
    active_bank = (RFM70_byte_io(READ_STATUS) & (1<<RBANK)) ? 1 : 0;
    RFM70_set_CS(1);
    if (bank_no ^ active_bank) {            //if set other bank - change it
        RFM70_set_CS(0);
        RFM70_byte_io(ACTIVATE);
        RFM70_byte_io(TOGGLE_BANK);
        RFM70_set_CS(1);
    }     
}
 
void RFM70_enable_features(uint8_t features) {
    uint8_t feature_register;
 
    RFM70_set_CS(0);
    RFM70_byte_io(R_REGISTER | FEATURE);
    feature_register = RFM70_byte_io(READ_BYTE);
    RFM70_set_CS(1);
 
    if (feature_register != features) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | FEATURE);
        RFM70_byte_io(features);
        RFM70_set_CS(1);
     
        RFM70_set_CS(0);
        RFM70_byte_io(R_REGISTER | FEATURE);
        feature_register = RFM70_byte_io(READ_BYTE);
        RFM70_set_CS(1);
        if (feature_register != features) {
            RFM70_set_CS(0);
            RFM70_byte_io(ACTIVATE);
            RFM70_byte_io(FEATURES);
            RFM70_set_CS(1);
        }         
    }
}
 
void RFM70_init() {
    uint8_t row_counter, element_counter;
    volatile uint16_t delay_counter;
 
    //prepare external signals
    RFM70_DDR_CE |= (1<<RFM70_CE);            //CE as an output
    RFM70_PORT_CE &= ~(1<<RFM70_CE);        //0 by default (STBY RFM70)
    RFM70_DDR_CS |= (1<<RFM70_CS);            //CS as an output
    RFM70_PORT_CS |= (1<<RFM70_CS);            //1 by default (idle SPI)
    //delay before transmission
    delay_counter = 0xFFFF;
    while (delay_counter--);
    //enable features setting
    RFM70_enable_features(0x1); //anything !=0 for features acivation
    RFM70_enable_features(0x0); //0 (default) in case nothing is set during init
    //initialize register bank0
    RFM70_use_bank(0);
    delay_counter = 0xFFFF;
    while (delay_counter--);
    for (row_counter = 0; row_counter < (sizeof(init_values_bank0) / sizeof(init_values_bank0[0])); row_counter++) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | init_values_bank0[row_counter][0]);
        for (element_counter = 1; element_counter < (sizeof(init_values_bank0[0]) / sizeof(init_values_bank0[0][0])); element_counter++) {
            RFM70_byte_io(init_values_bank0[row_counter][element_counter]);
        }
        RFM70_set_CS(1);
    }
    for (row_counter = 0; row_counter < (sizeof(init_values_bank0_addresses) / sizeof(init_values_bank0_addresses[0])); row_counter++) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | init_values_bank0_addresses[row_counter][0]);
        for (element_counter = 1; element_counter < (sizeof(init_values_bank0_addresses[0]) / sizeof(init_values_bank0_addresses[0][0])); element_counter++) {
            RFM70_byte_io(init_values_bank0_addresses[row_counter][element_counter]);
        }
        RFM70_set_CS(1);
    }
    //delay
    delay_counter = 0xFFFF;
    while (delay_counter--);
    //initialize register bank1
    RFM70_use_bank(1);
    delay_counter = 0xFFFF;
    while (delay_counter--);
    for (row_counter = 0; row_counter < (sizeof(init_values_bank1) / sizeof(init_values_bank1[0])); row_counter++) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | init_values_bank1[row_counter][0]);
        for (element_counter = 1; element_counter < (sizeof(init_values_bank1[0]) / sizeof(init_values_bank1[0][0])); element_counter++) {
            RFM70_byte_io(init_values_bank1[row_counter][element_counter]);
        }
        RFM70_set_CS(1);
    }
    RFM70_set_CS(0);
    RFM70_byte_io(W_REGISTER | init_values_bank1_14[0]);
    for (element_counter = 1; element_counter < (sizeof(init_values_bank1_14) / sizeof(init_values_bank1_14[0])); element_counter++) {
        RFM70_byte_io(init_values_bank1_14[element_counter]);
    }
    //writing again bank1, reg4 with 24 and 25 bit toggling
    for (row_counter = 0; row_counter < 2; row_counter++) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | 0x4);
        for (element_counter = 1; element_counter < (sizeof(init_values_bank1[0]) / sizeof(init_values_bank1[0][0])); element_counter++) {
            switch (element_counter) {
                case 1:
                    if (row_counter == 0) {
                        RFM70_byte_io(init_values_bank1[4][element_counter] | 0x6);
                    } else {
                        RFM70_byte_io(init_values_bank1[4][element_counter] & ~(0x6));
                    }
                    break;
                default:
                    RFM70_byte_io(init_values_bank1[4][element_counter]);
                    break;
            }
        }
        RFM70_set_CS(1);
    }
    //delay before transmission
    delay_counter = 0xFFFF;
    while (delay_counter--);
    //restore bank0
    RFM70_use_bank(0);
}
 
void tx_fifo_flush(void) {
    RFM70_set_CS(0);
    RFM70_byte_io(FLUSH_TX);
    RFM70_set_CS(1);
}
 
void rx_fifo_flush(void) {
    RFM70_set_CS(0);
    RFM70_byte_io(FLUSH_RX);
    RFM70_set_CS(1);
}
 
void transmitter_mode(void) {
    uint8_t status, config;
    //flush fifo
    tx_fifo_flush();
    //standby
    RFM70_set_CE(0);
    //reset active interrupt flags
    RFM70_set_CS(0);
    status = RFM70_byte_io(READ_STATUS);
    RFM70_set_CS(1);
    RFM70_set_CS(0);
    RFM70_byte_io(W_REGISTER | STATUS);
    RFM70_byte_io(status);
    RFM70_set_CS(1);
    //switch to tx mode
    RFM70_set_CS(0);
    RFM70_byte_io(R_REGISTER | CONFIG);
    config = RFM70_byte_io(READ_BYTE);
    RFM70_set_CS(1);
    config &= ~(1<<PRIM_RX);
    RFM70_set_CS(0);
    RFM70_byte_io(W_REGISTER | CONFIG);
    RFM70_byte_io(config);
    RFM70_set_CS(1);
    //go active
    RFM70_set_CE(1);
}
 
void receiver_mode(void) {
    uint8_t status, config;
    //flush fifo
    rx_fifo_flush();
    //standby
    RFM70_set_CE(0);
    //reset active interrupt flags
    RFM70_set_CS(0);
    status = RFM70_byte_io(READ_STATUS);
    RFM70_set_CS(1);
    RFM70_set_CS(0);
    RFM70_byte_io(W_REGISTER | STATUS);
    RFM70_byte_io(status);
    RFM70_set_CS(1); 
    //switch to rx mode
    RFM70_set_CS(0);
    RFM70_byte_io(R_REGISTER | CONFIG);
    config = RFM70_byte_io(READ_BYTE);
    RFM70_set_CS(1);
    config |= (1<<PRIM_RX);
    RFM70_set_CS(0);
    RFM70_byte_io(W_REGISTER | CONFIG);
    RFM70_byte_io(config);
    RFM70_set_CS(1);
    //go active
    RFM70_set_CE(1);
}
 
void write_payload(uint8_t *data, uint8_t size) {
    uint8_t element_counter;
 
    if (size > 32) { size = 32;    }
 
    RFM70_set_CS(0);
    RFM70_byte_io(W_TX_PAYLOAD);
    for (element_counter = 0; element_counter < size; element_counter++) {
        RFM70_byte_io(data[element_counter]);
    } 
    RFM70_set_CS(1);
}
 
void write_payload_no_ack(uint8_t *data, uint8_t size) {
    uint8_t element_counter;
 
    if (size > 32) { size = 32;    }
 
    RFM70_set_CS(0);
    RFM70_byte_io(W_TX_PAYLOAD_NOACK);
    for (element_counter = 0; element_counter < size; element_counter++) {
        RFM70_byte_io(data[element_counter]);
    }
    RFM70_set_CS(1);
}
 
uint8_t data_transmitted(void) {
    uint8_t status;
 
    RFM70_set_CS(0);
    status = RFM70_byte_io(READ_STATUS);
    RFM70_set_CS(1);
 
    if (status & (1<<TX_DS)) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | STATUS);
        //RFM70_byte_io(status |= (1<<TX_DS));
        RFM70_byte_io(status);
        RFM70_set_CS(1);
        return 1;
    }
    return 0;
}
 
uint8_t data_received(void) {
    uint8_t status;
 
    RFM70_set_CS(0);
    status = RFM70_byte_io(READ_STATUS);
    RFM70_set_CS(1);
 
    if (status & (1<<RX_DR)) {
        RFM70_set_CS(0);
        RFM70_byte_io(W_REGISTER | STATUS);
        RFM70_byte_io(status |= (1<<RX_DR));
        RFM70_set_CS(1);
        return 1;
    }
    return 0;
}
 
uint8_t read_payload_length(void) {
    uint8_t payload_length;
 
    RFM70_set_CS(0);
    RFM70_byte_io(R_RX_PL_WID);
    payload_length = RFM70_byte_io(READ_BYTE);
    RFM70_set_CS(1);
 
    return payload_length;
}
 
void read_payload(uint8_t *payload_buffer, uint8_t size) {
    uint8_t index;
 
    RFM70_set_CS(0);
    RFM70_byte_io(R_RX_PAYLOAD);
    for (index = 0; index < size; index++) {
        payload_buffer[index] = RFM70_byte_io(READ_BYTE);
    }
    RFM70_set_CS(1);
    payload_buffer[index] = '\0';
}
 
regards
@Harshad Italiya • 11 Jul, 2012 Ok it will take some time as I am away from my PC but meanwhile you can check your SPI routine using Registor read write. If it works fine we can focus on CE pin only.
@ky3orr • 11 Jul, 2012 Yes, SPI is working. It is visible in register dump. Data read from the device is consistent with those used during initialization.
I also did example code to see if CE pin can toggle its value - it's working.

I am wondering if all is set up correctly.
Maybe some delays I forgot.
I am most interested in Your banks initialization values and order of setting them.

If You could post Your code it would be much easier and the fastest way to find differences.

Anyway thanks for Your interest in my problem. I hope it will work soon 😀

regards
@Harshad Italiya • 11 Jul, 2012
ky3orr
Yes, SPI is working. It is visible in register dump. Data read from the device is consistent with those used during initialization.
I also did example code to see if CE pin can toggle its value - it's working.

I am wondering if all is set up correctly.
Maybe some delays I forgot.
I am most interested in Your banks initialization values and order of setting them.

If You could post Your code it would be much easier and the fastest way to find differences.

Anyway thanks for Your interest in my problem. I hope it will work soon 😀

regards
Yes mostly by today I'll post codes.
@ky3orr • 11 Jul, 2012 Thanks,

right now I am guessing that I might do have a problem because in register 1D bank0 I set only EN_DPL but I guess I also should enable EN_DYN_ACK while sending data with W_TX_PAYLOAD_NO_ACK command...

Maybe that's why receiver can't receive anything because I am not letting it to get any of air frames without ACK.
Is my thinking right?

I guess if I set all pipes to work in ACK mode and if I want to send data without ACK needed I should use W_TX_PAYLOAD_NO_ACK command then (so EN_DYN_ACK should be enabled in features)?

best regards
@Harshad Italiya • 11 Jul, 2012 • 1 like #include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */
#include "RF70.h"
#include "pindef.h"

UINT8 op_status;

extern unsigned int test;



//Bank1 register initialization value

//In the array RegArrFSKAnalog,all the register value is the byte reversed!!!!!!!!!!!!!!!!!!!!!
const unsigned long Bank1_Reg0_13[]={ //latest config txt
0xE2014B40,
0x00004BC0,
0x028CFCD0,
0x41390099,
0x0B869Ef9,
0xA67F0624,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0x00127300,
0x36B48000,
};

const UINT8 Bank1_Reg14[]=
{
0x41,0x20,0x08,0x04,0x81,0x20,0xCF,0xF7,0xFE,0xFF,0xFF
};

//Bank0 register initialization value
const UINT8 Bank0_Reg[][2]={
{0,0x0F},//reflect RX_DR\TX_DS\MAX_RT,Enable CRC ,2byte,POWER UP,PRX
{1,0x3F},//Enable auto acknowledgement data pipe5\4\3\2\1\0
{2,0x3F},//Enable RX Addresses pipe5\4\3\2\1\0
{3,0x03},//RX/TX address field width 5byte
{4,0xff},//auto retransmission dalay (4000us),auto retransmission count(15)
{5,0x17},//23 channel
{6,0x1f/*0x17*/},//air data rate-1M,out power 5dbm,setup LNA gain
{7,0x07},//
{8,0x00},//
{9,0x00},
{12,0xc3},//only LSB Receive address data pipe 2, MSB bytes is equal to RX_ADDR_P1[39:8]
{13,0xc4},//only LSB Receive address data pipe 3, MSB bytes is equal to RX_ADDR_P1[39:8]
{14,0xc5},//only LSB Receive address data pipe 4, MSB bytes is equal to RX_ADDR_P1[39:8]
{15,0xc6},//only LSB Receive address data pipe 5, MSB bytes is equal to RX_ADDR_P1[39:8]
{17,0x20},//Number of bytes in RX payload in data pipe0(32 byte)
{18,0x20},//Number of bytes in RX payload in data pipe1(32 byte)
{19,0x20},//Number of bytes in RX payload in data pipe2(32 byte)
{20,0x20},//Number of bytes in RX payload in data pipe3(32 byte)
{21,0x20},//Number of bytes in RX payload in data pipe4(32 byte)
{22,0x20},//Number of bytes in RX payload in data pipe5(32 byte)
{23,0x00},//fifo status
{28,0x3F},//Enable dynamic payload length data pipe5\4\3\2\1\0
{29,0x07}//Enables Dynamic Payload Length,Enables Payload with ACK,Enables the W_TX_PAYLOAD_NOACK command
};


#ifdef device1
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x01}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x02};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x03};////Receive address data pipe 1
#endif

#ifdef device2
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x02}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x03};////Receive address data pipe 1
#endif

#ifdef device3
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x03}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x02};////Receive address data pipe 1
#endif

extern UINT8 test_data;
extern UINT8 channel;
extern UINT8 power;
extern UINT8 data_rate;
extern UINT8 rx_buf[MAX_PACKET_LEN];


extern void delay_200ms(void);
extern void delay_50ms(void);
///////////////////////////////////////////////////////////////////////////////
// SPI access //
///////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////
// Function: SPI_RW();
//
//Description:
// Writes one UINT8 to RFM70, and return the UINT8 read
//////////////////////////////////////////////////////////

UINT8 SPI_RW(UINT8 value)
{
UINT8 bit_ctr;
for(bit_ctr=0;bit_ctr<8;bit_ctr++) // output 8-bit
{
if(value & 0x80)
{
MOSI = 1;
}
else
{
MOSI=0;
}
value = (value << 1); // shift next bit into MSB..
SCK = 1; // Set SCK high..
// asm(nop);
value |= MISO; // capture current MISO bit
SCK = 0; // ..then set SCK low again
}
return(value); // return read UINT8
}

//**************************************************
//Function: SPI_Write_Reg();
//
//Description:
// Writes value 'value' to register 'reg'
//**************************************************/
void SPI_Write_Reg(UINT8 reg, UINT8 value) //--unsigned int UINT8
{
CSN = 0; // CSN low, init SPI transaction
op_status = SPI_RW(reg); // select register
op_status = SPI_RW(value); // ..and write value to it..
CSN = 1; // CSN high again
}


//**************************************************/

//**************************************************
//Function: SPI_Read_Reg();
//
//Description:
// Read one UINT8 from BK2421 register, 'reg'
//**************************************************/
UINT8 SPI_Read_Reg(UINT8 reg)
{

UINT8 value;
CSN = 0; // CSN low, initialize SPI communication...
op_status=SPI_RW(reg); // Select register to read from..
value = SPI_RW(0); // ..then read register value
CSN = 1; // CSN high, terminate SPI communication
asm(NOP);
return(value); // return register value
}
//**************************************************/

//**************************************************
//Function: SPI_Read_Buf();
//
//Description:
// Reads 'length' #of length from register 'reg'
//**************************************************/
void SPI_Read_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 status,byte_ctr;

CSN = 0; // Set CSN l
status = SPI_RW(reg); // Select register to write, and read status UINT8

for(byte_ctr=0;byte_ctr<length;byte_ctr++)
pBuf[byte_ctr] = SPI_RW(0); // Perform SPI_RW to read UINT8 from RFM70

CSN = 1; // Set CSN high again

}
//**************************************************/

//**************************************************
//Function: SPI_Write_Buf();
//
//Description:
// Writes contents of buffer '*pBuf' to RFM70
//**************************************************/
void SPI_Write_Buf(UINT8 reg, UINT8 *pBuf, UINT8 length)
{
UINT8 byte_ctr;

CSN = 0; // Set CSN low, init SPI tranaction
op_status = SPI_RW(reg); // Select register to write to and read status UINT8
for(byte_ctr=0; byte_ctr<length; byte_ctr++) // then write all UINT8 in buffer(*pBuf)
SPI_RW(*pBuf++);
CSN = 1; // Set CSN high again

}
//**************************************************
//Function: SwitchToRxMode();
//Description:
// switch to Rx mode
//**************************************************/
void SwitchToRxMode()
{
UINT8 value;

SPI_Write_Reg(FLUSH_RX,0);//flush Rx

value=SPI_Read_Reg(STATUS); // read register STATUS's value
SPI_Write_Reg(WRITE_REG|STATUS,value);// clear RX_DR or TX_DS or MAX_RT interrupt flag

CE=0;

value=SPI_Read_Reg(CONFIG); // read register CONFIG's value
test = value;

//PRX
value=value|0x01;//set bit 1
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled..
CE=1;
}

//**************************************************
//Function: SwitchToTxMode();
//Description:
// switch to Tx mode
///**************************************************/
void SwitchToTxMode()
{
UINT8 value;
SPI_Write_Reg(FLUSH_TX,0);//flush Tx

CE=0;
value=SPI_Read_Reg(CONFIG); // read register CONFIG's value
//PTX
value=value&0xfe; //set bit 0
SPI_Write_Reg(WRITE_REG | CONFIG, value); // Set PWR_UP bit, enable CRC(2 length) & Prim:RX. RX_DR enabled.

CE=1;
}

//**************************************************
//Function: SwitchCFG();
//
//Description:
// access switch between Bank1 and Bank0

///Parameter:
// _cfg 1:register bank1
// 0:register bank0
//Return:
// None
//**************************************************/
void SwitchCFG(char _cfg)//1:Bank1 0:Bank0
{
UINT8 Tmp;

Tmp=SPI_Read_Reg(7);
Tmp=Tmp&0x80;

if( ( (Tmp)&&(_cfg==0) )
||( ((Tmp)==0)&&(_cfg) ) )
{
SPI_Write_Reg(ACTIVATE_CMD,0x53);
}
}

///**************************************************
//Function: SetChannelNum();
//Description:
// set channel number
//
//**************************************************/
void SetChannelNum(UINT8 ch)
{
SPI_Write_Reg((UINT8)(WRITE_REG|5),(UINT8)(ch));
}



///////////////////////////////////////////////////////////////////////////////
// RFM70 initialization //
///////////////////////////////////////////////////////////////////////////////
//**************************************************
//Function: RFM70_Initialize();
///
//Description:
// register initialization
//**************************************************/
void RFM70_Initialize()
{
UINT8 i,j,temp;
UINT8 WriteArr[12];

//DelayMs(100);//delay more than 50ms.
delay_200ms();

SwitchCFG(0);

for(i=0;i<20;i++)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
}

for(j=0;j<5;j++)
{
WriteArr[j]=RX0_Address[j];
}
SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);

//REG 11 - Rx1 addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX1_Address[j];
}
SPI_Write_Buf((WRITE_REG|11),&(WriteArr[0]),5);

//REG 16 - TX addr
for(j=0;j<5;j++)
{
WriteArr[j]=Tx_address[j];
}
SPI_Write_Buf((WRITE_REG|16),&(WriteArr[0]),5);

// printf("\nEnd Load Reg");

i=SPI_Read_Reg(29);//read Feature Register ���Ҫ֧�ֶ�̬���Ȼ��� Payload With ACK����Ҫ�ȸ�оƬ���� ACTIVATE������Ϊ0x73),Ȼ��ʹ�ܶ�̬���Ȼ��� Payload With ACK (REG28,REG29).

if(i==0) // i!=0 showed that chip has been actived.so do not active again.
SPI_Write_Reg(ACTIVATE_CMD,0x73);// Active

for(i=22;i>=21;i--)
{
SPI_Write_Reg((WRITE_REG|Bank0_Reg[0]),Bank0_Reg[1]);
//SPI_Write_Reg_Bank0(Bank0_Reg[0],Bank0_Reg[1]);
}

//********************Write Bank1 register******************
SwitchCFG(1);

for(i=0;i<=8;i++)//reverse
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

for(i=9;i<=13;i++)
{
for(j=0;j<4;j++)
WriteArr[j]=(Bank1_Reg0_13>>(8*(3-j) ) )&0xff;

SPI_Write_Buf((WRITE_REG|i),&(WriteArr[0]),4);
}

//SPI_Write_Buf((WRITE_REG|14),&(Bank1_Reg14[0]),11);
for(j=0;j<11;j++)
{
WriteArr[j]=Bank1_Reg14[j];
}
SPI_Write_Buf((WRITE_REG|14),&(WriteArr[0]),11);

//toggle REG4<25,26>
for(j=0;j<4;j++)
//WriteArr[j]=(RegArrFSKAnalog[4]>>(8*(j) ) )&0xff;
WriteArr[j]=(Bank1_Reg0_13[4]>>(8*(j) ) )&0xff;

WriteArr[0]=WriteArr[0]|0x06;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

WriteArr[0]=WriteArr[0]&0xf9;
SPI_Write_Buf((WRITE_REG|4),&(WriteArr[0]),4);

//**************************Test spi*****************************//
//SPI_Write_Reg((WRITE_REG|Bank0_Reg[2][0]),0x0f);
//test_data = SPI_Read_Reg(0x02);


//DelayMs(10);
delay_50ms();

//********************switch back to Bank0 register access******************
SwitchCFG(0);
SwitchToRxMode();//switch to RX mode
}
//**************************************************
//Function: DelayMs();
//
//Description:
// delay ms,please implement this function according to your MCU.
//**************************************************/
void DelayMs(UINT16 ms)
{


}
@ky3orr • 11 Jul, 2012 godfather thanks for that,

It's pretty much the same with difference on 1D register and addressing idea.

I will check If I could get modules working.

BTW: As long as addresses for pipe0 and tx are different I assume You're using transmissions without ACK?
I read in datasheet that those should be configured in that way because PRX sends back ACK packet to the PTX with address that is the same as PRX receiver pipe.

regards
@ky3orr • 11 Jul, 2012 Bingo!
I initialized register 1D with value 0x5 and everything is working.
I do have link between two modules and it is possible now to transmit data.

It wasn't working because I was transmitting with no ACK feature, that was not enabled on receiver side.

thanks for help.

regards
@Harshad Italiya • 11 Jul, 2012
ky3orr
Bingo!
I initialized register 1D with value 0x5 and everything is working.
I do have link between two modules and it is possible now to transmit data.

It wasn't working because I was transmitting with no ACK feature, that was not enabled on receiver side.

thanks for help.

regards
Great ! share your project video if you have no any issue. and looking forward to see you active on forum so we can help more and more people with our little knowledge.
@ky3orr • 12 Jul, 2012 No problem,
I will surely would like to share something to the community but I need to overcome all problems 😀

I was working now with polling readout of data and now I am shifting to the IRQ routine.

My problem now is that ISR doesn't want to trigger relevant function - I need to investigate all AVR register settings.

regards
@Harshad Italiya • 12 Jul, 2012 So you are going to connect IRQ of RF module to MCU's Interrupt pin? Make sure you need to provide sufficient delay to initialize Module on power up.
@ky3orr • 12 Jul, 2012 Yes, of course.

I am investigating now interrupt response on atmega8 now. It seems not to work yet as I expected.
So I believe it's just some misconfiguration.

Do You know if IRQ pin of RFM70 is kind of CMOS/TTL/or OC?

regards
@Harshad Italiya • 12 Jul, 2012 Yes TTL Logic. It remains High 3.3V and when receives data goes low.
@Futterama • 03 Oct, 2012 Hi there, newbie at this forum.

I have been working with the RFM70 too, and I have overcome a lot of the wierd things about the RFM70. The one thing that annoys me right now, is that if I want to change PRIM_RX from 1 to 0 (change mode from RX to TX) I need to power down the module (clearing PWR_UP) before changing the mode, and then power back up. This is not in the datasheet.

Also when powering back up, there need to be a delay for the module to power back up, but I can't find any info in the datasheet about how long the module needs to power up.

A lot of trial and error need to be done with these devices since so many things are left out of the datasheet :-(
@Harshad Italiya • 03 Oct, 2012
Futterama
Hi there, newbie at this forum.

I have been working with the RFM70 too, and I have overcome a lot of the wierd things about the RFM70. The one thing that annoys me right now, is that if I want to change PRIM_RX from 1 to 0 (change mode from RX to TX) I need to power down the module (clearing PWR_UP) before changing the mode, and then power back up. This is not in the datasheet.

Also when powering back up, there need to be a delay for the module to power back up, but I can't find any info in the datasheet about how long the module needs to power up.

A lot of trial and error need to be done with these devices since so many things are left out of the datasheet :-(
I have developed more than 15 application based on RFM70 and I never face such problem. Are you sure that you are following the proper initialization?
@Futterama • 04 Oct, 2012
godfather
I have developed more than 15 application based on RFM70 and I never face such problem. Are you sure that you are following the proper initialization?
I am pretty sure, but when you say it like that, it makes me think.

Another strange thing is that I get high packet loss when using 2 bytes CRC.

I would be happy if you wanted to help check my initialization. Do you have a problem reading other peoples code or should I translate to pseudo code? I did make a lot of comments in the code to help track down errors.
@Futterama • 04 Oct, 2012 Do you initialize Bank1?

HopeRF says the default values are fine and that the memory in Bank1 is non-volatile. But you need at least to initialize the register 04 in Bank1 if you want low power mode (which I do).
@Harshad Italiya • 04 Oct, 2012
Futterama
Do you initialize Bank1?

HopeRF says the default values are fine and that the memory in Bank1 is non-volatile. But you need at least to initialize the register 04 in Bank1 if you want low power mode (which I do).
I have used the reference code given by HopeRF and slight modification depend on my application parameter. I am afraid you might have changed some critical registers and because of that you are facing this issue.

Post your initialization I will try my best to spent some time on same.
@Futterama • 04 Oct, 2012 Thanks, when I get the time, I will test for the problem again, but this time without changing any parameters in Bank1 and with an unused module. Then I will get back to you. I will probably not have time before tomorrow :-(
@Harshad Italiya • 04 Oct, 2012
Futterama
Thanks, when I get the time, I will test for the problem again, but this time without changing any parameters in Bank1 and with an unused module. Then I will get back to you. I will probably not have time before tomorrow :-(
Take your time and make code better. 😀
@Futterama • 04 Oct, 2012 Ok, I made some time for testing tonight.

I have disabled all Bank1 writes so I only do a minimum of initialization on the RFM70 for testing.

I made one setup (setup 1) which transmits a packet and another setup (setup 2) that receives it. After receiving the packet, dynamic payload length is read from the RX buffer and mode is changed to TX in setup 2 and a packet is sent. The packet is sent fine, but only if I don't read the dynamic payload length first! If I read the dynamic payload length first, the TX fails.

My code for reading the dynamic payload length using the R_RX_PL_WID command:
CSN = 0;                  // Start SPI communication
SPI_RW(R_RX_PL_WID);      // Write command: Read RX-payload width
PacketLen = SPI_RW(0);    // Read payload width
CSN = 1;                  // End SPI communication)
So somehow the RFM70 gets stuck when using the R_RX_PL_WID, maybe because there is something I missed on how to read this value?
I must add that when I read the payload length value, I do get a valid value, but I must be shutting down the SPI communication in a wrong way?
@Futterama • 04 Oct, 2012 Ohh, I can read the dynamic payload AND make the TX work if I have a small delay (like 1us) between setting CS = 0 to enter standby-1 mode and reading the payload length. So the RFM70 needs a small amount of time before reading the payoad length after CE is set low (to disable RX and enter the standby-1 mode). I don't see this in the datasheet :-(
@Futterama • 04 Oct, 2012 Another thing I noticed. When a packet is received and the IRQ pin goes low, I read the RX_DR bit in the STATUS register, just to make sure the interrupt was caused by reception of a package.

If I disable the RX by setting CE = 0 before I read the STATUS register, RX_DR will be 0. If I wait and set CE = 0 after I have read the STATUS register, RX_DR will be 1.

I don't see this behavior in the datasheet either! And of course I want to disable the RX as soon as I have received a packet to conserve power.
@Harshad Italiya • 05 Oct, 2012
Futterama
Ohh, I can read the dynamic payload AND make the TX work if I have a small delay (like 1us) between setting CS = 0 to enter standby-1 mode and reading the payload length. So the RFM70 needs a small amount of time before reading the payoad length after CE is set low (to disable RX and enter the standby-1 mode). I don't see this in the datasheet :-(
Yes that is required as SPI is little slow for RFM70 and it is also good way to make communication in reliable way.
@Harshad Italiya • 05 Oct, 2012
Futterama
Another thing I noticed. When a packet is received and the IRQ pin goes low, I read the RX_DR bit in the STATUS register, just to make sure the interrupt was caused by reception of a package.

If I disable the RX by setting CE = 0 before I read the STATUS register, RX_DR will be 0. If I wait and set CE = 0 after I have read the STATUS register, RX_DR will be 1.

I don't see this behavior in the datasheet either! And of course I want to disable the RX as soon as I have received a packet to conserve power.
CE is used to for Chip Enable so if you are disabling RX by setting CE = 0 then after any of your command is not going to receive by RFM70 or say any SPI. So you must have to be sure that you have enabled CE pin of any SPI device before you are sending any command to SPI device.

And what I suggest you can use CE in always enable mode if you are communicating with only one SPI device say RFM70.
@Futterama • 05 Oct, 2012 Well, maybe I got some things mixed up. In power down mode, all SPI registers are available. But the datasheet does not say anything about the SPI registers being available in standby-1 mode. It just says that standby-1 mode is the mode the RFM70 returns to after RX or TX when CE is low. But some registers must be available in this mode because I can change the PRIM_RX bit when CE is low. I will take a closer look with the thing in mind that CE is Chip Enable and also "SPI Enable" 😉
@Harshad Italiya • 05 Oct, 2012
Futterama
Well, maybe I got some things mixed up. In power down mode, all SPI registers are available. But the datasheet does not say anything about the SPI registers being available in standby-1 mode. It just says that standby-1 mode is the mode the RFM70 returns to after RX or TX when CE is low. But some registers must be available in this mode because I can change the PRIM_RX bit when CE is low. I will take a closer look with the thing in mind that CE is Chip Enable and also "SPI Enable" 😉
Oh ! Then it would be really messy thing for you to get the list of the registers available in standby-1 mode.

what is your application?
@Futterama • 05 Oct, 2012 I can tell you for sure, many registers are active in standby-1 mode (CE = 0) because I do ALL my initialization with CE held low. My understanding of the function of the CE pin is that it only controls the RFM70 mode between "RX/TX" and "standby-1". So with CE = 0 that RFM70 will enter standby-1 mode and with CE = 1 the RFM70 will enter RX or TX mode, depending on the PRIM_RX bit setting. And to me it makes sense to configure the PRIM_RX bit BEFORE you let the RFM70 enter an active mode (RX or TX).
@Futterama • 05 Oct, 2012
godfather
And what I suggest you can use CE in always enable mode if you are communicating with only one SPI device say RFM70.
I am only communicating with one device. So you mean I should hold CE high at all times? This does not really make sense to me since one of the big advantages of the RFM70 is its ability to maintain a low power consumption using the standby modes.

I will need to make a list of registers readable and writeable in standby-1 mode and also a list of usable SPI commands. Or maybe my contact at HopeRF can give me a good answer (they tend to give short useless answers).
@Harshad Italiya • 05 Oct, 2012
Futterama
I am only communicating with one device. So you mean I should hold CE high at all times? This does not really make sense to me since one of the big advantages of the RFM70 is its ability to maintain a low power consumption using the standby modes.

I will need to make a list of registers readable and writeable in standby-1 mode and also a list of usable SPI commands. Or maybe my contact at HopeRF can give me a good answer (they tend to give short useless answers).
That is another way. If you are getting reply then you have to work less. 😀
@Futterama • 05 Oct, 2012 Yeah, but they have just had a week of holiday, so I guess their mailbox is full of technical questions from customers so I don't expect a quick reply ;-)
@Futterama • 05 Oct, 2012 I tested some of the registers, and it seems like you cannot read the STATUS register when CE = 0. The register content will not be shifted out when writing a SPI command either.
Also there needs to be a small delay (few µs) between setting CE low and issuing the R_RX_PL_WID command, otherwise something in the RFM70 prevents the TX from working until the PWR_UP bit is toggled (sometimes even with a delay between).

Some strange undocumented stuff to take into account when writing code for the RFM70!
@Futterama • 05 Oct, 2012 Oh my god. I still have the same problem, no IRQ on the IRQ pin (and the TX_DS bit is 0) when transmitting a packet unless I go to power down mode first. I even tried with a fresh RFM70 which I have not written anything to Bank1.
It only happens if I received a packet in RX mode before trying to transmit a packet.

The packet is actually transmitted (I received it on the receiver) but the IRQ is not asserted.
@Futterama • 05 Oct, 2012 I don't know what is going on here but this is what I have figured out:

- The RFM70 will not change from PRX to PTX if CE = 1 while you clear the PRIM_RX bit. You need to have CE = 0 when changing state of the PRIM_RX bit or at least toggle CE after making changes to the PRIM_RX bit. In short, the RFM70 will go into whatever mode the PRIM_RX bit indicates at the time CE goes high.
@Futterama • 06 Oct, 2012 • 1 like I started writing notes:

RFM70 notes

Only change mode between RX and TX while CE is low.
In TX mode, set CE high AFTER the payload has been loaded in the TX FIFO.

Transmit a package:
1. CE must be low.
2. Clear the PRIM_RX bit to enable TX mode.
3. Put payload in TX FIFO.
4. Set CE high.
5. Wait for IRQ.
6. Clear the TX_DS bit.
7. Set CE low.
@Harshad Italiya • 08 Oct, 2012
Futterama
I started writing notes:

RFM70 notes

Only change mode between RX and TX while CE is low.
In TX mode, set CE high AFTER the payload has been loaded in the TX FIFO.

Transmit a package:
1. CE must be low.
2. Clear the PRIM_RX bit to enable TX mode.
3. Put payload in TX FIFO.
4. Set CE high.
5. Wait for IRQ.
6. Clear the TX_DS bit.
7. Set CE low.
Good going buddy. you can start new thread for such notes. 😀
@jc_0x0 • 24 Oct, 2012 Hi! I have a question about the RFM70. Is it possible to directly conenct a pressure sensor to the RFM70 without the need of a microcontroller.
@[Prototype] • 24 Oct, 2012
jc_0x0
Hi! I have a question about the RFM70. Is it possible to directly conenct a pressure sensor to the RFM70 without the need of a microcontroller.
If your sensor output is digital then you can connect directly. If it gives analog output then you need ADC.
@Harshad Italiya • 24 Oct, 2012
jc_0x0
Hi! I have a question about the RFM70. Is it possible to directly conenct a pressure sensor to the RFM70 without the need of a microcontroller.
RFM70 is not self programmable You must have to send command via SPI to transmit and receive data. So its not possible that you interface sensor directly with RFM70. You will need microcontroller to send command so in this case Microcontroller is must.
@jc_0x0 • 24 Oct, 2012
godfather
RFM70 is not self programmable You must have to send command via SPI to transmit and receive data. So its not possible that you interface sensor directly with RFM70. You will need microcontroller to send command so in this case Microcontroller is must.
Hi! I am planning to modify this product.
https://www.cdrking.com/?mod=products&type=view&sid=13436&main=148
I want to replace the LCD with the RFm70 module. And since the product has already a microcontroller inside of it, Is it possible to directly connect the RFM70 to the microcontroller of the product?
@jc_0x0 • 24 Oct, 2012
[Prototype]
If your sensor output is digital then you can connect directly. If it gives analog output then you need ADC.
If my output is digital, where will I connect it? In what pins of RFm70?
@Harshad Italiya • 25 Oct, 2012
jc_0x0
Hi! I am planning to modify this product.
https://www.cdrking.com/?mod=products&type=view&sid=13436&main=148
I want to replace the LCD with the RFm70 module. And since the product has already a microcontroller inside of it, Is it possible to directly connect the RFM70 to the microcontroller of the product?
You have to modify even source code of that project. You can not interface any sensor with RFM70. You must have to interface all kind of sensors with microcontroller only. You can directly connect RFM70 with internal microcontroller but you also have to add the code for the same. And if you haven't made that pressure sensor then its difficult.

Alternate way is you can search if your device is sending any data serially. Just use that connection and make another board which can works as a transmitter.
@jc_0x0 • 25 Oct, 2012
godfather
You have to modify even source code of that project. You can not interface any sensor with RFM70. You must have to interface all kind of sensors with microcontroller only. You can directly connect RFM70 with internal microcontroller but you also have to add the code for the same. And if you haven't made that pressure sensor then its difficult.

Alternate way is you can search if your device is sending any data serially. Just use that connection and make another board which can works as a transmitter.
So even if my sensor, an accelerometer, has a digital output, it can't be directly connected to RFM70? It will only transmit. It won't function as receiver. It is because we are planning to put it in a motorcycle helmet.
@Harshad Italiya • 26 Oct, 2012
jc_0x0
So even if my sensor, an accelerometer, has a digital output, it can't be directly connected to RFM70? It will only transmit. It won't function as receiver. It is because we are planning to put it in a motorcycle helmet.
RFM70 can work as a transmitter as well as receiver but you must have to interface it with Microcontroller and whatever program you written for microcontroller it works as transmitter as well as receiver.

So suggested solution is to interface all sensors as well as RFM70 with microcontroller and make your own firmware to achieve task.
@jc_0x0 • 26 Oct, 2012 godfather, can you please help me with my project?

My project is a device for the motorcycle for accidents and theft. The accelerometer, placed in the helmet, will serve as the collision sensor. When triggered, our blood pressure monitoring device will be activated and at the same time, the GPS is also activated. This triggering is done wirelessly, and we are planning to use the RFM70 for the wireless transmission of triggering signal.

Do we need microcontroller for each(accelerometer, Blood pressure monitor and GPS) ?
@Harshad Italiya • 26 Oct, 2012
jc_0x0
godfather, can you please help me with my project?

My project is a device for the motorcycle for accidents and theft. The accelerometer, placed in the helmet, will serve as the collision sensor. When triggered, our blood pressure monitoring device will be activated and at the same time, the GPS is also activated. This triggering is done wirelessly, and we are planning to use the RFM70 for the wireless transmission of triggering signal.

Do we need microcontroller for each(accelerometer, Blood pressure monitor and GPS) ?
You can do all the things via one microcontroller only.
But before that remember if you are using Two RFM70 you need two Microcontroller one for each.

Why you want to measure blood pressure ?
@jc_0x0 • 26 Oct, 2012
godfather
You can do all the things via one microcontroller only.
But before that remember if you are using Two RFM70 you need two Microcontroller one for each.

Why you want to measure blood pressure ?
The accelerometer is placed in the helmet, I plan to interface the accelerometer with the RFM70. The blood pressure monitoring device is placed on the wrist of the user, I plan to interface the RFM70 directly to the microcontroller of the blood pressure monitoring device. And the GPS is placed on the motorcycle, I plan to interface the RFM70, AT89S52 and GPS module.

Is this connection right?


I want to measure the blood pressure so that we can monitor the vital signs of the user when an accident happens.
@dossdss • 26 Oct, 2012
godfather
Should i go ahead? I think people are not interested in RF project.
Ok lets See. 😔
i am a final year engg. student.. n am very much interested in ur guidance..
am trying to study spi in lpc 2148.
so i think i should use RFM70.
so i will let you know my doubts. ok?
@Harshad Italiya • 26 Oct, 2012
jc_0x0
The accelerometer is placed in the helmet, I plan to interface the accelerometer with the RFM70. The blood pressure monitoring device is placed on the wrist of the user, I plan to interface the RFM70 directly to the microcontroller of the blood pressure monitoring device. And the GPS is placed on the motorcycle, I plan to interface the RFM70, AT89S52 and GPS module.

Is this connection right?


I want to measure the blood pressure so that we can monitor the vital signs of the user when an accident happens.
Well your idea is OK. But what I see is to interface RFM70 with blood pressure monitor device is need some technical study. if your device is providing data via UART then you can use RFM70+MCU unit with blood pressure device. Again need to check how you are going to make it handy so it is suitable for wrist belt. Accelerometer+RFM70+MCU on helmet is fine. and GPS on motorcycle is also fine. now you have to also think on how to make all device as small as possible and battery powered.

But this is possible for sure. 👍
@Harshad Italiya • 26 Oct, 2012 Sure feel free to post here whatever you want to ask. 😀
@jc_0x0 • 28 Oct, 2012
godfather
Well your idea is OK. But what I see is to interface RFM70 with blood pressure monitor device is need some technical study. if your device is providing data via UART then you can use RFM70+MCU unit with blood pressure device. Again need to check how you are going to make it handy so it is suitable for wrist belt. Accelerometer+RFM70+MCU on helmet is fine. and GPS on motorcycle is also fine. now you have to also think on how to make all device as small as possible and battery powered.

But this is possible for sure. 👍
So there will be a MCU in the helmet? This is what I understand. And what if it isn't UART? My project becomes more clearer to do because of your help.
@dossdss • 28 Oct, 2012
jc_0x0
The accelerometer is placed in the helmet, I plan to interface the accelerometer with the RFM70. The blood pressure monitoring device is placed on the wrist of the user, I plan to interface the RFM70 directly to the microcontroller of the blood pressure monitoring device. And the GPS is placed on the motorcycle, I plan to interface the RFM70, AT89S52 and GPS module.

Is this connection right?


I want to measure the blood pressure so that we can monitor the vital signs of the user when an accident happens.

now if there is this bp device on wrist, then its gonna be difficult to connect anything to it, as it has to be a small, stand alone, wrist watch like device.
n yes it is; as you have provided in the link above.

you can not interface that device with your mcu , you have to make your own for that purpose.

secondly for that bp device again you have to make one wireless communication may be using rfm70 or something, but then again its hardly gonna fit to your wrist.
@Harshad Italiya • 29 Oct, 2012
jc_0x0
So there will be a MCU in the helmet? This is what I understand. And what if it isn't UART? My project becomes more clearer to do because of your help.
As you are using accelerometer and RFM70 with MCU on helmet no need of UART as you can directly interface accelerometer and RFM70 via SPI. Now you have to communicate with the other device placed on motorcycle and one more with Blood pressure monitor device.

Feel free to ask questions.
@kind2011 • 21 Nov, 2012 where can i find the datasheet for RFM70 module with the communication specs?
thanks!
@lilayko • 22 Nov, 2012 Hi godfather,
I'm a PhD student and for my project I need to send a 20kHz signal but the maximum I received is 2kHz. I use an RFM70 module with a pic18 (pikit3). I use the HOPE RF program and I tried to speed up the tranmitted signal with an adaptation of the clock (T2CON= 0x7f; PR2=255; OSCTUNEbits.PLLEN=1), I reduced the transmitted signal (3 bytes) and I changed some parameters of the RFM70 (data rate: 2M; interrupt not reflected on IRQ; auto retransmission delay: 250us; disable auto aknowledgement).
Do you know what can I do to obtain a 20kHz signal on the output pin of the received pic18?

Regards
@Harshad Italiya • 30 Nov, 2012
kind2011
where can i find the datasheet for RFM70 module with the communication specs?
thanks!
you can find same on Hope RF website www.hoperf.com
@Harshad Italiya • 30 Nov, 2012
lilayko
Hi godfather,
I'm a PhD student and for my project I need to send a 20kHz signal but the maximum I received is 2kHz. I use an RFM70 module with a pic18 (pikit3). I use the HOPE RF program and I tried to speed up the tranmitted signal with an adaptation of the clock (T2CON= 0x7f; PR2=255; OSCTUNEbits.PLLEN=1), I reduced the transmitted signal (3 bytes) and I changed some parameters of the RFM70 (data rate: 2M; interrupt not reflected on IRQ; auto retransmission delay: 250us; disable auto aknowledgement).
Do you know what can I do to obtain a 20kHz signal on the output pin of the received pic18?

Regards
So you have problem in receiving data? there is some limitation but for exact figure i need to check.
@lilayko • 10 Dec, 2012
godfather
So you have problem in receiving data? there is some limitation but for exact figure i need to check.
I send you my receiver code based on the Hope RF exemple with some modifications.
Regards
@Harshad Italiya • 11 Dec, 2012
lilayko
I send you my receiver code based on the Hope RF exemple with some modifications.
Regards
I will check it. will you please tell me what is your exact problem?
@lilayko • 11 Dec, 2012
godfather
I will check it. will you please tell me what is your exact problem?
With the code I send to you, the maximal signal I have at the outputof the pic18 (port D) is 2kHz. I need 20kHz. The information I need to send by RFM70 is a 3 bytes data. Theoretically I can have a 20kHz reception but There is something which limits the speed of the reception (or of the transmission) signal. Can you help me to find What I need to change in the code in order to rise up the frequency of the signal I receive.
@rikil • 26 Dec, 2012 I've got a pair of RFM70 and I am trying to understand the interface. But honestly, it is very confusing as compared to CC2500.

I understood the initialization of module and sample code is good enough for that. But communication part is really tricky.😨
Can someone just sum up the steps for sending and receiving data?
@Harshad Italiya • 27 Dec, 2012
rikil
I've got a pair of RFM70 and I am trying to understand the interface. But honestly, it is very confusing as compared to CC2500.

I understood the initialization of module and sample code is good enough for that. But communication part is really tricky.😨
Can someone just sum up the steps for sending and receiving data?
It is same as given in reference code if you follow same code you can easily send receive data. Can you tell me where exactly you stuck?

Is SPI working properly?
@rikil • 27 Dec, 2012 I am confused about the steps of sending and receiving data. As far as SPI is concerned, I will be using Hardware SPI which I am learning right now. So will let you know about it.
@Harshad Italiya • 04 Jan, 2013
rikil
I am confused about the steps of sending and receiving data. As far as SPI is concerned, I will be using Hardware SPI which I am learning right now. So will let you know about it.
Sure let me know once you complete your SPI functionality. As it is must DO work.
@ahp • 12 Mar, 2013 hi
@ahp • 12 Mar, 2013 Im doing a project base on wireless communication .main aim of my
project is i want to on and off the water pump motor which is far from
us . and if ther is no water in well then i want to give some
indication to our so 2 way communication can be done. I am using 2
different RFM70 transceiver modules.and they are interface to a 2
differant PIC microcontroller. But I am not able to programe it.
Interfacing will be done by reading datasheet, but I am having a
problem in the program. So please give me whole programing for my
project. It will helpfull for me.
@ngndangtan • 19 May, 2013 Hi godfather!
Im newbie at this forum.

I have been working with the RFM70 too.And I want to communicate many Rfm70's moduls.But i don't understand about change address to communicate many moduls.
Sory about English
@ngndangtan • 19 May, 2013 #ifdef device1
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x01}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x02};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x03};////Receive address data pipe 1
#endif

#ifdef device2
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x02}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x03};////Receive address data pipe 1
#endif

#ifdef device3
const UINT8 Tx_address[] ={0x00,0x00,0x00,0x00,0x03}; // Transmitter Address.
const UINT8 RX0_Address[]={0x00,0x00,0x00,0x00,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x00,0x00,0x00,0x00,0x02};////Receive address data pipe 1
#endif

and


for(j=0;j<5;j++)
{
WriteArr[j]=RX0_Address[j];
}
SPI_Write_Buf((WRITE_REG|10),&(WriteArr[0]),5);

//REG 11 - Rx1 addr
for(j=0;j<5;j++)
{
WriteArr[j]=RX1_Address[j];
}
SPI_Write_Buf((WRITE_REG|11),&(WriteArr[0]),5);

//REG 16 - TX addr
for(j=0;j<5;j++)
{
WriteArr[j]=Tx_address[j];
}
SPI_Write_Buf((WRITE_REG|16),&(WriteArr[0]),5);


so i want >3 moduls communicate so what?
@ngndangtan • 19 May, 2013 i see about example code I see:
const UINT8 RX0_Address[]={0x34,0x43,0x10,0x10,0x01};//Receive address data pipe 0
const UINT8 RX1_Address[]={0x39,0x38,0x37,0x36,0xc2};////Receive address data pipe 1
and
/*//reg 10 - Rx0 addr
SPI_Write_Buf((WRITE_REG|10),RX0_Address,5);

//REG 11 - Rx1 addr
SPI_Write_Buf((WRITE_REG|11),RX1_Address,5);

//REG 16 - TX addr
SPI_Write_Buf((WRITE_REG|16),RX0_Address,5);*/
but it work so what?
sorry about English
@Harshad Italiya • 20 May, 2013
ngndangtan
Hi godfather!
Im newbie at this forum.

I have been working with the RFM70 too.And I want to communicate many Rfm70's moduls.But i don't understand about change address to communicate many moduls.
Sory about English
First of all tell me are you able to Read SPI properly? If yes then Simply Swap Tx_address and RX0_Address while programming both boards.
@ngndangtan • 21 May, 2013
Harshad Italiya
First of all tell me are you able to Read SPI properly? If yes then Simply Swap Tx_address and RX0_Address while programming both boards.
Hi godfather!
I read spi finish by coping example code.And I set address about 2 device and it ok.So
I don't set enable pipe 2,3,4,5.
this is code but it don't work open pipe 2,3,4,5
//**************************************************************************
//
//! \mainpage rfm70
//!
//! C interface library for the HopeRF RFM70 4.3 GHz transceiver module
//!
//! \image html RFM70-D.jpg
//! \image rtf RFM70-D.jpg
//!
//! \author
//!    Wouter van Ooijen (wouter@voti.nl)
//!
//! \version
//!    V1.02 (2011-12-31)
//!
//! \par Introduction
//!
//! The RFM70 module from HopeRF (www.hoperf.com) is a small and cheap
//! transceiver (transmitter + receiver) module for the license-free
//! 4.3 MHz frequency band. This module is intended for short range
//! communication, for instance within a room.
//! Typical applications are wires mouses and keybords,
//! and garage door openers.
//! In open air a distance of
//! 50 .. 100 m is possible, but this is strictly line-of-sight: even
//! the leaves of a single tree can obstruct the signal.
//!
//! The two main files in this libary, rfm70.h and rfm70.c,
//! are target independent.
//! However, rfm70.c included by a file that must be provided
//! by the user.
//! This file must provide macro's for initializing and accessing the
//! I/O pins that connect to the RFM70 module, and for
//! delays of a specified number of milliseconds and microseconds.
//! A template for this file is provided.
//!
//! \par Files
//! - rfm70.h
//! - rfm70.c
//! - rfm70-config.h
//!
//!
//! \par License
//!
//! The files in this library are licensed under the zlib license,
//! which rougly says: when you redistribute the *source* you must
//! keep the copyright notice intact. Otherwise you can use these files
//! any way you like, including getting rich from selling applications.
//! But don't complain to me when it does not work (OTOH, contructive
//! comments are appreciated!).
//!
//! \par ToDo: bugs, notes, pitfalls, todo, known problems, etc
//!
//! - pictures for power
//! - document (other) files
//! - PIC18F examples, Cortex C examples, Arduino
//! - write 5 bytes when address <5 bytes?
//! - check and improve rtf documentation
//! - check CE cycling requirements
//! - descriptions for the other files
//! - add write ack payload for pipe N
//! - add 'report package has been sent'
//! - application: thermometer
//! - application: test signal strength
//! - application: asynch serial through the air
//!
//
//***************************************************************************//
 
//***************************************************************************//
//
// COPYRIGHT NOTICE (zlib license)
//
// Loosely based on the example application provided by HopeRF
//
// (c) Wouter van Ooijen - wouter@voti.nl
//
//  This software is provided 'as-is', without any express or implied
//  warranty.  In no event will the authors be held liable for any damages
//  arising from the use of this software.
//
//  Permission is granted to anyone to use this software for any purpose,
//  including commercial applications, and to alter it and redistribute it
//  freely, subject to the following restrictions:
//
//  1. The origin of this software must not be misrepresented; you must not
//    claim that you wrote the original software. If you use this software
//    in a product, an acknowledgment in the product documentation would be
//    appreciated but is not required.
//  2. Altered source versions must be plainly marked as such, and must not be
//    misrepresented as being the original software.
//  3. This notice may not be removed or altered from any source distribution.
//
//***************************************************************************//
 
//***************************************************************************//
//
//! \page revision information
//!
//! \par ToDo: bugs, notes, pitfalls, todo, known problems, etc
//!
//! - pictures for power
//! - document (other) files
//! - PIC18F examples, Cortex C examples, Arduino
//! - write 5 bytes when address <5 bytes?
//! - check and improve rtf documentation
//! - check CE cycling requirements
//! - descriptions for the other files
//! - add write ack payload for pipe N
//! - add 'report package has been sent'
//! - application: thermometer
//! - application: test signal strength
//! - application: asynch serial through the air
//!
//! \par release notes
//!
//! V1.02 (2011-12-31)
//! Arduino added
//!
//! V1.01 (2011-12-26)
//! some minor documentation and webpage changes, no code changes
//!
//! V1.00 (2011-12-24)
//! first release
//!
//
//***************************************************************************//
 
//***************************************************************************//
//
//! \page overview RFM70 overview
//!
//! \image html smd-pins.jpg
//! \image rtf smd-pins.jpg
//!
//! The RFM70 is a small module (PCB with some components, ~ 18 x 26 mm)
//! that implements a transciever for the license-free 4.3 GHz band.
//! The module contains a small antenna on the PCB,
//! there is no provision for an external antenna.
//! Two versions of the module exist, one with
//! pins and one without. The pins are on a 1.28 mm grid, which is twice the
//! density of a standard DIL package. The module requires 1.9 .. 3.6 Volt
//! for its power, 3.3 Volt seems to be the preferred operating voltage.
//! It is NOT designed to run at 5.0 Volt.
//! According to the datasheet that maximum 'typical' operating current
//! is 23 mA.
//!
//! Note that 'licence free' means that certain well-described use of this
//! frequency band is allowd without a license.
//! The RFM70 is designed to be compatible with the requirements for such
//! use, but it is the responsibility of anyone who sells a product that
//! to make sure that it complies with such rules.
//!
//! The main component of an RFM70 module is the RF70 chip (hidden beneath
//! the black blob). The manufacturer provides separate datasheets for both
//! the RF70 chip and the RFM70 module.
//! The two datasheets seem to be the same, except for the physical
//! and pinout information which is of course different for the chip
//! and the module, so you can probably ignore the RF70 chip datasheet.
//! The RFM70 module datasheet can currently be found at
//! https://www.hoperf.com/upload/rf/RFM70.pdf
//!
//! The RFM70 module is intended for short-range communication,
//! like wireless computer peripherals (mouse, keyboard, tablet, ect.)
//! keyfobs (car opener, garage door opener, motorized fence opener -
//! some cryptografy will probably be required for such applications)
//! and toys. In a line of sight situation a maximum range of 50 .. 100 m
//! is possible. Indoors communication within a single room will generally
//! be OK (unless you have a very large room..) but passing even a single
//! wall can be a problem.
//!
//! An RFM70 module must be used with a microcontroller that initializes
//! and operates the module. By itself the module can not be used as a
//! 'wireless wire', although such a mode could be implemented in the
//! microcontroller. The interface between the RFM70 and the microcontroller
//! is a standard 4-PIN SPI interface (MISO, MOSI, CLCK, CSN) plus a CE
//! (Chip Enable) pin. The module also provides an IRQ pin that could be used
//! to speed up the detection of certain events within the module.
//! The library does not used this pin.
//! The SPI input pins are 5V-tolerant, so provided that
//! the high level as output by the module is accpetable to the
//! microcontroller no glue circuitry is needed to interface to a
//! microcontroller that runs from 5 Volt. (Except for course for a
//! regulator that provides the 3.3 Volt to power the RFM70.)
//!
//! An RFM70 module operates in the 4.3 GHz band.
//! Within that band a frequency can be selected in 1 MHz steps.
//! RFM70 modules can communicate only when they use the same frequency.
//!
//! The RFM70 module operates on a packet basis.
//! Each packet has a destination address.
//! By default the address is a 5 byte value, but a 4 or 3 byte
//! address can also be configured.
//! For succesfull communication the RFM70 modules that are involved must
//! be configures for the same address length, and the receiving
//! module(s) must have one of their so-called pipes configured
//! for the address used by the transmitter.
//!
//! An RFM70 contains 6 so-called data pipes that can receive packages.
//! Each pipe has an address, and will receive only messages
//! for that address.
//! Pipes 0 and 1 have a full (up to 5 bytes) address.
//! For pipes 2 .. 6 only the least significant byte can be
//! configured, the other bytes are copied from the address of pipe 1.
//! The length of the address (3, 4 or 5 bytes) is the same for
//! transmission and for all 6 receive data pipes.
//!
//! A packet contains 1 .. 32 user data bytes.
//! The packet length can either be fixed or flexible.
//! When the packet length is fixed each receiving pipe is configured
//! with its packet length. The length of a package that is sent is
//! determined by the number of bytes written into the transmit buffer,
//! and it it must match the length configured for the receiving pipe.
//! When the packet length is flexible the length of a package is again
//! determined by the number of bytes written into the transmit, but in
//! this case this number is transmitted in the message, and on the
//! receiving side it can be retrieved by the R_RX_PL_WID command
//! (rfm70_channel_payload_size function).
//!
//! The simple way to send a package is without acknowledgement.
//! The RFM70 just transmits the package and considers it done.
//! It can be received by zero, one, or multiple RFM70 modules, but
//! the sending modules does not care and has no way of knowing.
//! For this simple mode of communication the involved RFM70's
//! - must be configured for the same channel frequency
//! - must use the same address length
//! - the receiving RFM70 must have a receive pipe configured
//!  for the same address as used by the transmitting RFM70
//!
//! Alternatively a package can be sent with acknowledgement and
//! (if necessary) retransmission.
//! In this case the RFM70 will send the message, and consider it
//! done only when it receives an acknowledge for it.
//! If it does not receive an acknowledge within a fixed amount of
//! time it will re-transmit the package, up to a set maximum.
//! A receiving RFM70 can automatically send an acknowledgement
//! for a successfully received package.
//! For this to work the same requirements as for simple unacknowledged
//! communicatiobn apply, and additionally on both RFM70's
//! - CRC must be enabled (length 1 or 2) on both modules
//! - receive data pipe 0 must be configured for the same address
//!  as the module uses for transmitting
//!
//! The automatic retransmission provided by the RFM70 uses a fixed
//! retransmission timout, which is probly fine for correcting an
//! occasional packet loss due to interference from other 4.3 GHz sources,
//! but it is potentially inefective when the interference is caused by
//! another RFM70 that uses the same timout! In such cases the
//! microcontroller should implemnet its own retransmission scheme,
//! with for instance a random timeout, and maybe an exponential
//! backoff.
//!
//
//***************************************************************************//
 
//***************************************************************************//
//
//! \page hardware RFM70 hardware interface
//!
//! \image html smd-pins.jpg
//! \image rtf smd-pins.jpg
//!
//! The RFM70 uses a standard 4-wire SPI interface.
//! It also provides an active low interrupt pin, which could be used to
//! avoid polling. This library does not use the interrupt pin.
//! The RFM70 also has a CE (chip enable) input, which must be de-asserted
//! to put the chip in standby or power-down mode, and must be cycled
//! to switch between receive and transmit mode. Hence the interface
//! uses 5 data pins, plus ground and power (3.3V):
//! - GND : common ground
//! - VDD : 3.3V power
//! - CE : Chip Enable, active high, microcontoller output
//! - CSN : Chip Select Negative, active low, microcontoller output
//! - SCK : Serial ClocK, microcontoller output
//! - MOSI : Master Out Slave In, microcontoller output
//! - MISO : Master In Slave Out, microcontoller input
//! - IRQ : Interrupt ReQuest, not used
//!
//! When the microcontroller operates at 3.3 Volt (or lower,
//! the RFM70 datasheet claims operation down to 1.9 Volt) all lines,
//! including power, 
//! can be connected directly to the microcontroller.
//! If you are experimenting and want to protect yourself against
//! problems when you accidentally configure the pin connected to MISO
//! as output, you could insert a suitable series resistor in this line.
//! 2k2 seems to be a good choice.
//!
//! When the microcontroller operates at 5 Volt there are three possible issues:
//! - power : the RFM70 operates at 1.9 .. 3.3 Volt, so the 5 Volt must somehow
//!  be reduced to a voltage within this range
//! - data from the microcontroller to the RFM70 : no problem here, the
//!  RFM70 inputs are 5 Volt tolerant.
//!  As explained, a series resistor in the MISO line might be a good idea.
//! - data from RFM70 to the microcontroller : in most cases this will not
//!  be a problem, but you might want to check the minimum voltage required
//!  by your microcontroller to reliably detect a logic 1. For instance a
//!  PIC requires ~ 2.0 Volt on a TTL level input, but 0.8 * VDD on a
//!  Schmitt Trigger input! And you must consider this at the maximum VDD
//!  for the microcontroller, which can be 5.5 Volt when delivered by
//!  an 7805 or an USB port.
//!
//! There are various ways to create a 3.3 Volt supply for the RFM70 from a
//! 5 Volt supply. I prefer to use a low-drop low-quiecent
//! current 3.3 Volt linear regulator. Read the datasheet of the regulator
//! carefully: some put very stringent requirements on the value and impedance
//! of the decoupling capacitors. My favourite is the Microchip MCP1702,
//! which has a low quiecent current (5 uA maximum), and is stable with
//! only 1 uF input an output capacitors of any type
//! (ceramic, tantalum, aluminium electrolytic).
//!
//! TBW: picture
//!
//! A crude way to create the power for the RFM70 is to use a
//! resistor divider. I would do this only in an experimental
//! setup on my desk, never in a final product.
//! The source impedance of the divider causes a drop in the
//! voltage when the RFM70 uses more current.
//! This drop can be reduced by lowering the resistor values, but at
//! the cost of a higher current through the resistors. The RFM70
//! can operate down to 1.9 Volt, but at that level the microcontroller
//! might not reliably recognise a logic 1 from the RFM70. Another issue
//! is the dissipation in the resistors. The circuit below is a compromise.
//! It uses three equal-valued resistors because I don't stock many
//! different resistor values.
//! The idle current through the resistors is 83 mA at 5.5 Volt, in
//! this situation the RFM70 gets 3.7 Volt. That is slightly high, but
//! probably not a big problem.
//! When the RFM70 draws its maximum current of 23 mA when the
//! microcontroller's power is at 4.5 Volt the RFM70 still gets 2.6 Volt.
//! You might want to double-check that the microcontroller accepts ~ 2 Volt
//! as a logic 1.
//!
//! TBW: picture
//!
//
//***************************************************************************//
 
#include "rfm70.h"
#include "rfm70-config.h"
#include "main.h"
 
// RFM70 SPI read and write commands
#define RFM70_CMD_READ_REG            0x00
#define RFM70_CMD_WRITE_REG          0x20
 
//interrupt status
#define STATUS_RX_DR    0x40
#define STATUS_TX_DS    0x20
#define STATUS_MAX_RT  0x10
 
#define STATUS_TX_FULL  0x01
 
//FIFO_STATUS
#define FIFO_STATUS_TX_REUSE  0x40
#define FIFO_STATUS_TX_FULL  0x20
#define FIFO_STATUS_TX_EMPTY  0x10
 
#define FIFO_STATUS_RX_FULL  0x02
#define FIFO_STATUS_RX_EMPTY  0x01
 
 
 
// Bank0 register initialization values
#define BANK0_ENTRIES 10
const unsigned char Bank0_Reg[ BANK0_ENTRIES ][ 2 ]={
  {  0, 0x0F }, // receive, enabled, CRC 2, enable interupts
  {  1, 0x3F }, // auto-ack on all pipes enabled
  {  2, 0x3f }, // Enable pipes 0 and 1
  {  3, 0x03 }, // 5 bytes addresses
  {  4, 0xff }, // auto retransmission delay 4000 ms, 15 times
  {  5, 0x0A }, // channel 10
  {  6 ,0x37 }, // data rate 1Mbit, power 5dbm, LNA gain high
  {  7, 0x07 }, // why write this at all?? but seems required to work...
  {  8, 0x00 }, // clear Tx packet counters
  { 23, 0x00 }, // fifo status
};
 
  // default receive address data pipe 0:
  // just a bunch of bytes, nothing magical
//const unsigned char RX0_Address[]={ 0x34, 0x43, 0x10, 0x10, 0x01 };
const unsigned char Tx_address[] ={0x00,0x00,0x00,0x00,0x01}; // Transmitter Address.
const unsigned char RX0_Address[]={0x00,0x00,0x00,0x00,0x02};//Receive address data pipe 0
const unsigned char RX1_Address[]={0x00,0x00,0x00,0x00,0x03};////Receive address data pipe 1
 
unsigned char rfm70_SPI_RW( unsigned char value ){
  unsigned char i;
  for( i =0 ; i < 8; i++ ){
       
      RFM70_WAIT_US( 1 );
      if((value & 0x80)!=0)  RFM70_MOSI(1); 
      if((value & 0x80)==0)  RFM70_MOSI(0);
//      RFM70_MOSI( value & 0x80  );     
      value = (value << 1);    // shift next bit into MSB..
     
      RFM70_WAIT_US( 1 );
      RFM70_SCK( 1 );         
      value |= RFM70_MISO;    // capture current MISO bit
     
      RFM70_WAIT_US( 1 );
      RFM70_SCK( 0 );
      RFM70_WAIT_US( 1 );
  }
  return value;
}
 
void rfm70_register_write( unsigned char reg, unsigned char value ){
  if( reg < RFM70_CMD_WRITE_REG ){
      reg |= RFM70_CMD_WRITE_REG;     
  } 
  RFM70_CSN( 0 );                // CSN low, init SPI transaction
  (void)rfm70_SPI_RW( reg );    // select register
  (void)rfm70_SPI_RW( value );  // ..and write value to it..
  RFM70_CSN( 1 );                // CSN high again
}
 
unsigned char rfm70_register_read( unsigned char reg ){
  unsigned char value;
       
  if( reg < RFM70_CMD_WRITE_REG )
        {
      reg |= RFM70_CMD_READ_REG; 
  } 
   
  RFM70_CSN( 0 );              // CSN low, initialize SPI communication...   
  (void)rfm70_SPI_RW( reg );  // Select register to read from..
           
  value = rfm70_SPI_RW( 0 );  // ..then read register value
  RFM70_CSN( 1 );              // CSN high, terminate SPI communication
  return value;                // return register value
}
 
void rfm70_buffer_read(
  unsigned char reg,
  unsigned char *pBuf,
  unsigned char length
){
  unsigned char i;
  if( reg < RFM70_CMD_WRITE_REG ){
      reg |= RFM70_CMD_READ_REG;     
  } 
  RFM70_CSN( 0 );                  // Set CSN 0
  (void)rfm70_SPI_RW( reg );      // Select register to write
  for( i = 0; i < length; i++ ){    // read all bytes
      *pBuf++ = rfm70_SPI_RW( 0 );  // read one byte from RFM70
  }
  RFM70_CSN( 1 );                  // Set CSN high again
}
 
void rfm70_buffer_write(
  char reg,
  const unsigned char *pBuf,
  unsigned char length
){
  unsigned char i;
  if( reg < RFM70_CMD_WRITE_REG ){
      reg |= RFM70_CMD_WRITE_REG;     
  } 
  RFM70_CSN( 0 );                    // Set CSN low, init SPI tranaction
  (void)rfm70_SPI_RW( reg );        // Select register to write tio write
  for( i = 0; i < length; i++ ){      // write all bytes in buffer(*pBuf)
      (void)rfm70_SPI_RW( *pBuf++ );  // write one byte
  } 
  RFM70_CSN( 1 );                    // Set CSN high again
}
 
void rfm70_bank( unsigned char b )
{
 
  unsigned char st =(0x80 & rfm70_register_read( RFM70_REG_STATUS ));
 
 
  if(( st &&( b == 0 )) || (( st == 0 ) && b ))
        {
      rfm70_register_write( RFM70_CMD_ACTIVATE, 0x53 );
  }
}
 
  // magic bank1 register initialization values
const unsigned long Bank1_Reg0_13[] = {
  0xE2014B40,
  0x00004BC0,
  0x028CFCD0,
  0x41390099,
  0x0B869Ef9,
  0xA67F0624,
  0x00000000,
  0x00000000,
  0x00000000,
  0x00000000,
  0x00000000,
  0x00000000,
  0x00127300,
  0x36B48000 }; 
 
  // more magic bank1 register initialization values
const unsigned char Bank1_Reg14[] = {
  0x41, 0x20, 0x08, 0x04, 0x81, 0x20, 0xCF, 0xF7, 0xFE, 0xFF, 0xFF }; 
 
  // initialize bank1 like in the example code.
  // don't ask why, just do it
void rfm70_init_bank1( void ){
  unsigned char i, j;
  unsigned char WriteArr[ 12 ];
       
  rfm70_bank( 1 );
 
  for( i = 0; i <= 8; i++ ){ //reverse!
      for( j = 0; j < 4; j++ ){
        WriteArr[ j ]=( Bank1_Reg0_13[ i ]>>(8*(j) ) )&0xff;
      } 
      rfm70_buffer_write( i,WriteArr, 4 );
  }
 
  for( i = 9; i <= 13; i++ ){
      for( j = 0; j < 4; j++ ){
        WriteArr[ j ]=( Bank1_Reg0_13[ i ]>>(8*(3-j) ) )&0xff;
      }
      rfm70_buffer_write( i, WriteArr, 4 );
  }
 
  rfm70_buffer_write( 14, Bank1_Reg14, 11 );
 
  //toggle REG4<25,26>
  for(j=0;j<4;j++){
      WriteArr[ j ]=( Bank1_Reg0_13[ 4 ]>>(8*(j) ) )&0xff;
  }
 
  WriteArr[ 0 ] = WriteArr[ 0 ] | 0x06;
  rfm70_buffer_write( 4, WriteArr, 4);
 
  WriteArr[ 0 ] = WriteArr[ 0 ] & 0xf9;
  rfm70_buffer_write( 4, WriteArr,4);
 
  rfm70_bank( 0 );
}
 
unsigned char rfm70_is_present( void ){
  unsigned char st1, st2;
  st1 = rfm70_register_read( RFM70_REG_STATUS );
  rfm70_register_write( RFM70_CMD_ACTIVATE, 0x53 );
  st2 = rfm70_register_read( RFM70_REG_STATUS );
  rfm70_register_write( RFM70_CMD_ACTIVATE, 0x53 );
  return ( st1 ^ st2 ) == 0x80;
}
 
void rfm70_mode_receive( void ){
  unsigned char value;
 
  // flush receive queue
  rfm70_register_write( RFM70_CMD_FLUSH_RX, 0 );
 
  // clear interrupt status
  value = rfm70_register_read( RFM70_REG_STATUS );
  rfm70_register_write( RFM70_REG_STATUS ,value );
 
  // switch to receive mode
  RFM70_CE( 0 );
  value = rfm70_register_read( RFM70_REG_CONFIG );
  value |= 0x01; // set RX bit
  value |= 0x02; // set PWR_UP bit
  rfm70_register_write( RFM70_REG_CONFIG, value );
  RFM70_CE( 1 );
}
 
void rfm70_mode_transmit( void ){
  unsigned char value;
 
  // flush transmit queue
  rfm70_register_write( RFM70_CMD_FLUSH_TX, 0);
 
  // clear interrupt status
  value = rfm70_register_read( RFM70_REG_STATUS );
  rfm70_register_write( RFM70_REG_STATUS ,value );
 
  // switch to transmit mode
  RFM70_CE( 0 );
  value = rfm70_register_read( RFM70_REG_CONFIG );
  value &= 0xFE; // clear RX bit
  value |= 0x02; // set PWR_UP bit
  rfm70_register_write( RFM70_REG_CONFIG, value );
  RFM70_CE( 1 );
}
 
void rfm70_mode_standby( void ){
  unsigned char value;
  RFM70_CE( 0 );
  value = rfm70_register_read( RFM70_REG_CONFIG );
  value |= 0x02; // set PWR_UP bit
  rfm70_register_write( RFM70_REG_CONFIG, value );
}
 
void rfm70_mode_powerdown( void ){
  unsigned char value;
  RFM70_CE( 0 );
  value = rfm70_register_read( RFM70_REG_CONFIG );
  value &= 0xFD; // clear PWR_UP bit
  rfm70_register_write( RFM70_REG_CONFIG, value );
}
 
void rfm70_channel( unsigned char ch ){
  // MSB must be 0
  rfm70_register_write( RFM70_REG_RF_CH, ch & 0x7E );
}
 
void rfm70_air_data_rate( unsigned char rate ){
  unsigned char value;
  RFM70_CE( 0 );
  value = rfm70_register_read( RFM70_REG_RF_SETUP );
  value &= 0xF7;
  if( rate > 1 ){
      value |= 0x08; 
  }
  rfm70_register_write( RFM70_REG_RF_SETUP, value );
  RFM70_CE( 1 );
}
 
void rfm70_crc_length( unsigned char len ){
  unsigned char val;
  if( len > 2 ){
      len = 2;
  } 
  val = rfm70_register_read( RFM70_REG_CONFIG );
  if( len == 0 ){
      val &= 0xF3;
      rfm70_register_write( RFM70_REG_EN_AA, 0 );
      rfm70_register_write( RFM70_REG_CONFIG, val );
  } else {
      rfm70_register_write( RFM70_REG_EN_AA, 0x3F );
      val &= 0xFB;
      if( val == 2 ){
        val |= 0x04;
      } 
      rfm70_register_write( RFM70_REG_CONFIG, val );
  } 
}
 
void rfm70_address_length( unsigned char len ){
  if( len > 5 ){
      len = 5;
  }
  if( len < 3 ){
      len = 3;   
  }
  rfm70_register_write( RFM70_REG_SETUP_AW, len - 2  ); 
}
 
unsigned char rfm70_transmit_fifo_full( void ){
  unsigned char s;
  s = rfm70_register_read( RFM70_REG_FIFO_STATUS );
  return ( s & FIFO_STATUS_TX_FULL ) != 0;
}
   
unsigned char rfm70_receive_fifo_empty( void ){
  unsigned char s;
  s = rfm70_register_read( RFM70_REG_FIFO_STATUS );
  return ( s & FIFO_STATUS_RX_EMPTY ) != 0;
}
 
void rfm70_receive_address_p0( const unsigned char address[ 5 ] ){
  rfm70_buffer_write( RFM70_REG_RX_ADDR_P0, address, 5 ); 
}
 
void rfm70_receive_address_p1( const unsigned char address[ 5 ] ){
  rfm70_buffer_write( RFM70_REG_RX_ADDR_P1, address, 5 ); 
}
 
void rfm70_receive_address_pn( unsigned char channel, unsigned char address ){
  rfm70_register_write( RFM70_REG_RX_ADDR_P0 + channel, address );
}
 
void rfm70_transmit_address( const unsigned char *address ){
  rfm70_buffer_write( RFM70_REG_TX_ADDR, address, 5 ); 
}
 
unsigned char rfm70_retransmit_count( void ){
  return rfm70_register_read( RFM70_REG_OBSERVE_TX ) & 0x0F; 
}
 
unsigned char rfm70_lost_packets_count( void ){
  return ( rfm70_register_read( RFM70_REG_OBSERVE_TX ) >> 4 ) & 0x0F; 
}
 
void rfm70_pipe_autoack( unsigned char pipe, unsigned char enabled ){
  unsigned char val = rfm70_register_read( RFM70_REG_EN_AA );
  if( pipe > 5 ){
      pipe = 5;
  } 
  if( enabled ){
      val |= 1 << pipe;
  } else {
      val &= ~ ( 1 << pipe );
  }
  rfm70_register_write( RFM70_REG_EN_AA, val );
}
 
void rfm70_pipe_enable( unsigned char pipe, unsigned char enabled ){
  unsigned char val = rfm70_register_read( RFM70_REG_EN_RXADDR );
  if( pipe > 5 ){
      pipe = 5;
  } 
  if( enabled ){
      val |= 1 << pipe;
  } else {
      val &= ~ ( 1 << pipe );
  }
  rfm70_register_write( RFM70_REG_EN_RXADDR, val );
}
 
void rfm70_lost_packets_reset( void ){
  unsigned char val = rfm70_register_read( RFM70_REG_RF_CH ); 
  rfm70_register_write( RFM70_REG_RF_CH, val );   
}
 
void rfm70_retransmit_delay_attempts( unsigned char d, unsigned char n ){
  rfm70_register_write(
      RFM70_REG_SETUP_RETR, ( n & 0x0F ) | (( d & 0x0F ) << 4 ));
}
 
void rfm70_lna_high( void ){
  unsigned char val = rfm70_register_read( RFM70_REG_RF_SETUP );
  val |= 0x01;
  rfm70_register_write( RFM70_REG_RF_SETUP, val );
}
 
void rfm70_lna_low( void ){
  unsigned char val = rfm70_register_read( RFM70_REG_RF_SETUP );
  val &= 0xFE;
  rfm70_register_write( RFM70_REG_RF_SETUP, val );
}
 
void rfm70_power( unsigned char level ){
  unsigned char val;
   
  if( level > 3 ){
      level = 3;
  }
  RFM70_CE( 0 );
  val = rfm70_register_read( RFM70_REG_RF_SETUP );
  val &= 0x09;
  val |= 0x30;
  val |= ( level << 1 );
  rfm70_register_write( RFM70_REG_RF_SETUP, val );
  RFM70_CE( 1 );
}
 
void rfm70_channel_payload_size( unsigned char channel, unsigned char size ){
  unsigned char val;
  if( size > 32 ){
      size = 32;
  }
  val = rfm70_register_read( RFM70_REG_DYNPD ); 
  if( size == 0 ){
      val |= 1 << channel;
  } else {
      val &= ~ ( 1 << channel );
  }   
  rfm70_register_write( RFM70_REG_DYNPD, val );
  rfm70_register_write( RFM70_REG_RX_PW_P0 + channel, size ); 
}
 
void rfm70_transmit_message(
  const unsigned char *buf,
  unsigned char length
){
  if( length > 32 ){
      length = 32;
  }
  rfm70_buffer_write( RFM70_CMD_W_TX_PAYLOAD, buf, length );
}
   
void rfm70_transmit_message_once(
  const unsigned char *buf,
  unsigned char length
){
  if( length > 32 ){
      length = 32;
  }
  rfm70_buffer_write( RFM70_CMD_W_TX_PAYLOAD_NOACK, buf, length );
}
 
unsigned char rfm70_receive_next_pipe( void ){
  unsigned char status = rfm70_register_read( RFM70_REG_STATUS );
  return ( status >> 1 ) & 0x07;
}
 
unsigned char rfm70_receive_next_length( void ){
  return rfm70_register_read( RFM70_CMD_R_RX_PL_WID );
}
 
unsigned char rfm70_receive(
  unsigned char * pipe,
  unsigned char *buf,
  unsigned char * length
){
  unsigned char p = rfm70_receive_next_pipe();
  if( p == 0x07 ){
      return 0;
  } 
  * pipe = p;
  * length = rfm70_receive_next_length();
  rfm70_buffer_read( RFM70_CMD_R_RX_PAYLOAD, buf, * length );
  return 1;
}
   
void rfm70_init( void ){
  unsigned char i;
 
  RFM70_PIN_DIRECTION;
 
  RFM70_CE( 0 );
  RFM70_CSN( 1 );
  RFM70_SCK( 0 );
  RFM70_MOSI( 0 );
 
  // delay at least 50ms.
  // the example code says so, but why??
  RFM70_WAIT_MS( 50 );
   
   
[COLOR=#ff0000][B]    rfm70_pipe_enable(2,1 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_pipe_enable(3,1 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_pipe_enable(4,1 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_pipe_enable(5,1 );[/B][/COLOR]
  // write array of default init settings
  rfm70_bank( 0 );
   
 
  for( i = 0; i < BANK0_ENTRIES; i++ ){
    rfm70_register_write( Bank0_Reg[ i ][0], Bank0_Reg[ i ][1] );
  }
   
       
   
[COLOR=#ff0000][B]  rfm70_receive_address_p0( RX0_Address );[/B][/COLOR]
[COLOR=#ff0000][B]  rfm70_receive_address_p1( RX1_Address );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_receive_address_pn( 2, 0x04 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_receive_address_pn( 3, 0x05 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_receive_address_pn( 4, 0x06 );[/B][/COLOR]
[COLOR=#ff0000][B]    rfm70_receive_address_pn( 5, 0x07 );[/B][/COLOR]
 
[COLOR=#ff0000][B]  rfm70_transmit_address( Tx_address );[/B][/COLOR]
 
  // enable the extra features
  i = rfm70_register_read(29);
  if( i == 0 ){ // only when the extra features are not yet activated!
      rfm70_register_write( RFM70_CMD_ACTIVATE, 0x73 );
       
  }
 
  // select dynamic payload length data pipe5\4\3\2\1\0
  rfm70_register_write( 28, 0x3F );
 
  // select Dynamic Payload Length, Payload with ACK, W_TX_PAYLOAD_NOACK
  rfm70_register_write( 29, 0x07 ); 
 
  // dynamic payload sizing on channels 0 and 1
  rfm70_channel_payload_size( 0, 0 );
  rfm70_channel_payload_size( 1, 0 );
 
  rfm70_init_bank1();
  RFM70_WAIT_MS( 50 );
  rfm70_mode_receive();
 
}
 
 
 
 

I don't know to process when device 1 receive 6 pipe in time
@ngndangtan • 21 May, 2013 rfm70_pipe_enable(2,1 );
rfm70_pipe_enable(3,1 );
rfm70_pipe_enable(4,1 );
rfm70_pipe_enable(5,1 );

rfm70_receive_address_p0( RX0_Address );
rfm70_receive_address_p1( RX1_Address );
rfm70_receive_address_pn( 2, 0x04 );
rfm70_receive_address_pn( 3, 0x05 );
rfm70_receive_address_pn( 4, 0x06 );
rfm70_receive_address_pn( 5, 0x07 );
@Harshad Italiya • 21 May, 2013 If you want to receive from device 6 to Tx then you must have to swap address.

suppose Tx = 1 and Rx6 = 15 then you have to program this address into transmitter and
Tx = 15 and Rx6 = 1 into Receiver device.
@ngndangtan • 21 May, 2013
Harshad Italiya
If you want to receive from device 6 to Tx then you must have to swap address.

suppose Tx = 1 and Rx6 = 15 then you have to program this address into transmitter and
Tx = 15 and Rx6 = 1 into Receiver device.
thank you!
So.This is transmitter 2 module.My opinions is "when device receive so have 6 address to receive data and how to know data in each address " and How to open pipe 2,3,4,5.I only use pipe 0,1.And i need more.
@ngndangtan • 21 May, 2013
Harshad Italiya
If you want to receive from device 6 to Tx then you must have to swap address.

suppose Tx = 1 and Rx6 = 15 then you have to program this address into transmitter and
Tx = 15 and Rx6 = 1 into Receiver device.
thank you!
So.How to open pipe 2,3,4,5.I only use pipe 0,1.And i need more.


CTRL + Q to Enable/Disable GoPhoto.it


CTRL + Q to Enable/Disable GoPhoto.it
@ngndangtan • 21 May, 2013
Harshad Italiya
If you want to receive from device 6 to Tx then you must have to swap address.

suppose Tx = 1 and Rx6 = 15 then you have to program this address into transmitter and
Tx = 15 and Rx6 = 1 into Receiver device.
Thank you for at all.Godfather!
So I only 2 pipe to transmitter many moduls
@Harshad Italiya • 21 May, 2013
ngndangtan
Thank you for at all.Godfather!
So I only 2 pipe to transmitter many moduls
I'm not sure what you are asking now. Please explain.
@ngndangtan • 21 May, 2013
Harshad Italiya
I'm not sure what you are asking now. Please explain.
So i have more than 2 module to transmitter but I only open 2 pipe 0,1.I want more pipe and i configure
rfm70_pipe_enable(2,1 );
rfm70_pipe_enable(3,1 );
rfm70_pipe_enable(4,1 );
rfm70_pipe_enable(5,1 );

rfm70_receive_address_p0( RX0_Address );
rfm70_receive_address_p1( RX1_Address );
rfm70_receive_address_pn( 2, 0x04 );
rfm70_receive_address_pn( 3, 0x05 );
rfm70_receive_address_pn( 4, 0x06 );
rfm70_receive_address_pn( 5, 0x07 );
so it don't work.
And only 2 pipe with swap address How many device i can transmitter
@Harshad Italiya • 21 May, 2013 RFM70 is something like one transmitter and 6 Receiver. Program Transmitter and All Six receiver address. You can receive its data to all receiver but in different pipes. I'll try to make one diagram so you can get idea about mechanism.
@ngndangtan • 21 May, 2013 Thank you for all!
I have completed transmitter many device with swap address .But i don't know with six receiver address when send data from 6 device to 6 address as same time.How to solve
@Harshad Italiya • 22 May, 2013
ngndangtan
Thank you for all!
I have completed transmitter many device with swap address .But i don't know with six receiver address when send data from 6 device to 6 address as same time.How to solve
Will you please make one diagram showing that how exactly you want your system to be..So I can check if it is feasible or not.

Related Posts

I thought of compiling a list of the coolest and the best whatsapp group names that you've been using for your respective groups. For the sake of convenience, we'll stick...
A simple good bye email or last working day mail ain't cool! We've some awesome templates that you can use. If you're looking for an amazing Last Working Day email...
Hello CEans, How to convert CGPA (10 Point Scale) to Percentage? Please help!
I heard many students are having a trouble registering on the TCS Portal, when it's quite straightforward actually. If you have problem in attaching photos or CV, Use internet explorer...
What is IES or Indian Engineering Services Exam? Union Public Services Commission (UPSC) conducts the Engineering Services Exam or ESE 2016 is an entrance exam for graduates who wish to...