RFM12B driver definitions. More...
#include <stdint.h>Go to the source code of this file.
Macros | |
| #define | RF12_VERSION 2 |
| RFM12B Protocol version. More... | |
| #define | rf12_grp rf12_buf[0] |
| Shorthand for RFM12B group byte in rf12_buf. | |
| #define | rf12_hdr rf12_buf[1] |
| Shorthand for RFM12B header byte in rf12_buf. | |
| #define | rf12_len rf12_buf[2] |
| Shorthand for RFM12B length byte in rf12_buf. | |
| #define | rf12_data (rf12_buf + 3) |
| Shorthand for first RFM12B data byte in rf12_buf. | |
| #define | RF12_HDR_CTL 0x80 |
| RFM12B CTL bit mask. | |
| #define | RF12_HDR_DST 0x40 |
| RFM12B DST bit mask. | |
| #define | RF12_HDR_ACK 0x20 |
| RFM12B ACK bit mask. | |
| #define | RF12_HDR_MASK 0x1F |
| RFM12B HDR bit mask. | |
| #define | RF12_MAXDATA 66 |
| RFM12B Maximum message size in bytes. | |
| #define | RF12_433MHZ 1 |
| RFM12B 433 MHz frequency band. | |
| #define | RF12_868MHZ 2 |
| RFM12B 868 MHz frequency band. | |
| #define | RF12_915MHZ 3 |
| RFM12B 915 MHz frequency band. | |
| #define | RF12_EEPROM_ADDR ((uint8_t*) 0x20) |
| Starting offset. | |
| #define | RF12_EEPROM_SIZE 32 |
| Number of bytes. | |
| #define | RF12_EEPROM_EKEY (RF12_EEPROM_ADDR + RF12_EEPROM_SIZE) |
| EE start. | |
| #define | RF12_EEPROM_ELEN 16 |
| EE number of bytes. | |
| #define | RF12_WANTS_ACK ((rf12_hdr & RF12_HDR_ACK) && !(rf12_hdr & RF12_HDR_CTL)) |
| Shorthand to simplify detecting a request for an ACK. | |
| #define | RF12_ACK_REPLY |
| Shorthand to simplify sending out the proper ACK reply. More... | |
| #define | RF12_SLEEP 0 |
| Enter sleep mode. | |
| #define | RF12_WAKEUP -1 |
| Wake up from sleep mode. | |
Enumerations | |
| enum | rf12DataRates { RF12_DATA_RATE_CMD = 0xC600, RF12_DATA_RATE_9 = RF12_DATA_RATE_CMD | 0x02, RF12_DATA_RATE_8 = RF12_DATA_RATE_CMD | 0x05, RF12_DATA_RATE_7 = RF12_DATA_RATE_CMD | 0x06, RF12_DATA_RATE_6 = RF12_DATA_RATE_CMD | 0x08, RF12_DATA_RATE_5 = RF12_DATA_RATE_CMD | 0x11, RF12_DATA_RATE_4 = RF12_DATA_RATE_CMD | 0x23, RF12_DATA_RATE_3 = RF12_DATA_RATE_CMD | 0x47, RF12_DATA_RATE_2 = RF12_DATA_RATE_CMD | 0x91, RF12_DATA_RATE_1 = RF12_DATA_RATE_CMD | 0x9E, RF12_DATA_RATE_DEFAULT = RF12_DATA_RATE_7 } |
| See http://blog.strobotics.com.au/2009/07/27/rfm12-tutorial-part-3a/ Transmissions are packetized, don't assume you can sustain these speeds! More... | |
Functions | |
| void | rf12_set_cs (uint8_t pin) |
| Option to set RFM12 CS (or SS) pin for use on different hardware setups. More... | |
| void | rf12_spiInit (void) |
| Only needed if you want to init the SPI bus before rf12_initialize() does. | |
| uint8_t | rf12_initialize (uint8_t id, uint8_t band, uint8_t group=0xD4) |
| Call this once with the node ID, frequency band, and optional group. More... | |
| uint8_t | rf12_config (uint8_t show=1) |
| Initialize the RFM12B module from settings stored in EEPROM by "RF12demo" don't call rf12_initialize() if you init the hardware with rf12_config(). More... | |
| uint8_t | rf12_recvDone (void) |
| Call this frequently, returns true if a packet has been received. More... | |
| uint8_t | rf12_canSend (void) |
| Call this to check whether a new transmission can be started. More... | |
| void | rf12_sendStart (uint8_t hdr) |
| Call this only when rf12_recvDone() or rf12_canSend() return true. | |
| void | rf12_sendStart (uint8_t hdr, const void *ptr, uint8_t len) |
| Call this only when rf12_recvDone() or rf12_canSend() return true. More... | |
| void | rf12_sendStart (uint8_t hdr, const void *ptr, uint8_t len, uint8_t sync) |
| Deprecated: use rf12_sendStart(hdr,ptr,len) followed by rf12_sendWait(sync). More... | |
| void | rf12_sendNow (uint8_t hdr, const void *ptr, uint8_t len) |
| This variant loops on rf12_canSend() and then calls rf12_sendStart() asap. More... | |
| void | rf12_sendWait (uint8_t mode) |
| Wait for send to finish. More... | |
| void | rf12_onOff (uint8_t value) |
| This simulates OOK by turning the transmitter on and off via SPI commands. More... | |
| void | rf12_sleep (char n) |
| Power off the RFM12B, ms > 0 sets watchdog to wake up again after N * 32 ms. More... | |
| char | rf12_lowbat (void) |
| Return true if the supply voltage is below 3.1V. More... | |
| void | rf12_easyInit (uint8_t secs) |
| Set up the easy tranmission mode, arg is number of seconds between packets. More... | |
| char | rf12_easyPoll (void) |
| Call this often to keep the easy transmission mode going. More... | |
| char | rf12_easySend (const void *data, uint8_t size) |
| Send new data using easy transmission mode, buffer gets copied to driver. More... | |
| void | rf12_encrypt (const uint8_t *) |
| Enable encryption (null arg disables it again). More... | |
| uint16_t | rf12_control (uint16_t cmd) |
| Low-level control of the RFM12B via direct register access. More... | |
Variables | |
| volatile uint16_t | rf12_crc |
| Running crc value, should be zero at end. | |
| volatile uint8_t | rf12_buf [] |
| Recv/xmit buf including hdr & crc bytes. | |
| long | rf12_seq |
| Seq number of encrypted packet (or -1). | |
RFM12B driver definitions.
| #define RF12_ACK_REPLY |
Shorthand to simplify sending out the proper ACK reply.
| #define RF12_VERSION 2 |
RFM12B Protocol version.
Version 1 did not include the group code in the crc. Version 2 does include the group code in the crc.
| enum rf12DataRates |
See http://blog.strobotics.com.au/2009/07/27/rfm12-tutorial-part-3a/ Transmissions are packetized, don't assume you can sustain these speeds!
| uint8_t rf12_canSend | ( | void | ) |
Call this to check whether a new transmission can be started.
Call this when you have some data to send. If it returns true, then you can use rf12_sendStart() to start the transmission. Else you need to wait and retry this call at a later moment.
Don't call this function if you have nothing to send, because rf12_canSend() will stop reception when it returns true. IOW, calling the function indicates your intention to send something, and once it returns true, you should follow through and call rf12_sendStart() to actually initiate a send. See this weblog post.
Note that even if you only want to send out packets, you still have to call rf12_recvDone() periodically, because it keeps the RFM12B logic going. If you don't, rf12_canSend() will never return true.
| uint8_t rf12_config | ( | uint8_t | show | ) |
Initialize the RFM12B module from settings stored in EEPROM by "RF12demo" don't call rf12_initialize() if you init the hardware with rf12_config().
This calls rf12_initialize() with settings obtained from EEPROM address 0x20 .. 0x3F. These settings can be filled in by the RF12demo sketch in the RFM12B library. If the checksum included in those bytes is not valid, rf12_initialize() will not be called.
As side effect, rf12_config() also writes the current configuration to the serial port, ending with a newline.
| uint16_t rf12_control | ( | uint16_t | cmd | ) |
Low-level control of the RFM12B via direct register access.
http://tools.jeelabs.org/rfm12b is useful for calculating these.
This call provides direct access to the RFM12B registers. If you're careful to avoid configuring the wireless module in a way which stops the driver from functioning, this can be used to adjust frequencies, power levels, RSSI threshold, etc. See the RFM12B wireless module documentation.
This call will briefly disable interrupts to avoid clashes on the SPI bus.
Returns the 16-bit value returned by SPI. Probably only useful with a "0x0000" status poll command.
| cmd | RF12 command, topmost bits determines which register is affected. |
| void rf12_easyInit | ( | uint8_t | secs | ) |
Set up the easy tranmission mode, arg is number of seconds between packets.
Set up the easy transmission mechanism. The argument is the minimal number of seconds between new data packets (from 1 to 255). With 0 as argument, packets will be sent as fast as possible:
This function should be called after the RF12 driver has been initialized, using either rf12_initialize() or rf12_config().
| secs | The minimal number of seconds between new data packets (from 1 to 255). With a 0 argument, packets will be sent as fast as possible: on the 433 and 915 MHz frequency bands, this is fixed at 100 msec (10 packets/second). On 866 MHz, the frequency depends on the number of bytes sent: for 1-byte packets, it will be up to 7 packets/second, for 66-byte bytes of data it will be approx. 1 packet/second. |
| char rf12_easyPoll | ( | void | ) |
Call this often to keep the easy transmission mode going.
This needs to be called often to keep the easy transmission mechanism going, i.e. once per millisecond or more in normal use. Failure to poll frequently enough is relatively harmless but may lead to lost acknowledgements.
| char rf12_easySend | ( | const void * | data, |
| uint8_t | size | ||
| ) |
Send new data using easy transmission mode, buffer gets copied to driver.
Submit some data bytes to send using the easy transmission mechanism. The data bytes will be copied to an internal buffer since the actual send may take place later than specified, and may need to be re-transmitted in case packets are lost of damaged in transit.
Packets will be sent no faster than the rate specified in the rf12_easyInit() call, even if called more often.
Only packets which differ from the previous packet will actually be sent. To force re-transmission even if the data hasn't changed, call "rf12_easySend(0,0)". This can be used to give a "sign of life" every once in a while, and to recover when the receiving node has been rebooted and no longer has the previous data.
The return value indicates whether a new packet transmission will be started (1), or the data is the same as before and no send is needed (0).
Note that you also have to call rf12_easyPoll periodically, because it keeps the RFM12B logic going. If you don't, rf12_easySend() will never send out any packets.
| void rf12_encrypt | ( | const uint8_t * | key | ) |
Enable encryption (null arg disables it again).
This enables or disables encryption using the public domain XXTEA algorithm by David Wheeler. The payload will be extended with 1 .. 4 bytes, containing a 6..30-bit sequence number which is incremented in the sender for each new packet.
The number of bits sent across depends on the number of padding bytes needed to make the resulting payload an exact mulitple of 4 bytes. A longer sequence number field can provide more protection against replay attacks (note that verification of this sequence number must be implemented in the receiver code).
Encrypted packets (and acknowledgements) must be 4..62 bytes long. Packets less than 4 bytes will not be encrypted. On reception, the payload length is adjusted back to the original length passed to rf12_sendStart().
There is a "long rf12seq" global which is set to the received sequence number (only valid right after rf12recvDone() returns true). When encryption is not enabled, this global is set to -1.
| key | Pointer to a 16-byte (128-bit) encryption key to use for all packet data. A null pointer disables encryption again. Note: this is an EEPROM address, not RAM! - RF12_EEPROM_EKEY is a great value to use, as defined in the include file, but another address can be specified if needed. |
| uint8_t rf12_initialize | ( | uint8_t | id, |
| uint8_t | band, | ||
| uint8_t | g | ||
| ) |
Call this once with the node ID, frequency band, and optional group.
Call this once with the node ID (0-31), frequency band (0-3), and optional group (0-255 for RFM12B, only 212 allowed for RFM12).
| id | The ID of this wireless node. ID's should be unique within the netGroup in which this node is operating. The ID range is 0 to 31, but only 1..30 are available for normal use. You can pass a single capital letter as node ID, with 'A' .. 'Z' corresponding to the node ID's 1..26, but this convention is now discouraged. ID 0 is reserved for OOK use, node ID 31 is special because it will pick up packets for any node (in the same netGroup). |
| band | This determines in which frequency range the wireless module will operate. The following pre-defined constants are available: RF12_433MHZ, RF12_868MHZ, RF12_915MHZ. You should use the one matching the module you have. |
| g | Net groups are used to separate nodes: only nodes in the same net group can communicate with each other. Valid values are 1 to 212. This parameter is optional, it defaults to 212 (0xD4) when omitted. This is the only allowed value for RFM12 modules, only RFM12B modules support other group values. |
Note that rf12_initialize() does not use the EEprom netId and netGroup settings, nor does it change the EEPROM settings. To use the netId and netGroup settings saved in EEPROM use rf12_config() instead of rf12_initialize. The choice whether to use rf12_initialize() or rf12_config() at the top of every sketch is one of personal preference. To set EEPROM settings for use with rf12_config() use the RF12demo sketch.
| char rf12_lowbat | ( | void | ) |
Return true if the supply voltage is below 3.1V.
This checks the status of the RF12 low-battery detector. It wil be 1 when the supply voltage drops below 3.1V, and 0 otherwise. This can be used to detect an impending power failure, but there are no guarantees that the power still remaining will be sufficient to send or receive further packets.
| void rf12_onOff | ( | uint8_t | value | ) |
This simulates OOK by turning the transmitter on and off via SPI commands.
Use this only when the radio was initialized with a fake zero node ID.
This can be used to send out slow bit-by-bit On Off Keying signals to other devices such as remotely controlled power switches operating in the 433, 868, or 915 MHz bands.
To use this, you need to first call rf12initialize() with a zero node ID and the proper frequency band. Then call rf12onOff() in the exact timing you need for sending out the signal. Once done, either call rf12onOff(0) to turn the transmitter off, or reinitialize the wireless module completely with a call to rf12initialize().
| value | Turn the transmitter on (if true) or off (if false). |
| uint8_t rf12_recvDone | ( | void | ) |
Call this frequently, returns true if a packet has been received.
The timing of this function is relatively coarse, because SPI transfers are used to enable / disable the transmitter. This will add some jitter to the signal, probably in the order of 10 µsec.
If the result is true, then a packet has been received and is available for processing. The following global variables will be set:
To send an acknowledgement, call rf12_sendStart() - but only right after rf12_recvDone() returns true. This is commonly done using these macros:
if(RF12_WANTS_ACK){
rf12_sendStart(RF12_ACK_REPLY,0,0);
}
| void rf12_sendNow | ( | uint8_t | hdr, |
| const void * | ptr, | ||
| uint8_t | len | ||
| ) |
This variant loops on rf12_canSend() and then calls rf12_sendStart() asap.
Wait until transmission is possible, then start it as soon as possible.
| hdr | The header contains information about the destination of the packet to send, and flags such as whether this should be acknowledged - or if it actually is an acknowledgement. |
| ptr | Pointer to the data to send as packet. |
| len | Number of data bytes to send. Must be in the range 0 .. 65. |
| void rf12_sendStart | ( | uint8_t | hdr, |
| const void * | ptr, | ||
| uint8_t | len | ||
| ) |
Call this only when rf12_recvDone() or rf12_canSend() return true.
Switch to transmission mode and send a packet. This can be either a request or a reply.
The rf12_sendStart() function may only be called in two specific situations:
Because transmissions may only be started when there is no other reception or transmission taking place.
The short form, i.e. "rf12_sendStart(hdr)" is for a special buffer-less transmit mode, as described in this weblog post.
The call with 4 arguments, i.e. "rf12_sendStart(hdr, data, length, sync)" is deprecated, as described in that same weblog post. The recommended idiom is now to call it with 3 arguments, followed by a call to rf12_sendWait().
| hdr | The header contains information about the destination of the packet to send, and flags such as whether this should be acknowledged - or if it actually is an acknowledgement. |
| ptr | Pointer to the data to send as packet. |
| len | Number of data bytes to send. Must be in the range 0 .. 65. |
| void rf12_sendStart | ( | uint8_t | hdr, |
| const void * | ptr, | ||
| uint8_t | len, | ||
| uint8_t | sync | ||
| ) |
Deprecated: use rf12_sendStart(hdr,ptr,len) followed by rf12_sendWait(sync).
| void rf12_sendWait | ( | uint8_t | mode | ) |
Wait for send to finish.
| mode | sleep mode 0=none, 1=idle, 2=standby, 3=powerdown. |
Wait for completion of the preceding rf12_sendStart() call, using the specified low-power mode.
| mode | Power-down mode during wait: 0 = NORMAL, 1 = IDLE, 2 = STANDBY, 3 = PWR_DOWN. Values 2 and 3 can cause the millisecond time to lose a few interrupts. Value 3 can only be used if the ATmega fuses have been set for fast startup, i.e. 258 CK - the default Arduino fuse settings are not suitable for full power down. |
| void rf12_set_cs | ( | uint8_t | pin | ) |
Option to set RFM12 CS (or SS) pin for use on different hardware setups.
Set to Dig10 by default for JeeNode. Can be Dig10, Dig9 or Dig8
| void rf12_sleep | ( | char | n | ) |
Power off the RFM12B, ms > 0 sets watchdog to wake up again after N * 32 ms.
This function can put the radio module to sleep and wake it up again. In sleep mode, the radio will draw only one or two microamps of current.
This function can also be used as low-power watchdog, by putting the radio to sleep and having it raise an interrupt between about 30 milliseconds and 4 seconds later.
| n | If RF12SLEEP (0), put the radio to sleep - no scheduled wakeup. If RF12WAKEUP (-1), wake the radio up so that the next call to rf12_recvDone() can restore normal reception. If value is in the range 1 .. 127, then the radio will go to sleep and generate an interrupt approximately 32*value miliiseconds later. |