embello

Embedded software from JeeLabs

Embello Home Page
Hardware Documentation
Forth Library Documentation

RFM69 radio driver

This is a driver for the RFM69W and RFM69CW modules from HopeRF.

At the moment, all communication with the radio is polled, the interrupt signals available on the DIO0..DIO5 pins are not used. Call rf-recv periodically to find out whether a new packet has been received.

API

The driver and chip must be initialized by calling rf-init after setting the rf.freq and rf.group variables. rf-sleep can be used to put the radio into low-power sleep mode. To wake it up call rf-recv or rf-send.

: rf-init ( -- )  \ init RFM69 with current rf.group and rf.freq values
: rf-sleep ( -- ) RF:M_SLEEP rf!mode ;  \ put radio module to sleep

A packet can be sent with rf-send with the address and length of the buffer holding the payload on the stack. The header byte must also be on the stack. This is the first actual payload byte and is used in the JeeLabs protocol to hold the source node ID in the 6 low bits as well as an ack request flag in bit 7 and a data/special flag in bit 6.

To receive packets, rf-recv must be called periodically. The first time it enables the receiver, thereafter it checks whether a packet has been received and returns the packet payload length. The data is found in rf.buf and reception info is found in rf.rssi, rf.lna, and rf.afc.

: rf-recv ( -- b )  \ check whether a packet has been received, return #bytes
: rf-send ( addr count hdr -- )  \ send out one packet

The transmission power can be adjusted at any time using rf-power. The carrier frequency can be adjusted based on the rf.afc measurement of the incoming packet using rf-correct, which should be called right after a packet is successfully received. Bug: rf-correct assumes that rf.freq contains the frequency in Hz (not Khz or Mhz).

: rf-power ( n -- )  \ change TX power level (0..31)
: rf-correct ( -- ) \ correct the freq based on the AFC measurement of the last packet

To briefly wait for an ACK response rf-ack? should be called after rf-send returns. It takes a max number of milliseconds to wait for and returns the length of the ACK packet (bug: this assumes the ACK contains at least one byte of payload). A typical low-power loop is to read sensors, send the data with rf-send, then wait for an ACK with rf-ack?, adjust the frequency with rf-correct and go back to sleep.

rf-listen sits in a loop calling rf-recv and printing info about incoming packets until a key is hit.

: rf-ack? ( ms -- b ) \ waits ms milliseconds for an ACK and returns #bytes recv'd
: rf-listen ( -- )  \ init RFM69 and report incoming packets until key press
: rf-txtest ( n -- )  \ send out a test packet with the number as ASCII chars
: rf. ( -- )  \ print out all the RF69 registers

Variables

These should only be changed before calling rf-init:

8683 variable rf.freq    \ frequency (auto-scaled to 100..999 MHz)
  42 variable rf.group   \ network group (1..250)
  61 variable rf.nodeid  \ node ID of this node (1..63)

Information about the last packet reception:

   0 variable rf.rssi  \ RSSI signal strength of last reception
   0 variable rf.lna   \ Low Noise Amplifier setting (set by AGC)
   0 variable rf.afc   \ Auto Frequency Control offset
  66 buffer:  rf.buf   \ buffer with last received packet data

Examples

Listen for packets on 868.6 MHz, net group 6, and report each one in hex:

8686 rf.freq !  \ set frequency, scaled down to 868.6 MHz
6 rf.group !    \ set the net group to filter on to 6
rf-listen       \ listen and print packets until RETURN typed

Sample output, this will continue until a key is typed on the console:

RF69 21EE0675040006C00107 8102AA4A978080
RF69 21EE0676040012C00107 8102A44A988080
RF69 21EE0676040016C00104 81808080
RF69 21EE067504000EC00107 8102A24A998080

Send a test packet with hex bytes 31 and 32 (the ASCII equivalent of “12”):

12 rf-txtest  \ value is sent as ASCII-formatted payload

Put the RF module to sleep (it must have been initialised first):

rf-sleep

To wake-up from sleep mode, call rf-recv or rf-send.

Display the radio’s internal registers:

rf.

Sample output:

    0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F
00: -- 10 00 02 8A 05 C3 D9 26 40 41 60 02 92 F5 20
10: 24 9F 09 1A 40 B0 7B 9B 20 42 42 40 80 06 5C 00
20: 00 00 03 00 77 00 07 D9 46 A0 00 00 00 05 88 2D
30: 06 00 00 00 00 00 00 D0 42 00 00 00 8F 12 00 00
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00
50: 15 05 88 08 00 00 01 00 1B 09 55 80 70 33 CA 08 ok.