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.
The driver and chip must be initialized by calling
rf-init after setting
rf-sleep can be used to put the
radio into low-power sleep mode. To wake it up call
: 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
rf.buf and reception info is found in
: 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
The carrier frequency can be adjusted based on the
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
These should only be changed before calling
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
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):
To wake-up from sleep mode, call
Display the radio’s internal registers:
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.