RFM69 driver

Posted on
  • Hi,

    I just hacked up a very basic RFM69 driver. Not in a module yet because I'm sure it needs a lot of refinement, but:

    var RFM69HFreqTbl = { 
      315 : new Uint16Array([0x074e, 0x08c0, 0x0900]), //315MHz
      434 : new Uint16Array([0x076c, 0x0880, 0x0900]), //434MHz
      868 : new Uint16Array([0x07d9, 0x0800, 0x0900]), //868MHz
      915 : new Uint16Array([0x07e4, 0x08c0, 0x0900]), //915MHz
    };
    
    var RFM69HRateTbl = [
      [0x0368, 0x042B],         //BR=1.2K BW=83.333K
      [0x0334, 0x0415],         //BR=2.4K BW=83.333K  
      [0x031A, 0x040B],         //BR=4.8K BW=83.333K
      [0x030D, 0x0405],         //BR=9.6K BW=83.333K
    ];
    
    var RFM69HPowerTbl = new Uint16Array([ 
      0x117F,                   //20dbm  
      0x117C,                   //17dbm
      0x1179,                   //14dbm
      0x1176,                   //11dbm 
    ]);
    
    var RFM69HConfigTbl = new Uint16Array([ 
      0x0200,                   //RegDataModul, FSK Packet  
      0x0502,                   //RegFdevMsb, 241*61Hz = 35KHz  
      0x0641,                   //RegFdevLsb
      0x1952,                   //RegRxBw , RxBW, 83KHz
      
      0x2C00,                   //RegPreambleMsb  
      0x2D05,                   //RegPreambleLsb, 5Byte Preamble
      0x2E90,                   //enable Sync.Word, 2+1=3bytes
      0x2FAA,                   //0xAA, SyncWord = aa2dd4
      0x302D,                   //0x2D
      0x31D4,                   //0xD4  
    //  0x3700,                 //RegPacketConfig1, Fixed length, Disable CRC, No DC-free encode, No address filter
    //  0x3815,                 //RegPayloadLength, 21 bytes for length & Fixed length
      0x3790,                   //RegPacketConfig1, Variable length, Enable CRC, No address filter
      0x3842,                   //RegPayloadLength, 66 bytes MAX for variable length
      0x3C95,                   //RegFiFoThresh   
      
      0x1888,                   //RegLNA, 200R  
      0x581B,                   //RegTestLna, Normal sensitivity
      //0x582D,                 //RegTestLna, increase sensitivity with LNA (Note: consumption also increase!)
      0x6F30,                   //RegTestDAGC, Improved DAGC
      //0x6F00,                 //RegTestDAGC, Normal DAGC
      0x0104,                   //Enter standby mode    
    ]);
    
      
    var RFM69HRxTbl = new Uint16Array([
      0x119F,                   //      
      0x2544,                   //DIO Mapping for Rx. DIO 0..5 = PayloadReady,FifoLevel,Data,FifoFull
      0x1310,                   //OCP enabled
      0x5A55,                   //Normal and Rx
      0x5C70,                   //Normal and Rx   
      0x0110                    //Enter Rx mode
    ]);         
    
        
    var RFM69HTxTbl = new Uint16Array([
      0x2504,                   //DIO Mapping for Tx. DIO 0..5 = PacketSent,FifoLevel,Data,FifoFull
      0x130F,                   //Disable OCP
      0x5A5D,                   //High power mode
      0x5C7C,                   //High power mode
      0x010C,                   //Enter Tx mode
    ]);
    
    
    SPI2.setup({mosi:B15,miso:B14,sck:B13});
    var spi = SPI2;
    var cs = B10;
    var rst = B1;
    
    function r(a) {
      return spi.send([a&0x7f,0], cs)[1];
    }
    
    function w(a,v) {
      spi.send([a|128,v], cs);
    }
    function w16(v) {
      spi.send([(v>>8)|128,v], cs);
    }
    
    function connect(callback) {
      digitalPulse(rst,1,100);
      setTimeout(function() {
        w(0x2F,0xAA);
        if (r(0x2F)!=0xAA) throw new Error("RFM69 not found");
        w(0x2F,0x55);
        if (r(0x2F)!=0x55) throw new Error("RFM69 not found");
        // setup freq
        RFM69HFreqTbl[434].forEach(w16);
        // setup rate
        RFM69HRateTbl[0].forEach(w16);
        // general init
        RFM69HConfigTbl.forEach(w16);
        if (callback) callback();
      }, 100);
    }
    
    function rxmode() {
      RFM69HRxTbl.forEach(w16);
    }
    
    function getPacket() {
      if (!(r(0x28)&4)) return undefined; // no packet
      w16(0x0104); // standby
      cs.reset(); // chip select
      var len = spi.send([0,0])[1];
      var d = spi.send(new Uint8Array(len));
      cs.set(); // let go of CS
      w16(0x0110); // enter RX mode again
      return d;
    }
    
    function hasPacket() {
      return !!(r(0x28)&4);
    }
    
    function sendPacket(d, callback) { 
      w16(0x0104); // standby
      setTimeout(function() { // wait for us to hit standby
        spi.write(0x80, d.length, d, cs);
        RFM69HTxTbl.forEach(w16); // enter TX mode
    
        var t = 100; // 1 sec
        var i = setInterval(function() {
          if (r(0x28)&8 || t-- < 0) {
            w16(0x0104); // standby
            clearInterval(i);
            if (t<0) throw "Timeout in RF69 send";
            if (callback) callback();
          }
        }, 10);
      }, 1);
    }
    

    Transmit:

    sendPacket("Hello World", 
      function() { console.log("Done"); 
    });
    

    Receive:

    rxmode();
    setInterval(function() { 
      if (hasPacket()) console.log(JSON.stringify(E.toString(getPacket()))); 
    },10);
    

    If anyone has some RFM69s they want to try out (@DrAzzy? :) ) I'd be interested to see how this works :) Currently this uses 433Mhz, but it can be changed pretty easily in the connect function.

  • I'll see if I can find time to test this this weekend - I've got the boards with me.

  • Great - thanks!

  • @DrAzzy did you ever get a chance to look at this? It'd be nice to get it module-ified.

    What do you think about turning it into more of a stream-based interface, with read and write? It'd be nice to add the same to NRF24 and work on getting other wireless modules using the same API

  • Haven't even had a chance to look at it. A lot of my interest has dissipated since I am not doing anything long range, and now that I've gotten the 433mhz stuff working reliably, the short range radio is sufficient for what I'm working on. And there are just so many other projects in the queue.

  • Hi! I am trying to get a Sparkfun RFM69HCW breakout board to work with a Pico. This is the only thread I can find about the RFM69 module. I am using the example in the tutorials for SPI connected devices to listen for incoming packets, but whenever I actually force the onInit() function to run by entering it in the web IDE, this happens:

    >echo(0);
    =undefined
    >
    =undefined
    >onInit()
    =undefined
    >Uncaught Error: RFM69 not found
     at line 1 col 58
    ...row Error("RFM69 not found");b.w(47,85);if(85!=b.r(47))throw...
                                  ^
    in function called from system
    =undefined
    > 
    

    I am not a very experienced js programmer, but can try to help debug this module with some guidance. There seems to be little interest in it, but having used an esp8266, I find that power is a consideration for battery operation and also the range through walls is not very good. In contrast, my Moteino network is superior in both of those areas. A Pico could be a very nice addition to the network with a working driver.

    Thanks, Duane

  • I'm pretty sure RFM69 not found happens if it's not wired up correctly.

    Basically on initialisation it tries to write to some registers and read the result, and errors if it can't: https://github.com/espruino/EspruinoDocs/blob/master/devices/RFM69.js#L82

    Are you sure it's connected exactly as that page describes?

  • Thanks Gordon! I am embarrassed to say I was one pin off in my connection. I moved everything over one pin and I get the Connected message. I still have not read a packet, but that probably has to do with the packet format the moteino uses. Now back to reading the docs.

    Duane

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

RFM69 driver

Posted by Avatar for Gordon @Gordon

Actions