CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

rfm22 transceiver module - disable usb interrupts ??
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

rfm22 transceiver module - disable usb interrupts ??
PostPosted: Thu Mar 04, 2010 4:12 pm     Reply with quote

Hi Folks,

Has anyone used and been able to get code to work with the RFM22 rf modules? I have been fighting this module for a few days now. I can set and readback the configuration registers using a SW SPI interface. The code I'm using is based on the example from http://www.hoperf.com for transmit and receive.

I have the receive side polling the nIRQ pin and when active, the code polls the receive FIFO for the received data. The test sends 17 bytes as a payload and for some reason every time I receive a valid packet, as indicated by the chip, I only get 17 copies of the last byte loaded into the TX FIFO. There are so many registers to set that I really don't understand it all yet and was hoping that someone might have already run through this and could shed some light.

I can post the final working code for others if I ever get it working.

Thanks,

Dan


Last edited by dan king on Fri Mar 12, 2010 12:57 pm; edited 1 time in total
MikeW



Joined: 15 Sep 2003
Posts: 184
Location: Warrington UK

View user's profile Send private message

PostPosted: Fri Mar 05, 2010 2:22 am     Reply with quote

Dan,

I haven't used the RFM12 or 22 modules yet, but hope (sic) to in the future.

A few months ago, I did some googling, and there's loads of stuff on google.

try RFM12.

have a look at

http://blog.strobotics.com.au/2008/01/08/rfm12-tutorial-part1/

I haven't studied the modules in great detail, but they seem to use the silabs chips.

http://www.silabs.com

Please post code if you get it up and running.

I will happily zip all the stuff I have if you pm me with your email address.

Mike
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri Mar 05, 2010 7:33 am     Reply with quote

Hi Mike,

I reviewed the silabs docs since the rfm22 uses the si4431 transceiver chip but they really don't have much in the way of an app note with register settings, at least that I could find.

I've also been to the tutorial link but it's incomplete, doesn't go past section 2.

The amount of detail on google for the rfm22 is pretty sparse, the rfm12 has more but I'm pretty sure they are different enough to not be applicable.

I haven't made much progress with my code at getting past the fifo containing 17 copies of the last byte tx'd. I wish I could read back what was loaded into the tx fifo to check the integrity of the data but a read to the fifo pulls data from the rx fifo. I'm really at an impass now because I can't determine what is actually being transmitted.

I'll pm my email address, thanks for anything you might have.

Rgds,

Dan
xberger



Joined: 11 Mar 2010
Posts: 2

View user's profile Send private message

PostPosted: Thu Mar 11, 2010 6:21 am     Reply with quote

Hello Dan,

RFM22 (+20dBm) module is based on Si4432 chip from Silicon Labs.
But demo code of HopeRF should work for both.

I used the transmit and receive demo code on MSP430.
It's work fine. I receive the same payload than I transmit.
But since I used it, HopeRF modified their demo code.
see the news from HopeRF : http://www.hoperf.com/news/32.htm
I didn't test this new code.

As define in the code, the payload should be :

0x30
0x31
0x32
0x33
0x34
0x35
0x36
0x37
0x38
0x39
0x3a
0x3b
0x3c
0x3d
0x3e
0x3f
0x78

In your case, you receive 17 copies of the last byte tx'd.
That's mean, 17 times 0x78 ?

Best regards
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Thu Mar 11, 2010 7:25 am     Reply with quote

I'm getting better results than when I posted before. I am sometimes receiving the complete payload but something with my setup is flakey. I get varying levels of success and I can't determine what is causing the inconsistency. I added code to check for TX timeouts where the fifo gets loaded and then the code waits for nIRQ incdicating a successful TX. This sometimes gets lost and when I re-init the registers the issue isn't resolved. If I reset the entire system is sometimes recovers.

As far as the RX side, I do occasionally get valid packets received showing the 17 bytes but I also seem to get an odd extra reception at the end and my code reads the rx fifo 17 times and prints the result to show the same value. I'm not sure where that is coming from but I'm assuming that 17 bytes are being sent for the mystery data because I believe the nIRQ doesn't change state until a full packet(17 bytes) is received, is that correct based on the register settings in the demo code?


I wish I could read the tx fifo after I load it but the datasheet indicates that when I read the fifo I'm actually getting what is in the rx fifo. UGH.

Anyhow, i'll stop my rambling and keep trying. When I have something that is stable and repeatable I'll post for others to reference.

OH - BTW the datasheet schematic doesn't show the connection for the SDN pin, a big time gotcha since if that pin isn't tied to GND the transceiver does nothing. The example code does show that and saved me Smile

Rgds,
Dan
xberger



Joined: 11 Mar 2010
Posts: 2

View user's profile Send private message

PostPosted: Fri Mar 12, 2010 5:07 am     Reply with quote

Hello Dan,

In the case of HopeRF's configuration, nIRQ goes low only if a valid packet in received.
It's sure because there is a CRC in the packet (encrc = '1' in Register 30h : Data Access Control.

On the receiver side, if you read the RX FIFO after nIRQ goes low you must read the right payload.

HopeRF add a 8-bit checksum in the payload but it's not necessary.

Best regards
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri Mar 12, 2010 7:15 am     Reply with quote

Yah, I know about the CRC. That's why I would like to see what is in the TX FIFO because when I finally do get a correct TX, it's always followed by another packet that is the same value for all 17 bytes. Very confusing because I'm only sending the example packet.

I am also have serious stability issues. Both my send and receive platforms are going into strange modes that require toggling the SDN pin to recover. Resending the init register values doesn't restore it because I believe the onboard micro has latched or something. Reading register 0x00 should always return the same device type but starts sending random data when read in the "unknown" mode.

After I toggle SDN the registers return expected value. I am looking into the power supply further but I don't expect to find any surprises there since I have decoupling caps everywhere and some stiff electrolytics on both sides of the 3.3 V regulator.

Anyhow, thanks for the input. I'll report more back later.

Dan
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Fri Mar 12, 2010 10:03 am     Reply with quote

Ok, I think I've found part of the problem with my setup. I have been using PIC18F2455 USB parts and run the CDC configuration to allow terminal access to each part. It appears that the USB influence, whether rf or in pic code, is to blame. I modified my code to allow a pushbutton to initiate TX as well as through usb terminal commands and what I found is that the TX works almost 100% of the time when the transmit side runs off of batteries. When connected to usb neither the pushbutton or the terminal command for TX works even close to reasonable. The RX side works just fine when connected to USB though so I'm not sure if the usb code is causing problems or if it's rf related but I tend to think the usb code is the problem since the rf transceiver gets latched fairly often.

My main code is shown below to demostrate what I have set up.

Code:
   while(1){

      usb_task();

      if (!button){
         testled = !testled;
         to_tx_mode();
         delay_ms(100);
      }

      if (usb_cdc_kbhit()) {                           //if incoming USB commands, service them
             c=usb_cdc_getc();
         
         switch (c){
            case 'h': usb_cdc_putc("TX help usb link\n\r");
                  usb_cdc_putc("t to transmit packet\n\r");      
                  usb_cdc_putc("i to init the transceiver\n\r");
                  usb_cdc_putc("r to read back a register\n\r");
                  break;
            case 'g': usb_cdc_putc("input an 8 bit number\n\r");   
               temp = get_usb_num();
               printf(usb_cdc_putc,"\r\ntest %u\r\n",temp);
               break;
            case 'i': usb_cdc_putc("initializing\n\r");
               shutdown = 1;
               delay_ms(100);
               shutdown = 0;
               delay_ms(1000);
               rf22_init_parameter();
               idle;
               usb_cdc_putc("done\n\r");
               break;
            case 't':   testled = !testled;
               to_tx_mode();
               delay_ms(100);
               usb_cdc_putc("sent\n\r");
               break;
            case 'r': usb_cdc_putc("input an 8 bit hex address to read\n\r");   
               nib_h = get_usb_nibble();
               nib_h = nib_h <<4;
               nib_l = get_usb_nibble();
               nib_h = nib_h|nib_l;
               temp=spi_read_rfm(nib_h);
               printf(usb_cdc_putc,"\r\naddress 0x%x= %x\r\n",nib_h,temp);
               break;   
            case 'w': usb_cdc_putc("input an 8 bit hex address to write to\n\r");   
               nib_h = get_usb_nibble();
               nib_h = nib_h <<4;
               nib_l = get_usb_nibble();
               nib_h = nib_h|nib_l;

               printf(usb_cdc_putc,"\r\ninput an 8 bit hex value to write to address 0x%x\n\r",nib_h);   
               val_h = get_usb_nibble();
               val_h = val_h <<4;
               val_l = get_usb_nibble();
               val_h = val_h|val_l;
               spi_write_rfm(nib_h,val_h);
               usb_cdc_putc("\r\nwritten\n\r");
               break;   

            default: ;
         }

         }


   }            //close while 1
}               //close mai



is there a way to disable usb interrupts during certain routines?

btw - compiler version CCS PCH C Compiler, Version 4.074

Thanks,

Dan
danr



Joined: 14 Sep 2010
Posts: 4

View user's profile Send private message

RFM22B Multiple copies of last byte
PostPosted: Tue Sep 14, 2010 6:18 am     Reply with quote

Hi Dan,

I have just produced some code using an RFM22 module and a PIC16f687 to control it. Everything is fine except the use of the FIFO and what happens to the payoad - it sounds exactly like your original post where whatever the last byte shifted into the FIFO at the TX end is gets read out at the receiver end the same number of times as the packet payload length.

How did you finally solve this problem - I have no USB interractions to consider, it is pure SPI from the PIC.

Many thanks.
dan king



Joined: 22 Sep 2003
Posts: 119

View user's profile Send private message

PostPosted: Tue Sep 14, 2010 10:00 am     Reply with quote

Sorry to say, that was as far as I got since I didn't have a project in mind I only wanted to get started with the modules.

I found that if I initiated a TX with a pushbutton instead of through terminal access(via USB) the module would work pretty well. I figured that once I had a project that I could narrow down the other issues.

I know that doesn't help but good luck.
danr



Joined: 14 Sep 2010
Posts: 4

View user's profile Send private message

RFM22B Multiple copies of last byte
PostPosted: Wed Sep 15, 2010 4:33 am     Reply with quote

Looks resolved now - the RFM22b datasheet from Hope doesn't say (or I didn't notice) that the clear RX/TX FIFO is a double write - set '1' and then set '0'. It appears in an application note from SI. Once implimented the modules perform as expected.
dap20



Joined: 11 Aug 2011
Posts: 5

View user's profile Send private message

Re: RFM22B Multiple copies of last byte
PostPosted: Thu Aug 11, 2011 5:01 pm     Reply with quote

Hi, I have tried to make work the rfm22b, but with no positive results, please could you show me your source code.
danr



Joined: 14 Sep 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun Aug 14, 2011 2:44 am     Reply with quote

I initalise the module like this:
Code:

void init_radio(char pause)   
{
   char freq_reg_76;
   char freq_reg_77;   

   switch (master_station)      //first decide the frequency based on master station number - 6 stations allowed for here
   {
      case 1:            //433.1MHz
      freq_reg_76 = 0x4d;
      freq_reg_77 = 0x80;
      break;
      
      case 2:            //433.4MHz
      freq_reg_76 = 0x55;
      freq_reg_77 = 0x00;
      break;
      
      case 3:            //433.7MHz
      freq_reg_76 = 0x5c;
      freq_reg_77 = 0x80;
      break;
      
      case 4:            //434.1MHz
      freq_reg_76 = 0x66;
      freq_reg_77 = 0x80;
      break;
      
      case 5:            //434.4MHz
      freq_reg_76 = 0x6e;
      freq_reg_77 = 0x00;
      break;
      
      case 6:            //434.7MHz
      freq_reg_76 = 0x75;
      freq_reg_77 = 0x80;
      break;
   }   
   
   if(pause)
   {
      rf_sdn = 1;      //shut down the RF module
      delay_ms(50);
      rf_sdn = 0;      //start up  the RF module
      delay_ms(50);
   }
   send_rf_spi(interrupt_enable_reg_1, 0x00);//5 00               //interrupt enable reg1 - none used at the moment
   send_rf_spi(interrupt_enable_reg_2, 0x00);//6 03               //interrupt enable reg2 - none used at the moment
   get_rf_spi(interrupt_status_1);                              //read out interrupt register 1
   get_rf_spi(interrupt_status_2);                              //read out interrupt register 2
   send_rf_spi(operating_and_func_control_1, idle_standby);//7 01      //start out in standby mode
   send_rf_spi(operating_and_func_control_2, 0b00000001);//8 00      
   send_rf_spi(operating_and_func_control_2, 0b00000000);//8 00   
   send_rf_spi(operating_and_func_control_2, 0b00000010);//8 00      
   send_rf_spi(operating_and_func_control_2, 0b00000000);//8 00
   send_rf_spi(if_filter_bandwidth, 0x15);//1C
   send_rf_spi(afc_loop_gearshift_override, 0x40);//1D
   send_rf_spi(afc_timing_control, 0x0A);//1E 0A
   send_rf_spi(clock_recovery_gearshift_override, 0x00);//1F 03   should be 00
   send_rf_spi(clock_recovery_oversampling_ratio, 0xC8);//20
   send_rf_spi(clock_recovery_offset_2, 0x00);//21       
   send_rf_spi(clock_recovery_offset_1, 0x51);//22       
   send_rf_spi(clock_recovery_offset_0, 0xEC);//23    
   send_rf_spi(clock_recovery_timing_loop_gain_1, 0x10);//24   should be 10
   send_rf_spi(clock_recovery_timing_loop_gain_0, 0xA6);//25
   send_rf_spi(afc_limiter, 0x29);//2A
   send_rf_spi(data_access_control, 0x8D);//30 8D            //TX and RX packet handling on, CRC whole packet, CRC-16 polynomial
   send_rf_spi(header_control_1, 0x0C);//32 0C
   send_rf_spi(header_control_2, 0x22);//33 22    
   send_rf_spi(preamble_length, 0x20);//34                  //use 4 bytes (8 nibbles) of transmitted preamble
   send_rf_spi(preamble_detection_control, 0x52);//35 22      //use 4 nibbles <7:3> for preamble detection threshold
   send_rf_spi(sync_word_3, 0x2D);//36 2D                  //only using 2 sync words so leaving 1 and 0 unconfigured
   send_rf_spi(sync_word_2, 0xD4);//37 D4
   send_rf_spi(sync_word_1, 0x00);//38 00
   send_rf_spi(sync_word_0, 0x00);//39 00   
   send_rf_spi(transmit_header_3, master_station);//3A 00         //this is the address put into the packet header for tx
   send_rf_spi(transmit_header_2, 0x02);//3B 00
   send_rf_spi(transmit_header_1, 0x03);//3C 00
   send_rf_spi(transmit_header_0, 0x04);//3D 00
   send_rf_spi(transmit_packet_length, payload_length);//3E 00      //payload length in bytes   
   send_rf_spi(check_header_3, node);//3F 00                  //this is the 'local' address the packet header is checked against
   send_rf_spi(check_header_2, 0x02);//40 00
   send_rf_spi(check_header_1, 0x03);//41 00
   send_rf_spi(check_header_0, 0x04);//42 00   
   send_rf_spi(header_enable_3, 0xFF);//43 FF            
   send_rf_spi(header_enable_2, 0xFF);//44 FF
   send_rf_spi(header_enable_1, 0xFF);//45 FF
   send_rf_spi(header_enable_0, 0xFF);//46 FF   
   send_rf_spi(reserved_0x58, 0x80);//58 -                        
   send_rf_spi(agc_override_1, 0x60);//69 20   60         //reserved, 0, agcen, lnagain, 0, 0, 0, 0   
   char cur_reg_setting = get_rf_spi(tx_power);         //get the existing register value
   cur_reg_setting &= 0b11111000;                     //mask out the existing power setting, leave the other bits unchanged
   cur_reg_setting += initial_power;//_14dbm;            //add in the initial tx power setting
   send_rf_spi(tx_power, cur_reg_setting);//6D   18         //put the new power setting back into the module   
   send_rf_spi(tx_data_rate_1, 0x28);//6E    was 0x05      //data rate set for 5kbps
   send_rf_spi(tx_data_rate_0, 0xF6);//6F    was 0x1F      //data rate set for 5kbps
   send_rf_spi(modulation_mode_control_1, 0x2E);//70       //txdtrtscale = 0 <5>, en PH, ?, en maninv, enmanch, no whitening
   send_rf_spi(modulation_mode_control_2, 0x23);//71     
   send_rf_spi(freq_deviation, 0x20);//72                //this is 20kHz deviation   
   send_rf_spi(freq_band_select, 0x53);//75 75   
   send_rf_spi(nominal_carrier_freq_1, freq_reg_76);//76 BB      
   send_rf_spi(nominal_carrier_freq_0, freq_reg_77);//77 80   
}

I switch to rx mode like this:
Code:

void rf_to_rx()
{
   tx_ant = 0;         //disconnect the tx antenna
   rx_ant = 1;         //connect the rx antenna
   send_rf_spi(interrupt_enable_reg_1, 0x02);   //enable the valid packet interrupt
   send_rf_spi(interrupt_enable_reg_2, 0x00);   //no other interrupts needed
   get_rf_spi(interrupt_status_1);            //read out interrupt register 1
   get_rf_spi(interrupt_status_2);            //read out interrupt register 2
   send_rf_spi(operating_and_func_control_2, 0b00000010);   //clear the RX FIFO
   send_rf_spi(operating_and_func_control_2, 0b00000000);   //clearing is a double write
   delay_100us(1);                        //pause in idle before RX
   send_rf_spi(operating_and_func_control_1, rx_state);   //switch to the rx state   
   return;
}

and I switch to the tx state like this:
Code:

void rf_to_tx(char* data, char length)
{
   delay_100us(3);
   send_rf_spi(operating_and_func_control_2, 0b00000001);      //clear the TX FIFO
   send_rf_spi(operating_and_func_control_2, 0b00000000);      //clearing is a double write function
   send_rf_spi(transmit_packet_length, length);            //update the packet length register
   burst_write_rf_spi(fifo, data, length);                  //burst write the payload to the TX FIFO
   send_rf_spi(interrupt_enable_reg_1, 0x04);   //enable the packet sent interrupt
   send_rf_spi(interrupt_enable_reg_2, 0x00);   //no other interrupts needed
   get_rf_spi(interrupt_status_1);            //read out interrupt register 1
   get_rf_spi(interrupt_status_2);            //read out interrupt register 2      
   send_rf_spi(operating_and_func_control_1, tx_state);   //switch to the tx state
      
   char time_out_on_tx = 50;               //time out in ms   
   set_bit(intcon, GIE);
   packet_status = 0;                     //clear the status of incoming/outgoing packets
   while((packet_status == 0) && (time_out_on_tx > 0))      //wait here until the packet sent interrupt comes in
   {      
      delay_ms(1);      
      time_out_on_tx--;
      if(time_out_on_tx == 0)            //if there seems to be a problem with confirmation of TX then re-init the radio
      {         
         init_radio();            //re - init the RF board               
      }               
   }
   clear_bit(intcon, GIE);            //disallow interrupts
   get_rf_spi(interrupt_status_1);
   get_rf_spi(interrupt_status_2);      
   return;   
}

This has some timeout stuff in there that could be omitted if you're not too worried about making sure it tx'd OK.

SPI send to the module looks like this:
Code:

char send_rf_spi(char address, char data)
{
//address bit 7 is R/W - read is 0 write is 1
   char int_state = intcon;
   clear_bit (intcon, GIE);
   config_spi(spi_rfm);
   address.7 = 1;
   delay_us(1);
   rf_cs = 0;               //rf chip select is active low - assert here   
   delay_us(1);            //min delay required is 400nS
   clear_bit(sspcon, WCOL);   //ensure the collision detect flag s reset before we start
   sspbuf = address;         //first clock out the register address to write to
   while (!(sspstat & 1<<BF));   //wait to be finished   
   sspbuf = data;               //next clock data from the master
   while (!(sspstat & 1<<BF));      //wait to be finished
   delay_us(1);            //min delay required is 400nS
   rf_cs = 1;               //release the chip select
   intcon = int_state;
   return 1;               //success                        
}

Get from RF module looks like this:
Code:

char get_rf_spi(char address)
{
//address bit 7 is R/W - read is 0 write is 1
   char int_state = intcon;
   clear_bit (intcon, GIE);
   config_spi(spi_rfm);
   delay_us(1);
   rf_cs = 0;               //rf chip select is active low - assert here
   delay_us(1);            //min delay required is 400nS      
   address.7 = 0;
   clear_bit(sspcon, WCOL);   //ensure the collision detect flag s reset before we start
   sspbuf = address;         //first clock out the register address to read from
   while (!(sspstat & 1<<BF));   //wait to be finished   
   sspbuf = 0;                  //next clock dummy data from the master to read slave
   while (!(sspstat & 1<<BF));      //wait to be finished
   delay_us(1);            //min delay required is 400nS
   rf_cs = 1;               //release the chip select   
   intcon = int_state;
   return sspbuf;            //this will now contain the data clocked out of the slave                        
}

And finally, burst write:
Code:

void burst_write_rf_spi(char address, char length)
{
   char int_state = intcon;
   clear_bit (intcon, GIE);
   config_spi(spi_rfm);
   address.7 = 1;
   delay_us(1);
   rf_cs = 0;               //rf chip select is active low - assert here   
   delay_us(1);            //min delay required is 400nS
   clear_bit(sspcon, WCOL);   //ensure the collision detect flag is reset before we start
   sspbuf = address;         //first clock out the register address to write to
   while (!(sspstat & 1<<BF));   //wait to be finished
   for (char i=0; i<length; i++)
   {      
      sspbuf = tx_data[i];            //next clock data from the master
      while (!(sspstat & 1<<BF));      //wait to be finished
   }   
   delay_us(1);            //min delay required is 400nS
   rf_cs = 1;
   intcon = int_state;
}
danr



Joined: 14 Sep 2010
Posts: 4

View user's profile Send private message

PostPosted: Sun Aug 14, 2011 8:32 am     Reply with quote

The comments are not up to date, so don't pay to much attention to them!
crocu



Joined: 02 Nov 2009
Posts: 5

View user's profile Send private message

PostPosted: Sat Sep 29, 2012 5:19 pm     Reply with quote

Hello danr,

Would you please share you entire code with *.c and *.h files ?

I'm trying to use your code with a PIC 18F2620 but RFM22 registers defines are stated in your code and it is difficult to see how your code works.

I will appreciate if you could post the all project archive here, it will help me a lot.

Many thanks,
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group