├── .gitignore ├── LICENSE ├── README.md ├── rfm69 ├── __init__.py ├── configuration.py ├── constants.py ├── register_value.py └── rfm69.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Russ Garrett 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rfm69-python 2 | 3 | A library to control HopeRF RFM69-series radio modules through SPI and 4 | GPIO. This is designed for use on a Raspberry Pi but might also work on 5 | similar hardware (such as Beaglebone Black) with appropriate tweaks. 6 | 7 | Written for use with the [ukhas.net](http://ukhas.net) project. 8 | 9 | ## Requirements 10 | * Only currently tested on python 2.7, may also work on 3.4+ 11 | 12 | ## Datasheets 13 | * [RFM69W](http://www.hoperf.com/upload/rf/RFM69W-V1.3.pdf) 14 | * [Semtech SX1231](https://www.semtech.com/images/datasheet/sx1231.pdf) 15 | (the underlying RF chip, which much of the RFM69 datasheet is lifted 16 | from) 17 | 18 | ## Prior Art 19 | * [UKHASNetPiGateway](https://github.com/dbrooke/UKHASNetPiGateway) (in 20 | C/Wiring) 21 | * [ukhasnet LPC810 node](https://github.com/jamescoxon/LPC810) 22 | * [Python code for the beaglebone black](https://github.com/wcalvert/rfm69-python) 23 | -------------------------------------------------------------------------------- /rfm69/__init__.py: -------------------------------------------------------------------------------- 1 | from .rfm69 import RFM69 2 | from .configuration import RFM69Configuration 3 | -------------------------------------------------------------------------------- /rfm69/configuration.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, absolute_import, print_function, unicode_literals 2 | from collections import OrderedDict 3 | from .constants import Register, RF 4 | from .register_value import RegisterValue 5 | 6 | 7 | class OpMode(RegisterValue): 8 | REGISTER = 0x01 9 | FORMAT = [('disable_sequencer', 1), ('listen', 1), ('listen_abort', 1), ('mode', 3), (0b00, 2)] 10 | 11 | Sleep = 0b000 12 | Standby = 0b001 13 | FS = 0b010 14 | TX = 0b011 15 | RX = 0b100 16 | 17 | def __init__(self): 18 | self.disable_sequencer = False 19 | self.listen = False 20 | self.listen_abort = False 21 | self.mode = self.Standby 22 | 23 | 24 | class DataModulation(RegisterValue): 25 | REGISTER = 0x02 26 | FORMAT = [(False, 1), ('data_mode', 2), ('modulation_type', 2), (False, 1), ('modulation_shaping', 2)] 27 | 28 | ModePacket = 0b00 29 | ModeContinuousSync = 0b10 30 | ModeContinuousNoSync = 0b11 31 | 32 | TypeFSK = 0b00 33 | TypeOOK = 0b01 34 | 35 | def __init__(self): 36 | self.data_mode = self.ModePacket 37 | self.modulation_type = self.TypeFSK 38 | self.modulation_shaping = 0b00 39 | 40 | class RSSIConfig(RegisterValue): 41 | REGISTER = 0x23 42 | FORMAT = [(False, 6), ('rssi_done', 1), ('rssi_start', 1)] 43 | 44 | def __init__(self): 45 | self.rssi_done = True 46 | self.rssi_start = False 47 | 48 | 49 | class IRQFlags1(RegisterValue): 50 | REGISTER = 0x27 51 | FORMAT = [('mode_ready', 1), ('rx_ready', 1), ('tx_ready', 1), ('pll_lock', 1), ('rssi', 1), 52 | ('timeout', 1), ('auto_mode', 1), ('sync_address_match', 1)] 53 | 54 | def __init__(self): 55 | self.mode_ready = True 56 | self.rx_ready = False 57 | self.tx_ready = False 58 | self.pll_lock = False 59 | self.rssi = False 60 | self.timeout = False 61 | self.auto_mode = False 62 | self.sync_address_match = False 63 | 64 | 65 | class IRQFlags2(RegisterValue): 66 | REGISTER = 0x28 67 | FORMAT = [('fifo_full', 1), ('fifo_not_empty', 1), ('fifo_level', 1), ('fifo_overrun', 1), ('packet_sent', 1), 68 | ('payload_ready', 1), ('crc_ok', 1), (False, 1)] 69 | 70 | def __init__(self): 71 | self.fifo_full = False 72 | self.fifo_not_empty = False 73 | self.fifo_level = False 74 | self.fifo_overrun = False 75 | self.packet_sent = False 76 | self.payload_ready = False 77 | self.crc_ok = False 78 | 79 | 80 | class PacketConfig1(RegisterValue): 81 | REGISTER = 0x37 82 | FORMAT = [('variable_length', 1), ('dc_free', 2), ('crc', 1), ('crc_auto_clear_off', 1), ('address_filtering', 2), 83 | (False, 1)] 84 | 85 | DCFreeOff = 0b00 86 | DCFreeManchester = 0b01 87 | DCFreeWhitening = 0b10 88 | 89 | def __init__(self): 90 | self.variable_length = False 91 | self.dc_free = self.DCFreeOff 92 | self.crc = True 93 | self.crc_auto_clear_off = False 94 | self.address_filtering = 0b00 95 | 96 | 97 | class Temperature1(RegisterValue): 98 | REGISTER = 0x4E 99 | FORMAT = [(False, 4), ('start', 1), ('running', 1), (0b01, 2)] 100 | 101 | def __init__(self): 102 | self.start = False 103 | self.running = False 104 | 105 | 106 | class RFM69Configuration(object): 107 | """ An object to hold to represent the configuration of the RFM69. There's quite a bit of it. 108 | 109 | Some of the most-used registers are RegisterValue objects which remove the need for bitwise arithmetic. 110 | """ 111 | def __init__(self): 112 | """ Defaults here are *mostly* the same as the defaults on the RFM69W """ 113 | self.opmode = OpMode() 114 | self.data_modulation = DataModulation() 115 | 116 | self.bitrate_msb = RF.BITRATEMSB_4800 117 | self.bitrate_lsb = RF.BITRATELSB_4800 118 | 119 | self.fdev_msb = RF.FDEVMSB_5000 120 | self.fdev_lsb = RF.FDEVLSB_5000 121 | 122 | self.frf_msb = RF.FRFMSB_915 123 | self.frf_mid = RF.FRFMID_915 124 | self.frf_lsb = RF.FRFLSB_915 125 | 126 | self.afc_ctl = RF.AFCLOWBETA_OFF 127 | 128 | self.pa_level = RF.PALEVEL_PA0_ON | RF.PALEVEL_PA1_OFF | RF.PALEVEL_PA2_OFF | 0x18 129 | self.pa_ramp = RF.PARAMP_40 130 | 131 | self.ocp = RF.OCP_ON | RF.OCP_TRIM_95 132 | self.lna = RF.LNA_ZIN_200 133 | self.rx_bw = RF.RXBW_DCCFREQ_010 | RF.RXBW_MANT_24 | RF.RXBW_EXP_5 134 | self.afc_fei = RF.AFCFEI_AFCAUTO_OFF | RF.AFCFEI_AFCAUTOCLEAR_OFF 135 | 136 | self.dio_mapping_1 = RF.DIOMAPPING1_DIO0_01 137 | self.dio_mapping_2 = RF.DIOMAPPING2_CLKOUT_OFF 138 | 139 | self.rssi_threshold = 200 140 | 141 | self.rx_timeout_1 = 0 142 | self.rx_timeout_2 = 40 143 | 144 | self.sync_config = RF.SYNC_ON | RF.SYNC_FIFOFILL_AUTO | RF.SYNC_SIZE_4 | RF.SYNC_TOL_0 145 | self.sync_value_1 = 0 146 | self.sync_value_2 = 0 147 | self.sync_value_3 = 0 148 | self.sync_value_4 = 0 149 | self.sync_value_5 = 0 150 | self.sync_value_6 = 0 151 | self.sync_value_7 = 0 152 | self.sync_value_8 = 0 153 | 154 | self.packet_config_1 = PacketConfig1() 155 | self.payload_length = 0x40 156 | 157 | self.fifo_threshold = RF.FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF.FIFOTHRESH_VALUE 158 | self.packet_config_2 = RF.PACKET2_RXRESTARTDELAY_2BITS | RF.PACKET2_AUTORXRESTART_ON | RF.PACKET2_AES_OFF 159 | self.test_dagc = RF.DAGC_IMPROVED_LOWBETA0 160 | self.test_afc = 0x0e 161 | 162 | def get_registers(self): 163 | regs = OrderedDict() 164 | regs[Register.OPMODE] = self.opmode.pack() 165 | regs[Register.DATAMODUL] = self.data_modulation.pack() 166 | regs[Register.BITRATEMSB] = self.bitrate_msb 167 | regs[Register.BITRATELSB] = self.bitrate_lsb 168 | regs[Register.FDEVMSB] = self.fdev_msb 169 | regs[Register.FDEVLSB] = self.fdev_lsb 170 | regs[Register.FRFMSB] = self.frf_msb 171 | regs[Register.FRFMID] = self.frf_mid 172 | regs[Register.FRFLSB] = self.frf_lsb 173 | regs[Register.AFCCTRL] = self.afc_ctl 174 | regs[Register.PALEVEL] = self.pa_level 175 | regs[Register.PARAMP] = self.pa_ramp 176 | regs[Register.OCP] = self.ocp 177 | regs[Register.LNA] = self.lna 178 | regs[Register.RXBW] = self.rx_bw 179 | regs[Register.AFCFEI] = self.afc_fei 180 | regs[Register.DIOMAPPING1] = self.dio_mapping_1 181 | regs[Register.DIOMAPPING2] = self.dio_mapping_2 182 | regs[Register.RSSITHRESH] = self.rssi_threshold 183 | regs[Register.RXTIMEOUT1] = self.rx_timeout_1 184 | regs[Register.RXTIMEOUT2] = self.rx_timeout_2 185 | regs[Register.SYNCCONFIG] = self.sync_config 186 | regs[Register.SYNCVALUE1] = self.sync_value_1 187 | regs[Register.SYNCVALUE2] = self.sync_value_2 188 | regs[Register.SYNCVALUE3] = self.sync_value_3 189 | regs[Register.SYNCVALUE4] = self.sync_value_4 190 | regs[Register.SYNCVALUE5] = self.sync_value_5 191 | regs[Register.SYNCVALUE6] = self.sync_value_6 192 | regs[Register.SYNCVALUE7] = self.sync_value_7 193 | regs[Register.SYNCVALUE8] = self.sync_value_8 194 | regs[Register.PACKETCONFIG1] = self.packet_config_1.pack() 195 | regs[Register.PAYLOADLENGTH] = self.payload_length 196 | regs[Register.FIFOTHRESH] = self.fifo_threshold 197 | regs[Register.PACKETCONFIG2] = self.packet_config_2 198 | regs[Register.TESTDAGC] = self.test_dagc 199 | regs[Register.TESTAFC] = self.test_afc 200 | regs[255] = 0 201 | return regs 202 | -------------------------------------------------------------------------------- /rfm69/constants.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class Register(Enum): 5 | FIFO = 0x00 6 | OPMODE = 0x01 7 | DATAMODUL = 0x02 8 | BITRATEMSB = 0x03 9 | BITRATELSB = 0x04 10 | FDEVMSB = 0x05 11 | FDEVLSB = 0x06 12 | FRFMSB = 0x07 13 | FRFMID = 0x08 14 | FRFLSB = 0x09 15 | OSC1 = 0x0A 16 | AFCCTRL = 0x0B 17 | LOWBAT = 0x0C 18 | LISTEN1 = 0x0D 19 | LISTEN2 = 0x0E 20 | LISTEN3 = 0x0F 21 | VERSION = 0x10 22 | PALEVEL = 0x11 23 | PARAMP = 0x12 24 | OCP = 0x13 25 | AGCREF = 0x14 26 | AGCTHRESH1 = 0x15 27 | AGCTHRESH2 = 0x16 28 | AGCTHRESH3 = 0x17 29 | LNA = 0x18 30 | RXBW = 0x19 31 | AFCBW = 0x1A 32 | OOKPEAK = 0x1B 33 | OOKAVG = 0x1C 34 | OOKFIX = 0x1D 35 | AFCFEI = 0x1E 36 | AFCMSB = 0x1F 37 | AFCLSB = 0x20 38 | FEIMSB = 0x21 39 | FEILSB = 0x22 40 | RSSICONFIG = 0x23 41 | RSSIVALUE = 0x24 42 | DIOMAPPING1 = 0x25 43 | DIOMAPPING2 = 0x26 44 | IRQFLAGS1 = 0x27 45 | IRQFLAGS2 = 0x28 46 | RSSITHRESH = 0x29 47 | RXTIMEOUT1 = 0x2A 48 | RXTIMEOUT2 = 0x2B 49 | PREAMBLEMSB = 0x2C 50 | PREAMBLELSB = 0x2D 51 | SYNCCONFIG = 0x2E 52 | SYNCVALUE1 = 0x2F 53 | SYNCVALUE2 = 0x30 54 | SYNCVALUE3 = 0x31 55 | SYNCVALUE4 = 0x32 56 | SYNCVALUE5 = 0x33 57 | SYNCVALUE6 = 0x34 58 | SYNCVALUE7 = 0x35 59 | SYNCVALUE8 = 0x36 60 | PACKETCONFIG1 = 0x37 61 | PAYLOADLENGTH = 0x38 62 | NODEADRS = 0x39 63 | BROADCASTADRS = 0x3A 64 | AUTOMODES = 0x3B 65 | FIFOTHRESH = 0x3C 66 | PACKETCONFIG2 = 0x3D 67 | AESKEY1 = 0x3E 68 | AESKEY2 = 0x3F 69 | AESKEY3 = 0x40 70 | AESKEY4 = 0x41 71 | AESKEY5 = 0x42 72 | AESKEY6 = 0x43 73 | AESKEY7 = 0x44 74 | AESKEY8 = 0x45 75 | AESKEY9 = 0x46 76 | AESKEY10 = 0x47 77 | AESKEY11 = 0x48 78 | AESKEY12 = 0x49 79 | AESKEY13 = 0x4A 80 | AESKEY14 = 0x4B 81 | AESKEY15 = 0x4C 82 | AESKEY16 = 0x4D 83 | TEMP1 = 0x4E 84 | TEMP2 = 0x4F 85 | TESTPA1 = 0x5A # only present on RFM69HW/SX1231H 86 | TESTPA2 = 0x5C # only present on RFM69HW/SX1231H 87 | TESTDAGC = 0x6F 88 | TESTAFC = 0x71 89 | 90 | 91 | class RF(Enum): 92 | OPMODE_SEQUENCER_OFF = 0x80 93 | OPMODE_SEQUENCER_ON = 0x00 # Default 94 | 95 | OPMODE_LISTEN_ON = 0x40 96 | OPMODE_LISTEN_OFF = 0x00 # Default 97 | 98 | OPMODE_LISTENABORT = 0x20 99 | 100 | OPMODE_SLEEP = 0x00 101 | OPMODE_STANDBY = 0x04 # Default 102 | OPMODE_SYNTHESIZER = 0x08 103 | OPMODE_TRANSMITTER = 0x0C 104 | OPMODE_RECEIVER = 0x10 105 | 106 | # Reg Data Modul 107 | DATAMODUL_DATAMODE_PACKET = 0x00 # Default 108 | DATAMODUL_DATAMODE_CONTINUOUS = 0x40 109 | DATAMODUL_DATAMODE_CONTINUOUSNOBSYNC = 0x60 110 | 111 | DATAMODUL_MODULATIONTYPE_FSK = 0x00 # Default 112 | DATAMODUL_MODULATIONTYPE_OOK = 0x08 113 | 114 | DATAMODUL_MODULATIONSHAPING_00 = 0x00 # Default 115 | DATAMODUL_MODULATIONSHAPING_01 = 0x01 116 | DATAMODUL_MODULATIONSHAPING_10 = 0x02 117 | DATAMODUL_MODULATIONSHAPING_11 = 0x03 118 | 119 | # RegBitRate (bits/sec) example bitrates 120 | BITRATEMSB_1200 = 0x68 121 | BITRATELSB_1200 = 0x2B 122 | BITRATEMSB_2400 = 0x34 123 | BITRATELSB_2400 = 0x15 124 | BITRATEMSB_4800 = 0x1A # Default 125 | BITRATELSB_4800 = 0x0B # Default 126 | BITRATEMSB_9600 = 0x0D 127 | BITRATELSB_9600 = 0x05 128 | BITRATEMSB_19200 = 0x06 129 | BITRATELSB_19200 = 0x83 130 | BITRATEMSB_38400 = 0x03 131 | BITRATELSB_38400 = 0x41 132 | BITRATEMSB_38323 = 0x03 133 | BITRATELSB_38323 = 0x43 134 | BITRATEMSB_34482 = 0x03 135 | BITRATELSB_34482 = 0xA0 136 | BITRATEMSB_76800 = 0x01 137 | BITRATELSB_76800 = 0xA1 138 | BITRATEMSB_153600 = 0x00 139 | BITRATELSB_153600 = 0xD0 140 | BITRATEMSB_57600 = 0x02 141 | BITRATELSB_57600 = 0x2C 142 | BITRATEMSB_115200 = 0x01 143 | BITRATELSB_115200 = 0x16 144 | BITRATEMSB_12500 = 0x0A 145 | BITRATELSB_12500 = 0x00 146 | BITRATEMSB_25000 = 0x05 147 | BITRATELSB_25000 = 0x00 148 | BITRATEMSB_50000 = 0x02 149 | BITRATELSB_50000 = 0x80 150 | BITRATEMSB_100000 = 0x01 151 | BITRATELSB_100000 = 0x40 152 | BITRATEMSB_150000 = 0x00 153 | BITRATELSB_150000 = 0xD5 154 | BITRATEMSB_200000 = 0x00 155 | BITRATELSB_200000 = 0xA0 156 | BITRATEMSB_250000 = 0x00 157 | BITRATELSB_250000 = 0x80 158 | BITRATEMSB_300000 = 0x00 159 | BITRATELSB_300000 = 0x6B 160 | BITRATEMSB_32768 = 0x03 161 | BITRATELSB_32768 = 0xD1 162 | # custom bitrates 163 | BITRATEMSB_55555 = 0x02 164 | BITRATELSB_55555 = 0x40 165 | BITRATEMSB_200KBPS = 0x00 166 | BITRATELSB_200KBPS = 0xa0 167 | 168 | # RegFdev - frequency deviation (Hz) 169 | FDEVMSB_2000 = 0x00 170 | FDEVLSB_2000 = 0x21 171 | FDEVMSB_5000 = 0x00 # Default 172 | FDEVLSB_5000 = 0x52 # Default 173 | FDEVMSB_7500 = 0x00 174 | FDEVLSB_7500 = 0x7B 175 | FDEVMSB_10000 = 0x00 176 | FDEVLSB_10000 = 0xA4 177 | FDEVMSB_15000 = 0x00 178 | FDEVLSB_15000 = 0xF6 179 | FDEVMSB_20000 = 0x01 180 | FDEVLSB_20000 = 0x48 181 | FDEVMSB_25000 = 0x01 182 | FDEVLSB_25000 = 0x9A 183 | FDEVMSB_30000 = 0x01 184 | FDEVLSB_30000 = 0xEC 185 | FDEVMSB_35000 = 0x02 186 | FDEVLSB_35000 = 0x3D 187 | FDEVMSB_40000 = 0x02 188 | FDEVLSB_40000 = 0x8F 189 | FDEVMSB_45000 = 0x02 190 | FDEVLSB_45000 = 0xE1 191 | FDEVMSB_50000 = 0x03 192 | FDEVLSB_50000 = 0x33 193 | FDEVMSB_55000 = 0x03 194 | FDEVLSB_55000 = 0x85 195 | FDEVMSB_60000 = 0x03 196 | FDEVLSB_60000 = 0xD7 197 | FDEVMSB_65000 = 0x04 198 | FDEVLSB_65000 = 0x29 199 | FDEVMSB_70000 = 0x04 200 | FDEVLSB_70000 = 0x7B 201 | FDEVMSB_75000 = 0x04 202 | FDEVLSB_75000 = 0xCD 203 | FDEVMSB_80000 = 0x05 204 | FDEVLSB_80000 = 0x1F 205 | FDEVMSB_85000 = 0x05 206 | FDEVLSB_85000 = 0x71 207 | FDEVMSB_90000 = 0x05 208 | FDEVLSB_90000 = 0xC3 209 | FDEVMSB_95000 = 0x06 210 | FDEVLSB_95000 = 0x14 211 | FDEVMSB_100000 = 0x06 212 | FDEVLSB_100000 = 0x66 213 | FDEVMSB_110000 = 0x07 214 | FDEVLSB_110000 = 0x0A 215 | FDEVMSB_120000 = 0x07 216 | FDEVLSB_120000 = 0xAE 217 | FDEVMSB_130000 = 0x08 218 | FDEVLSB_130000 = 0x52 219 | FDEVMSB_140000 = 0x08 220 | FDEVLSB_140000 = 0xF6 221 | FDEVMSB_150000 = 0x09 222 | FDEVLSB_150000 = 0x9A 223 | FDEVMSB_160000 = 0x0A 224 | FDEVLSB_160000 = 0x3D 225 | FDEVMSB_170000 = 0x0A 226 | FDEVLSB_170000 = 0xE1 227 | FDEVMSB_180000 = 0x0B 228 | FDEVLSB_180000 = 0x85 229 | FDEVMSB_190000 = 0x0C 230 | FDEVLSB_190000 = 0x29 231 | FDEVMSB_200000 = 0x0C 232 | FDEVLSB_200000 = 0xCD 233 | FDEVMSB_210000 = 0x0D 234 | FDEVLSB_210000 = 0x71 235 | FDEVMSB_220000 = 0x0E 236 | FDEVLSB_220000 = 0x14 237 | FDEVMSB_230000 = 0x0E 238 | FDEVLSB_230000 = 0xB8 239 | FDEVMSB_240000 = 0x0F 240 | FDEVLSB_240000 = 0x5C 241 | FDEVMSB_250000 = 0x10 242 | FDEVLSB_250000 = 0x00 243 | FDEVMSB_260000 = 0x10 244 | FDEVLSB_260000 = 0xA4 245 | FDEVMSB_270000 = 0x11 246 | FDEVLSB_270000 = 0x48 247 | FDEVMSB_280000 = 0x11 248 | FDEVLSB_280000 = 0xEC 249 | FDEVMSB_290000 = 0x12 250 | FDEVLSB_290000 = 0x8F 251 | FDEVMSB_300000 = 0x13 252 | FDEVLSB_300000 = 0x33 253 | 254 | # Reg Frf (MHz) - carrier frequency 255 | # 315 Mhz band 256 | FRFMSB_314 = 0x4E 257 | FRFMID_314 = 0x80 258 | FRFLSB_314 = 0x00 259 | FRFMSB_315 = 0x4E 260 | FRFMID_315 = 0xC0 261 | FRFLSB_315 = 0x00 262 | FRFMSB_316 = 0x4F 263 | FRFMID_316 = 0x00 264 | FRFLSB_316 = 0x00 265 | # 433 mhz band 266 | FRFMSB_433 = 0x6C 267 | FRFMID_433 = 0x40 268 | FRFLSB_433 = 0x00 269 | FRFMSB_434 = 0x6C 270 | FRFMID_434 = 0x80 271 | FRFLSB_434 = 0x00 272 | FRFMSB_435 = 0x6C 273 | FRFMID_435 = 0xC0 274 | FRFLSB_435 = 0x00 275 | # 868 Mhz band 276 | FRFMSB_863 = 0xD7 277 | FRFMID_863 = 0xC0 278 | FRFLSB_863 = 0x00 279 | FRFMSB_864 = 0xD8 280 | FRFMID_864 = 0x00 281 | FRFLSB_864 = 0x00 282 | FRFMSB_865 = 0xD8 283 | FRFMID_865 = 0x40 284 | FRFLSB_865 = 0x00 285 | FRFMSB_866 = 0xD8 286 | FRFMID_866 = 0x80 287 | FRFLSB_866 = 0x00 288 | FRFMSB_867 = 0xD8 289 | FRFMID_867 = 0xC0 290 | FRFLSB_867 = 0x00 291 | FRFMSB_868 = 0xD9 292 | FRFMID_868 = 0x00 293 | FRFLSB_868 = 0x00 294 | FRFMSB_869 = 0xD9 295 | FRFMID_869 = 0x40 296 | FRFLSB_869 = 0x00 297 | FRFMSB_870 = 0xD9 298 | FRFMID_870 = 0x80 299 | FRFLSB_870 = 0x00 300 | # 915 Mhz band 301 | FRFMSB_902 = 0xE1 302 | FRFMID_902 = 0x80 303 | FRFLSB_902 = 0x00 304 | FRFMSB_903 = 0xE1 305 | FRFMID_903 = 0xC0 306 | FRFLSB_903 = 0x00 307 | FRFMSB_904 = 0xE2 308 | FRFMID_904 = 0x00 309 | FRFLSB_904 = 0x00 310 | FRFMSB_905 = 0xE2 311 | FRFMID_905 = 0x40 312 | FRFLSB_905 = 0x00 313 | FRFMSB_906 = 0xE2 314 | FRFMID_906 = 0x80 315 | FRFLSB_906 = 0x00 316 | FRFMSB_907 = 0xE2 317 | FRFMID_907 = 0xC0 318 | FRFLSB_907 = 0x00 319 | FRFMSB_908 = 0xE3 320 | FRFMID_908 = 0x00 321 | FRFLSB_908 = 0x00 322 | FRFMSB_909 = 0xE3 323 | FRFMID_909 = 0x40 324 | FRFLSB_909 = 0x00 325 | FRFMSB_910 = 0xE3 326 | FRFMID_910 = 0x80 327 | FRFLSB_910 = 0x00 328 | FRFMSB_911 = 0xE3 329 | FRFMID_911 = 0xC0 330 | FRFLSB_911 = 0x00 331 | FRFMSB_912 = 0xE4 332 | FRFMID_912 = 0x00 333 | FRFLSB_912 = 0x00 334 | FRFMSB_913 = 0xE4 335 | FRFMID_913 = 0x40 336 | FRFLSB_913 = 0x00 337 | FRFMSB_914 = 0xE4 338 | FRFMID_914 = 0x80 339 | FRFLSB_914 = 0x00 340 | FRFMSB_915 = 0xE4 # Default 341 | FRFMID_915 = 0xC0 # Default 342 | FRFLSB_915 = 0x00 # Default 343 | FRFMSB_916 = 0xE5 344 | FRFMID_916 = 0x00 345 | FRFLSB_916 = 0x00 346 | FRFMSB_917 = 0xE5 347 | FRFMID_917 = 0x40 348 | FRFLSB_917 = 0x00 349 | FRFMSB_918 = 0xE5 350 | FRFMID_918 = 0x80 351 | FRFLSB_918 = 0x00 352 | FRFMSB_919 = 0xE5 353 | FRFMID_919 = 0xC0 354 | FRFLSB_919 = 0x00 355 | FRFMSB_920 = 0xE6 356 | FRFMID_920 = 0x00 357 | FRFLSB_920 = 0x00 358 | FRFMSB_921 = 0xE6 359 | FRFMID_921 = 0x40 360 | FRFLSB_921 = 0x00 361 | FRFMSB_922 = 0xE6 362 | FRFMID_922 = 0x80 363 | FRFLSB_922 = 0x00 364 | FRFMSB_923 = 0xE6 365 | FRFMID_923 = 0xC0 366 | FRFLSB_923 = 0x00 367 | FRFMSB_924 = 0xE7 368 | FRFMID_924 = 0x00 369 | FRFLSB_924 = 0x00 370 | FRFMSB_925 = 0xE7 371 | FRFMID_925 = 0x40 372 | FRFLSB_925 = 0x00 373 | FRFMSB_926 = 0xE7 374 | FRFMID_926 = 0x80 375 | FRFLSB_926 = 0x00 376 | FRFMSB_927 = 0xE7 377 | FRFMID_927 = 0xC0 378 | FRFLSB_927 = 0x00 379 | FRFMSB_928 = 0xE8 380 | FRFMID_928 = 0x00 381 | FRFLSB_928 = 0x00 382 | 383 | # Reg Osc 1 384 | OSC1_RCCAL_START = 0x80 385 | OSC1_RCCAL_DONE = 0x40 386 | 387 | AFCLOWBETA_ON = 0x20 388 | AFCLOWBETA_OFF = 0x00 # Default 389 | 390 | # Reg Low Bat 391 | LOWBAT_MONITOR = 0x10 392 | LOWBAT_ON = 0x08 393 | LOWBAT_OFF = 0x00 # Default 394 | 395 | LOWBAT_TRIM_1695 = 0x00 396 | LOWBAT_TRIM_1764 = 0x01 397 | LOWBAT_TRIM_1835 = 0x02 # Default 398 | LOWBAT_TRIM_1905 = 0x03 399 | LOWBAT_TRIM_1976 = 0x04 400 | LOWBAT_TRIM_2045 = 0x05 401 | LOWBAT_TRIM_2116 = 0x06 402 | LOWBAT_TRIM_2185 = 0x07 403 | 404 | # Reg Listen 1 405 | LISTEN1_RESOL_64 = 0x50 406 | LISTEN1_RESOL_4100 = 0xA0 # Default 407 | LISTEN1_RESOL_262000 = 0xF0 408 | 409 | LISTEN1_CRITERIA_RSSI = 0x00 # Default 410 | LISTEN1_CRITERIA_RSSIANDSYNC = 0x08 411 | 412 | LISTEN1_END_00 = 0x00 413 | LISTEN1_END_01 = 0x02 # Default 414 | LISTEN1_END_10 = 0x04 415 | 416 | # Reg Listen 2 417 | LISTEN2_COEFIDLE_VALUE = 0xF5 # Default 418 | 419 | # Reg Listen 3 420 | LISTEN3_COEFRX_VALUE = 0x20 # Default 421 | 422 | # Reg PaLevel 423 | PALEVEL_PA0_ON = 0x80 # Default 424 | PALEVEL_PA0_OFF = 0x00 425 | PALEVEL_PA1_ON = 0x40 426 | PALEVEL_PA1_OFF = 0x00 # Default 427 | PALEVEL_PA2_ON = 0x20 428 | PALEVEL_PA2_OFF = 0x00 # Default 429 | 430 | PALEVEL_OUTPUTPOWER_00000 = 0x00 431 | PALEVEL_OUTPUTPOWER_00001 = 0x01 432 | PALEVEL_OUTPUTPOWER_00010 = 0x02 433 | PALEVEL_OUTPUTPOWER_00011 = 0x03 434 | PALEVEL_OUTPUTPOWER_00100 = 0x04 435 | PALEVEL_OUTPUTPOWER_00101 = 0x05 436 | PALEVEL_OUTPUTPOWER_00110 = 0x06 437 | PALEVEL_OUTPUTPOWER_00111 = 0x07 438 | PALEVEL_OUTPUTPOWER_01000 = 0x08 439 | PALEVEL_OUTPUTPOWER_01001 = 0x09 440 | PALEVEL_OUTPUTPOWER_01010 = 0x0A 441 | PALEVEL_OUTPUTPOWER_01011 = 0x0B 442 | PALEVEL_OUTPUTPOWER_01100 = 0x0C 443 | PALEVEL_OUTPUTPOWER_01101 = 0x0D 444 | PALEVEL_OUTPUTPOWER_01110 = 0x0E 445 | PALEVEL_OUTPUTPOWER_01111 = 0x0F 446 | PALEVEL_OUTPUTPOWER_10000 = 0x10 447 | PALEVEL_OUTPUTPOWER_10001 = 0x11 448 | PALEVEL_OUTPUTPOWER_10010 = 0x12 449 | PALEVEL_OUTPUTPOWER_10011 = 0x13 450 | PALEVEL_OUTPUTPOWER_10100 = 0x14 451 | PALEVEL_OUTPUTPOWER_10101 = 0x15 452 | PALEVEL_OUTPUTPOWER_10110 = 0x16 453 | PALEVEL_OUTPUTPOWER_10111 = 0x17 454 | PALEVEL_OUTPUTPOWER_11000 = 0x18 455 | PALEVEL_OUTPUTPOWER_11001 = 0x19 456 | PALEVEL_OUTPUTPOWER_11010 = 0x1A 457 | PALEVEL_OUTPUTPOWER_11011 = 0x1B 458 | PALEVEL_OUTPUTPOWER_11100 = 0x1C 459 | PALEVEL_OUTPUTPOWER_11101 = 0x1D 460 | PALEVEL_OUTPUTPOWER_11110 = 0x1E 461 | PALEVEL_OUTPUTPOWER_11111 = 0x1F # Default 462 | 463 | # Reg PaRamp 464 | PARAMP_3400 = 0x00 465 | PARAMP_2000 = 0x01 466 | PARAMP_1000 = 0x02 467 | PARAMP_500 = 0x03 468 | PARAMP_250 = 0x04 469 | PARAMP_125 = 0x05 470 | PARAMP_100 = 0x06 471 | PARAMP_62 = 0x07 472 | PARAMP_50 = 0x08 473 | PARAMP_40 = 0x09 # Default 474 | PARAMP_31 = 0x0A 475 | PARAMP_25 = 0x0B 476 | PARAMP_20 = 0x0C 477 | PARAMP_15 = 0x0D 478 | PARAMP_12 = 0x0E 479 | PARAMP_10 = 0x0F 480 | 481 | # Reg Ocp 482 | OCP_OFF = 0x0F 483 | OCP_ON = 0x1A # Default 484 | 485 | OCP_TRIM_45 = 0x00 486 | OCP_TRIM_50 = 0x01 487 | OCP_TRIM_55 = 0x02 488 | OCP_TRIM_60 = 0x03 489 | OCP_TRIM_65 = 0x04 490 | OCP_TRIM_70 = 0x05 491 | OCP_TRIM_75 = 0x06 492 | OCP_TRIM_80 = 0x07 493 | OCP_TRIM_85 = 0x08 494 | OCP_TRIM_90 = 0x09 495 | OCP_TRIM_95 = 0x0A 496 | OCP_TRIM_100 = 0x0B # Default 497 | OCP_TRIM_105 = 0x0C 498 | OCP_TRIM_110 = 0x0D 499 | OCP_TRIM_115 = 0x0E 500 | OCP_TRIM_120 = 0x0F 501 | 502 | # Reg Agc Ref 503 | AGCREF_AUTO_ON = 0x40 # Default 504 | AGCREF_AUTO_OFF = 0x00 505 | 506 | AGCREF_LEVEL_MINUS80 = 0x00 # Default 507 | AGCREF_LEVEL_MINUS81 = 0x01 508 | AGCREF_LEVEL_MINUS82 = 0x02 509 | AGCREF_LEVEL_MINUS83 = 0x03 510 | AGCREF_LEVEL_MINUS84 = 0x04 511 | AGCREF_LEVEL_MINUS85 = 0x05 512 | AGCREF_LEVEL_MINUS86 = 0x06 513 | AGCREF_LEVEL_MINUS87 = 0x07 514 | AGCREF_LEVEL_MINUS88 = 0x08 515 | AGCREF_LEVEL_MINUS89 = 0x09 516 | AGCREF_LEVEL_MINUS90 = 0x0A 517 | AGCREF_LEVEL_MINUS91 = 0x0B 518 | AGCREF_LEVEL_MINUS92 = 0x0C 519 | AGCREF_LEVEL_MINUS93 = 0x0D 520 | AGCREF_LEVEL_MINUS94 = 0x0E 521 | AGCREF_LEVEL_MINUS95 = 0x0F 522 | AGCREF_LEVEL_MINUS96 = 0x10 523 | AGCREF_LEVEL_MINUS97 = 0x11 524 | AGCREF_LEVEL_MINUS98 = 0x12 525 | AGCREF_LEVEL_MINUS99 = 0x13 526 | AGCREF_LEVEL_MINUS100 = 0x14 527 | AGCREF_LEVEL_MINUS101 = 0x15 528 | AGCREF_LEVEL_MINUS102 = 0x16 529 | AGCREF_LEVEL_MINUS103 = 0x17 530 | AGCREF_LEVEL_MINUS104 = 0x18 531 | AGCREF_LEVEL_MINUS105 = 0x19 532 | AGCREF_LEVEL_MINUS106 = 0x1A 533 | AGCREF_LEVEL_MINUS107 = 0x1B 534 | AGCREF_LEVEL_MINUS108 = 0x1C 535 | AGCREF_LEVEL_MINUS109 = 0x1D 536 | AGCREF_LEVEL_MINUS110 = 0x1E 537 | AGCREF_LEVEL_MINUS111 = 0x1F 538 | AGCREF_LEVEL_MINUS112 = 0x20 539 | AGCREF_LEVEL_MINUS113 = 0x21 540 | AGCREF_LEVEL_MINUS114 = 0x22 541 | AGCREF_LEVEL_MINUS115 = 0x23 542 | AGCREF_LEVEL_MINUS116 = 0x24 543 | AGCREF_LEVEL_MINUS117 = 0x25 544 | AGCREF_LEVEL_MINUS118 = 0x26 545 | AGCREF_LEVEL_MINUS119 = 0x27 546 | AGCREF_LEVEL_MINUS120 = 0x28 547 | AGCREF_LEVEL_MINUS121 = 0x29 548 | AGCREF_LEVEL_MINUS122 = 0x2A 549 | AGCREF_LEVEL_MINUS123 = 0x2B 550 | AGCREF_LEVEL_MINUS124 = 0x2C 551 | AGCREF_LEVEL_MINUS125 = 0x2D 552 | AGCREF_LEVEL_MINUS126 = 0x2E 553 | AGCREF_LEVEL_MINUS127 = 0x2F 554 | AGCREF_LEVEL_MINUS128 = 0x30 555 | AGCREF_LEVEL_MINUS129 = 0x31 556 | AGCREF_LEVEL_MINUS130 = 0x32 557 | AGCREF_LEVEL_MINUS131 = 0x33 558 | AGCREF_LEVEL_MINUS132 = 0x34 559 | AGCREF_LEVEL_MINUS133 = 0x35 560 | AGCREF_LEVEL_MINUS134 = 0x36 561 | AGCREF_LEVEL_MINUS135 = 0x37 562 | AGCREF_LEVEL_MINUS136 = 0x38 563 | AGCREF_LEVEL_MINUS137 = 0x39 564 | AGCREF_LEVEL_MINUS138 = 0x3A 565 | AGCREF_LEVEL_MINUS139 = 0x3B 566 | AGCREF_LEVEL_MINUS140 = 0x3C 567 | AGCREF_LEVEL_MINUS141 = 0x3D 568 | AGCREF_LEVEL_MINUS142 = 0x3E 569 | AGCREF_LEVEL_MINUS143 = 0x3F 570 | 571 | # Reg Agc Thresh 1 572 | AGCTHRESH1_SNRMARGIN_000 = 0x00 573 | AGCTHRESH1_SNRMARGIN_001 = 0x20 574 | AGCTHRESH1_SNRMARGIN_010 = 0x40 575 | AGCTHRESH1_SNRMARGIN_011 = 0x60 576 | AGCTHRESH1_SNRMARGIN_100 = 0x80 577 | AGCTHRESH1_SNRMARGIN_101 = 0xA0 # Default 578 | AGCTHRESH1_SNRMARGIN_110 = 0xC0 579 | AGCTHRESH1_SNRMARGIN_111 = 0xE0 580 | 581 | AGCTHRESH1_STEP1_0 = 0x00 582 | AGCTHRESH1_STEP1_1 = 0x01 583 | AGCTHRESH1_STEP1_2 = 0x02 584 | AGCTHRESH1_STEP1_3 = 0x03 585 | AGCTHRESH1_STEP1_4 = 0x04 586 | AGCTHRESH1_STEP1_5 = 0x05 587 | AGCTHRESH1_STEP1_6 = 0x06 588 | AGCTHRESH1_STEP1_7 = 0x07 589 | AGCTHRESH1_STEP1_8 = 0x08 590 | AGCTHRESH1_STEP1_9 = 0x09 591 | AGCTHRESH1_STEP1_10 = 0x0A 592 | AGCTHRESH1_STEP1_11 = 0x0B 593 | AGCTHRESH1_STEP1_12 = 0x0C 594 | AGCTHRESH1_STEP1_13 = 0x0D 595 | AGCTHRESH1_STEP1_14 = 0x0E 596 | AGCTHRESH1_STEP1_15 = 0x0F 597 | AGCTHRESH1_STEP1_16 = 0x10 # Default 598 | AGCTHRESH1_STEP1_17 = 0x11 599 | AGCTHRESH1_STEP1_18 = 0x12 600 | AGCTHRESH1_STEP1_19 = 0x13 601 | AGCTHRESH1_STEP1_20 = 0x14 602 | AGCTHRESH1_STEP1_21 = 0x15 603 | AGCTHRESH1_STEP1_22 = 0x16 604 | AGCTHRESH1_STEP1_23 = 0x17 605 | AGCTHRESH1_STEP1_24 = 0x18 606 | AGCTHRESH1_STEP1_25 = 0x19 607 | AGCTHRESH1_STEP1_26 = 0x1A 608 | AGCTHRESH1_STEP1_27 = 0x1B 609 | AGCTHRESH1_STEP1_28 = 0x1C 610 | AGCTHRESH1_STEP1_29 = 0x1D 611 | AGCTHRESH1_STEP1_30 = 0x1E 612 | AGCTHRESH1_STEP1_31 = 0x1F 613 | 614 | # Reg Agc Thresh 2 615 | AGCTHRESH2_STEP2_0 = 0x00 616 | AGCTHRESH2_STEP2_1 = 0x10 617 | AGCTHRESH2_STEP2_2 = 0x20 618 | AGCTHRESH2_STEP2_3 = 0x30 # XXX wrong -- Default 619 | AGCTHRESH2_STEP2_4 = 0x40 620 | AGCTHRESH2_STEP2_5 = 0x50 621 | AGCTHRESH2_STEP2_6 = 0x60 622 | AGCTHRESH2_STEP2_7 = 0x70 # Default 623 | AGCTHRESH2_STEP2_8 = 0x80 624 | AGCTHRESH2_STEP2_9 = 0x90 625 | AGCTHRESH2_STEP2_10 = 0xA0 626 | AGCTHRESH2_STEP2_11 = 0xB0 627 | AGCTHRESH2_STEP2_12 = 0xC0 628 | AGCTHRESH2_STEP2_13 = 0xD0 629 | AGCTHRESH2_STEP2_14 = 0xE0 630 | AGCTHRESH2_STEP2_15 = 0xF0 631 | 632 | AGCTHRESH2_STEP3_0 = 0x00 633 | AGCTHRESH2_STEP3_1 = 0x01 634 | AGCTHRESH2_STEP3_2 = 0x02 635 | AGCTHRESH2_STEP3_3 = 0x03 636 | AGCTHRESH2_STEP3_4 = 0x04 637 | AGCTHRESH2_STEP3_5 = 0x05 638 | AGCTHRESH2_STEP3_6 = 0x06 639 | AGCTHRESH2_STEP3_7 = 0x07 640 | AGCTHRESH2_STEP3_8 = 0x08 641 | AGCTHRESH2_STEP3_9 = 0x09 642 | AGCTHRESH2_STEP3_10 = 0x0A 643 | AGCTHRESH2_STEP3_11 = 0x0B # Default 644 | AGCTHRESH2_STEP3_12 = 0x0C 645 | AGCTHRESH2_STEP3_13 = 0x0D 646 | AGCTHRESH2_STEP3_14 = 0x0E 647 | AGCTHRESH2_STEP3_15 = 0x0F 648 | 649 | # Reg Agc Thresh 3 650 | AGCTHRESH3_STEP4_0 = 0x00 651 | AGCTHRESH3_STEP4_1 = 0x10 652 | AGCTHRESH3_STEP4_2 = 0x20 653 | AGCTHRESH3_STEP4_3 = 0x30 654 | AGCTHRESH3_STEP4_4 = 0x40 655 | AGCTHRESH3_STEP4_5 = 0x50 656 | AGCTHRESH3_STEP4_6 = 0x60 657 | AGCTHRESH3_STEP4_7 = 0x70 658 | AGCTHRESH3_STEP4_8 = 0x80 659 | AGCTHRESH3_STEP4_9 = 0x90 # Default 660 | AGCTHRESH3_STEP4_10 = 0xA0 661 | AGCTHRESH3_STEP4_11 = 0xB0 662 | AGCTHRESH3_STEP4_12 = 0xC0 663 | AGCTHRESH3_STEP4_13 = 0xD0 664 | AGCTHRESH3_STEP4_14 = 0xE0 665 | AGCTHRESH3_STEP4_15 = 0xF0 666 | 667 | AGCTHRESH3_STEP5_0 = 0x00 668 | AGCTHRESH3_STEP5_1 = 0x01 669 | AGCTHRESH3_STEP5_2 = 0x02 670 | AGCTHRESH3_STEP5_3 = 0x03 671 | AGCTHRESH3_STEP5_4 = 0x04 672 | AGCTHRESH3_STEP5_5 = 0x05 673 | AGCTHRESH3_STEP5_6 = 0x06 674 | AGCTHRESH3_STEP5_7 = 0x07 675 | AGCTHRES33_STEP5_8 = 0x08 676 | AGCTHRESH3_STEP5_9 = 0x09 677 | AGCTHRESH3_STEP5_10 = 0x0A 678 | AGCTHRESH3_STEP5_11 = 0x0B # Default 679 | AGCTHRESH3_STEP5_12 = 0x0C 680 | AGCTHRESH3_STEP5_13 = 0x0D 681 | AGCTHRESH3_STEP5_14 = 0x0E 682 | AGCTHRESH3_STEP5_15 = 0x0F 683 | 684 | # Reg Lna 685 | LNA_ZIN_50 = 0x00 686 | LNA_ZIN_200 = 0x80 # Default 687 | 688 | LNA_LOWPOWER_OFF = 0x00 # Default 689 | LNA_LOWPOWER_ON = 0x40 690 | 691 | LNA_CURRENTGAIN = 0x08 692 | 693 | LNA_GAINSELECT_AUTO = 0x00 # Default 694 | LNA_GAINSELECT_MAX = 0x01 695 | LNA_GAINSELECT_MAXMINUS6 = 0x02 696 | LNA_GAINSELECT_MAXMINUS12 = 0x03 697 | LNA_GAINSELECT_MAXMINUS24 = 0x04 698 | LNA_GAINSELECT_MAXMINUS36 = 0x05 699 | LNA_GAINSELECT_MAXMINUS48 = 0x06 700 | 701 | # Reg Rx Bw 702 | RXBW_DCCFREQ_000 = 0x00 703 | RXBW_DCCFREQ_001 = 0x20 704 | RXBW_DCCFREQ_010 = 0x40 # Default 705 | RXBW_DCCFREQ_011 = 0x60 706 | RXBW_DCCFREQ_100 = 0x80 707 | RXBW_DCCFREQ_101 = 0xA0 708 | RXBW_DCCFREQ_110 = 0xC0 709 | RXBW_DCCFREQ_111 = 0xE0 710 | 711 | RXBW_MANT_16 = 0x00 712 | RXBW_MANT_20 = 0x08 713 | RXBW_MANT_24 = 0x10 # Default 714 | 715 | RXBW_EXP_0 = 0x00 716 | RXBW_EXP_1 = 0x01 717 | RXBW_EXP_2 = 0x02 718 | RXBW_EXP_3 = 0x03 719 | RXBW_EXP_4 = 0x04 720 | RXBW_EXP_5 = 0x05 # Default 721 | RXBW_EXP_6 = 0x06 722 | RXBW_EXP_7 = 0x07 723 | 724 | # Reg Afc Bw 725 | AFCBW_DCCFREQAFC_000 = 0x00 726 | AFCBW_DCCFREQAFC_001 = 0x20 727 | AFCBW_DCCFREQAFC_010 = 0x40 728 | AFCBW_DCCFREQAFC_011 = 0x60 729 | AFCBW_DCCFREQAFC_100 = 0x80 # Default 730 | AFCBW_DCCFREQAFC_101 = 0xA0 731 | AFCBW_DCCFREQAFC_110 = 0xC0 732 | AFCBW_DCCFREQAFC_111 = 0xE0 733 | 734 | AFCBW_MANTAFC_16 = 0x00 735 | AFCBW_MANTAFC_20 = 0x08 # Default 736 | AFCBW_MANTAFC_24 = 0x10 737 | 738 | AFCBW_EXPAFC_0 = 0x00 739 | AFCBW_EXPAFC_1 = 0x01 740 | AFCBW_EXPAFC_2 = 0x02 741 | AFCBW_EXPAFC_3 = 0x03 # Default 742 | AFCBW_EXPAFC_4 = 0x04 743 | AFCBW_EXPAFC_5 = 0x05 744 | AFCBW_EXPAFC_6 = 0x06 745 | AFCBW_EXPAFC_7 = 0x07 746 | 747 | AFCFEI_AFCAUTO_ON = 0x04 748 | AFCFEI_AFCAUTO_OFF = 0x00 749 | 750 | AFCFEI_FEI_DONE = 0x40 751 | AFCFEI_FEI_START = 0x20 752 | AFCFEI_AFC_DONE = 0x10 753 | AFCFEI_AFCAUTOCLEAR_ON = 0x08 754 | AFCFEI_AFCAUTOCLEAR_OFF = 0x00 755 | 756 | # Reg Ook Peak 757 | OOKPEAK_THRESHTYPE_FIXED = 0x00 758 | OOKPEAK_THRESHTYPE_PEAK = 0x40 # Default 759 | OOKPEAK_THRESHTYPE_AVERAGE = 0x80 760 | 761 | OOKPEAK_PEAKTHRESHSTEP_000 = 0x00 # Default 762 | OOKPEAK_PEAKTHRESHSTEP_001 = 0x08 763 | OOKPEAK_PEAKTHRESHSTEP_010 = 0x10 764 | OOKPEAK_PEAKTHRESHSTEP_011 = 0x18 765 | OOKPEAK_PEAKTHRESHSTEP_100 = 0x20 766 | OOKPEAK_PEAKTHRESHSTEP_101 = 0x28 767 | OOKPEAK_PEAKTHRESHSTEP_110 = 0x30 768 | OOKPEAK_PEAKTHRESHSTEP_111 = 0x38 769 | 770 | OOKPEAK_PEAKTHRESHDEC_000 = 0x00 # Default 771 | OOKPEAK_PEAKTHRESHDEC_001 = 0x01 772 | OOKPEAK_PEAKTHRESHDEC_010 = 0x02 773 | OOKPEAK_PEAKTHRESHDEC_011 = 0x03 774 | OOKPEAK_PEAKTHRESHDEC_100 = 0x04 775 | OOKPEAK_PEAKTHRESHDEC_101 = 0x05 776 | OOKPEAK_PEAKTHRESHDEC_110 = 0x06 777 | OOKPEAK_PEAKTHRESHDEC_111 = 0x07 778 | 779 | # Reg Ook Avg 780 | OOKAVG_AVERAGETHRESHFILT_00 = 0x00 781 | OOKAVG_AVERAGETHRESHFILT_01 = 0x40 782 | OOKAVG_AVERAGETHRESHFILT_10 = 0x80 # Default 783 | OOKAVG_AVERAGETHRESHFILT_11 = 0xC0 784 | 785 | # Reg Ook Fix 786 | OOKFIX_FIXEDTHRESH_VALUE = 0x06 # Default 787 | 788 | # Reg Afc Fei 789 | AFCFEI_FEI_DONE = 0x40 790 | AFCFEI_FEI_START = 0x20 791 | AFCFEI_AFC_DONE = 0x10 792 | AFCFEI_AFCAUTOCLEAR_ON = 0x08 793 | AFCFEI_AFCAUTOCLEAR_OFF = 0x00 # Default 794 | 795 | AFCFEI_AFCAUTO_ON = 0x04 796 | AFCFEI_AFCAUTO_OFF = 0x00 # Default 797 | 798 | AFCFEI_AFC_CLEAR = 0x02 799 | AFCFEI_AFC_START = 0x01 800 | 801 | # Reg Rssi Config 802 | RSSI_FASTRX_ON = 0x08 803 | RSSI_FASTRX_OFF = 0x00 # Default 804 | RSSI_DONE = 0x02 805 | RSSI_START = 0x01 806 | 807 | # Reg Dio Mapping 1 808 | DIOMAPPING1_DIO0_00 = 0x00 # Default 809 | DIOMAPPING1_DIO0_01 = 0x40 810 | DIOMAPPING1_DIO0_10 = 0x80 811 | DIOMAPPING1_DIO0_11 = 0xC0 812 | 813 | DIOMAPPING1_DIO1_00 = 0x00 # Default 814 | DIOMAPPING1_DIO1_01 = 0x10 815 | DIOMAPPING1_DIO1_10 = 0x20 816 | DIOMAPPING1_DIO1_11 = 0x30 817 | 818 | DIOMAPPING1_DIO2_00 = 0x00 # Default 819 | DIOMAPPING1_DIO2_01 = 0x04 820 | DIOMAPPING1_DIO2_10 = 0x08 821 | DIOMAPPING1_DIO2_11 = 0x0C 822 | 823 | DIOMAPPING1_DIO3_00 = 0x00 # Default 824 | DIOMAPPING1_DIO3_01 = 0x01 825 | DIOMAPPING1_DIO3_10 = 0x02 826 | DIOMAPPING1_DIO3_11 = 0x03 827 | 828 | # Reg Dio Mapping 2 829 | DIOMAPPING2_DIO4_00 = 0x00 # Default 830 | DIOMAPPING2_DIO4_01 = 0x40 831 | DIOMAPPING2_DIO4_10 = 0x80 832 | DIOMAPPING2_DIO4_11 = 0xC0 833 | 834 | DIOMAPPING2_DIO5_00 = 0x00 # Default 835 | DIOMAPPING2_DIO5_01 = 0x10 836 | DIOMAPPING2_DIO5_10 = 0x20 837 | DIOMAPPING2_DIO5_11 = 0x30 838 | 839 | DIOMAPPING2_CLKOUT_32 = 0x00 840 | DIOMAPPING2_CLKOUT_16 = 0x01 841 | DIOMAPPING2_CLKOUT_8 = 0x02 842 | DIOMAPPING2_CLKOUT_4 = 0x03 843 | DIOMAPPING2_CLKOUT_2 = 0x04 844 | DIOMAPPING2_CLKOUT_1 = 0x05 845 | DIOMAPPING2_CLKOUT_RC = 0x06 846 | DIOMAPPING2_CLKOUT_OFF = 0x07 # Default 847 | 848 | # Reg Irq Flags 1 849 | IRQFLAGS1_MODEREADY = 0x80 850 | IRQFLAGS1_RXREADY = 0x40 851 | IRQFLAGS1_TXREADY = 0x20 852 | IRQFLAGS1_PLLLOCK = 0x10 853 | IRQFLAGS1_RSSI = 0x08 854 | IRQFLAGS1_TIMEOUT = 0x04 855 | IRQFLAGS1_AUTOMODE = 0x02 856 | IRQFLAGS1_SYNCADDRESSMATCH = 0x01 857 | 858 | # Reg Irq Flags 2 859 | IRQFLAGS2_FIFOFULL = 0x80 860 | IRQFLAGS2_FIFONOTEMPTY = 0x40 861 | IRQFLAGS2_FIFOLEVEL = 0x20 862 | IRQFLAGS2_FIFOOVERRUN = 0x10 863 | IRQFLAGS2_PACKETSENT = 0x08 864 | IRQFLAGS2_PAYLOADREADY = 0x04 865 | IRQFLAGS2_CRCOK = 0x02 866 | IRQFLAGS2_LOWBAT = 0x01 867 | 868 | # Reg Rssi Thresh 869 | RSSITHRESH_VALUE = 0xE4 # Default 870 | 871 | # Reg Rx Timeout 1 872 | RXTIMEOUT1_RXSTART_VALUE = 0x00 # Default 873 | 874 | # Reg Rx Timeout 2 875 | RXTIMEOUT2_RSSITHRESH_VALUE = 0x00 # Default 876 | 877 | # Reg Preamble 878 | PREAMBLESIZE_MSB_VALUE = 0x00 # Default 879 | PREAMBLESIZE_LSB_VALUE = 0x03 # Default 880 | 881 | # Reg Sync Config 882 | SYNC_ON = 0x80 # Default 883 | SYNC_OFF = 0x00 884 | 885 | SYNC_FIFOFILL_AUTO = 0x00 # Default -- when sync interrupt occurs 886 | SYNC_FIFOFILL_MANUAL = 0x40 887 | 888 | SYNC_SIZE_1 = 0x00 889 | SYNC_SIZE_2 = 0x08 890 | SYNC_SIZE_3 = 0x10 891 | SYNC_SIZE_4 = 0x18 # Default 892 | SYNC_SIZE_5 = 0x20 893 | SYNC_SIZE_6 = 0x28 894 | SYNC_SIZE_7 = 0x30 895 | SYNC_SIZE_8 = 0x38 896 | 897 | SYNC_TOL_0 = 0x00 # Default 898 | SYNC_TOL_1 = 0x01 899 | SYNC_TOL_2 = 0x02 900 | SYNC_TOL_3 = 0x03 901 | SYNC_TOL_4 = 0x04 902 | SYNC_TOL_5 = 0x05 903 | SYNC_TOL_6 = 0x06 904 | SYNC_TOL_7 = 0x07 905 | 906 | # Reg Sync Value 1-8 907 | SYNC_BYTE1_VALUE = 0x00 # Default 908 | SYNC_BYTE2_VALUE = 0x00 # Default 909 | SYNC_BYTE3_VALUE = 0x00 # Default 910 | SYNC_BYTE4_VALUE = 0x00 # Default 911 | SYNC_BYTE5_VALUE = 0x00 # Default 912 | SYNC_BYTE6_VALUE = 0x00 # Default 913 | SYNC_BYTE7_VALUE = 0x00 # Default 914 | SYNC_BYTE8_VALUE = 0x00 # Default 915 | 916 | # Reg Packet Config 1 917 | PACKET1_FORMAT_FIXED = 0x00 # Default 918 | PACKET1_FORMAT_VARIABLE = 0x80 919 | 920 | PACKET1_DCFREE_OFF = 0x00 # Default 921 | PACKET1_DCFREE_MANCHESTER = 0x20 922 | PACKET1_DCFREE_WHITENING = 0x40 923 | 924 | PACKET1_CRC_ON = 0x10 # Default 925 | PACKET1_CRC_OFF = 0x00 926 | 927 | PACKET1_CRCAUTOCLEAR_ON = 0x00 # Default 928 | PACKET1_CRCAUTOCLEAR_OFF = 0x08 929 | 930 | PACKET1_ADRSFILTERING_OFF = 0x00 # Default 931 | PACKET1_ADRSFILTERING_NODE = 0x02 932 | PACKET1_ADRSFILTERING_NODEBROADCAST = 0x04 933 | 934 | # Reg Payload Length 935 | PAYLOADLENGTH_VALUE = 0x40 # Default 936 | 937 | # Reg Broadcast Adrs 938 | BROADCASTADDRESS_VALUE = 0x00 939 | 940 | # Reg Auto Modes 941 | AUTOMODES_ENTER_OFF = 0x00 # Default 942 | AUTOMODES_ENTER_FIFONOTEMPTY = 0x20 943 | AUTOMODES_ENTER_FIFOLEVEL = 0x40 944 | AUTOMODES_ENTER_CRCOK = 0x60 945 | AUTOMODES_ENTER_PAYLOADREADY = 0x80 946 | AUTOMODES_ENTER_SYNCADRSMATCH = 0xA0 947 | AUTOMODES_ENTER_PACKETSENT = 0xC0 948 | AUTOMODES_ENTER_FIFOEMPTY = 0xE0 949 | 950 | AUTOMODES_EXIT_OFF = 0x00 # Default 951 | AUTOMODES_EXIT_FIFOEMPTY = 0x04 952 | AUTOMODES_EXIT_FIFOLEVEL = 0x08 953 | AUTOMODES_EXIT_CRCOK = 0x0C 954 | AUTOMODES_EXIT_PAYLOADREADY = 0x10 955 | AUTOMODES_EXIT_SYNCADRSMATCH = 0x14 956 | AUTOMODES_EXIT_PACKETSENT = 0x18 957 | AUTOMODES_EXIT_RXTIMEOUT = 0x1C 958 | 959 | AUTOMODES_INTERMEDIATE_SLEEP = 0x00 # Default 960 | AUTOMODES_INTERMEDIATE_STANDBY = 0x01 961 | AUTOMODES_INTERMEDIATE_RECEIVER = 0x02 962 | AUTOMODES_INTERMEDIATE_TRANSMITTER = 0x03 963 | 964 | #Reg Fifo Thresh 965 | FIFOTHRESH_TXSTART_FIFOTHRESH = 0x00 966 | FIFOTHRESH_TXSTART_FIFONOTEMPTY = 0x80 # Default 967 | 968 | FIFOTHRESH_VALUE = 0x0F # Default 969 | 970 | # Reg Packet Config 2 971 | PACKET2_RXRESTARTDELAY_1BIT = 0x00 # Default 972 | PACKET2_RXRESTARTDELAY_2BITS = 0x10 973 | PACKET2_RXRESTARTDELAY_4BITS = 0x20 974 | PACKET2_RXRESTARTDELAY_8BITS = 0x30 975 | PACKET2_RXRESTARTDELAY_16BITS = 0x40 976 | PACKET2_RXRESTARTDELAY_32BITS = 0x50 977 | PACKET2_RXRESTARTDELAY_64BITS = 0x60 978 | PACKET2_RXRESTARTDELAY_128BITS = 0x70 979 | PACKET2_RXRESTARTDELAY_256BITS = 0x80 980 | PACKET2_RXRESTARTDELAY_512BITS = 0x90 981 | PACKET2_RXRESTARTDELAY_1024BITS = 0xA0 982 | PACKET2_RXRESTARTDELAY_2048BITS = 0xB0 983 | PACKET2_RXRESTARTDELAY_NONE = 0xC0 984 | PACKET2_RXRESTART = 0x04 985 | 986 | PACKET2_AUTORXRESTART_ON = 0x02 # Default 987 | PACKET2_AUTORXRESTART_OFF = 0x00 988 | 989 | PACKET2_AES_ON = 0x01 990 | PACKET2_AES_OFF = 0x00 # Default 991 | 992 | # Reg Aes Key 1-16 993 | AESKEY1_VALUE = 0x00 # Default 994 | AESKEY2_VALUE = 0x00 # Default 995 | AESKEY3_VALUE = 0x00 # Default 996 | AESKEY4_VALUE = 0x00 # Default 997 | AESKEY5_VALUE = 0x00 # Default 998 | AESKEY6_VALUE = 0x00 # Default 999 | AESKEY7_VALUE = 0x00 # Default 1000 | AESKEY8_VALUE = 0x00 # Default 1001 | AESKEY9_VALUE = 0x00 # Default 1002 | AESKEY10_VALUE = 0x00 # Default 1003 | AESKEY11_VALUE = 0x00 # Default 1004 | AESKEY12_VALUE = 0x00 # Default 1005 | AESKEY13_VALUE = 0x00 # Default 1006 | AESKEY14_VALUE = 0x00 # Default 1007 | AESKEY15_VALUE = 0x00 # Default 1008 | AESKEY16_VALUE = 0x00 # Default 1009 | 1010 | # Reg Temp 1 1011 | TEMP1_MEAS_START = 0x08 1012 | TEMP1_MEAS_RUNNING = 0x04 1013 | TEMP1_ADCLOWPOWER_ON = 0x01 # Default 1014 | TEMP1_ADCLOWPOWER_OFF = 0x00 1015 | 1016 | # Reg Test Dagc = 0x6F : demodulator config and IO mode config 1017 | DAGC_NORMAL = 0x00 # Reset value 1018 | DAGC_IMPROVED_LOWBETA1 = 0x20 # 1019 | DAGC_IMPROVED_LOWBETA0 = 0x30 # Recommended default 1020 | -------------------------------------------------------------------------------- /rfm69/register_value.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, absolute_import, print_function, unicode_literals 2 | 3 | 4 | class RegisterValue(object): 5 | """ Represents a single 8-bit register. 6 | Allows booleans and int members to be packed into and unpacked from the register value. 7 | Removes the need to keep ANDing and ORing everything. 8 | 9 | To use: add a static FORMAT class variable which is a list of 2-tuples, in the order 10 | they're packed into the register (MSB first). The first element of the tuple is the name 11 | of the class member, the second is the number of bits it takes up. 12 | """ 13 | def pack(self): 14 | result = 0 15 | pos = 8 16 | for field, length in self.FORMAT: 17 | pos -= length 18 | assert pos >= 0 19 | if isinstance(field, basestring): 20 | val = getattr(self, field) 21 | else: 22 | val = field 23 | result |= int(val) << pos 24 | return result 25 | 26 | @classmethod 27 | def unpack(cls, value): 28 | reg = cls() 29 | pos = 8 30 | for field, length in reg.FORMAT: 31 | pos -= length 32 | bits = (value >> pos) & (2**length - 1) 33 | if isinstance(field, basestring): 34 | setattr(reg, field, type(getattr(reg, field))(bits)) 35 | return reg 36 | 37 | def __repr__(self): 38 | info = [] 39 | for field, length in self.FORMAT: 40 | if isinstance(field, basestring): 41 | val = getattr(self, field) 42 | if type(val) is int: 43 | val = ("{0:#0%sb}" % (length + 2)).format(val) 44 | info.append("%s: %s" % (field, val)) 45 | return """""".format(self.__class__.__name__, 46 | self.pack(), ", ".join(info)) 47 | -------------------------------------------------------------------------------- /rfm69/rfm69.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, absolute_import, print_function, unicode_literals 2 | from time import sleep, time 3 | from threading import Event 4 | import logging 5 | 6 | import RPi.GPIO as GPIO 7 | import spidev 8 | 9 | from .configuration import IRQFlags1, IRQFlags2, OpMode, Temperature1, RSSIConfig 10 | from .constants import Register, RF 11 | 12 | 13 | class RadioError(Exception): 14 | pass 15 | 16 | 17 | def wait_for(condition, timeout=5, check_time=0.005): 18 | """ Wait for a radio condition to become true within a timeout. 19 | If this doesn't happen, raise a RadioError. 20 | 21 | Returns the amount of time """ 22 | start = time() 23 | iter_count = 0 24 | while not condition(): 25 | # We're spinning quite fast here, so only get the current time 26 | # every 20 iterations 27 | if iter_count % 20 == 0 and (time() - start) > timeout: 28 | raise RadioError("Condition didn't become true within %s seconds" % timeout) 29 | sleep(check_time) 30 | iter_count += 1 31 | return time() - start 32 | 33 | 34 | class RFM69(object): 35 | """ Interface for the RFM69 series of radio modules. """ 36 | def __init__(self, reset_pin=None, dio0_pin=None, spi_channel=None, config=None): 37 | """ Initialise the object and configure the receiver. 38 | 39 | reset_pin -- the GPIO pin number which is attached to the reset pin of the RFM69 40 | dio0_pin -- the GPIO pin number which is attached to the DIO0 pin of the RFM69 41 | spi_channel -- the SPI channel used by the RFM69 42 | config -- an instance of `RFM69Configuration` 43 | """ 44 | self.log = logging.getLogger(__name__) 45 | self.reset_pin = reset_pin 46 | self.dio0_pin = dio0_pin 47 | self.spi_channel = spi_channel 48 | self.config = config 49 | self.rx_restarts = 0 50 | self.init_gpio() 51 | self.init_spi() 52 | self.reset() 53 | self.write_config() 54 | self.log.info("Initialised successfully") 55 | 56 | def init_gpio(self): 57 | GPIO.setmode(GPIO.BCM) 58 | GPIO.setwarnings(False) 59 | GPIO.setup(self.dio0_pin, GPIO.IN) 60 | 61 | def init_spi(self): 62 | self.spi = spidev.SpiDev() 63 | self.spi.open(self.spi_channel, 0) 64 | self.spi.bits_per_word = 8 65 | self.spi.max_speed_hz = 50000 66 | 67 | def reset(self): 68 | """ Reset the module, then check it's working. """ 69 | self.log.debug("Initialising RFM...") 70 | GPIO.setup(self.reset_pin, GPIO.OUT) 71 | GPIO.output(self.reset_pin, 1) 72 | sleep(0.05) 73 | GPIO.setup(self.reset_pin, GPIO.IN) 74 | sleep(0.05) 75 | if (self.spi_read(Register.VERSION) != 0x24): 76 | raise RadioError("Failed to initialise RFM69") 77 | 78 | def payload_ready_interrupt(self, pin): 79 | self.log.debug("Payload Ready Interrupt") 80 | self.packet_ready_event.set() 81 | 82 | def write_config(self): 83 | """ Write the full configuration to the module. This is called on 84 | initialisation. 85 | """ 86 | self.log.debug("Writing configuration...") 87 | count = 0 88 | for register, value in self.config.get_registers().iteritems(): 89 | self.spi_write(register, value) 90 | count += 1 91 | 92 | self.log.debug("%s configuration registers written.", count) 93 | 94 | def wait_for_packet(self, timeout=None): 95 | """ Put the module in receive mode, and block until we receive a packet. 96 | Returns a tuple of (packet, rssi), or None if there was a timeout 97 | 98 | timeout -- the amount of time to wait for before returning if no 99 | packets were received. 100 | """ 101 | start = time() 102 | self.packet_ready_event = Event() 103 | self.rx_restarts = 0 104 | GPIO.add_event_detect(self.dio0_pin, GPIO.RISING, callback=self.payload_ready_interrupt) 105 | self.set_mode(OpMode.RX) 106 | packet_received = False 107 | while True: 108 | irqflags = self.read_register(IRQFlags1) 109 | if not irqflags.mode_ready: 110 | self.log.error("Module out of ready state: %s", irqflags) 111 | break 112 | if irqflags.rx_ready and irqflags.timeout: 113 | # Once the RFM's receiver has been started by a signal over the RSSI 114 | # threshold, it will continue running (possibly with stale AGC/AFC 115 | # parameters). Detect this and reset the receiver. 116 | irqflags2 = self.read_register(IRQFlags2) 117 | self.log.debug("Restarting Rx on timeout. RSSI: %s, sync: %s, fifo_not_empty: %s, crc: %s", 118 | irqflags.rssi, irqflags.sync_address_match, irqflags2.fifo_not_empty, 119 | irqflags2.crc_ok) 120 | self.spi_write(Register.PACKETCONFIG2, 121 | self.spi_read(Register.PACKETCONFIG2) | RF.PACKET2_RXRESTART) 122 | self.rx_restarts += 1 123 | if timeout is not None and time() - start > timeout: 124 | break 125 | if self.packet_ready_event.wait(1): 126 | packet_received = True 127 | break 128 | 129 | GPIO.remove_event_detect(self.dio0_pin) 130 | self.set_mode(OpMode.Standby, wait=False) 131 | 132 | if packet_received: 133 | rssi = self.get_rssi() 134 | data_length = self.spi_read(Register.FIFO) 135 | data = self.spi_burst_read(Register.FIFO, data_length) 136 | 137 | self.log.info("Received message: %s, RSSI: %s", data, rssi) 138 | return (bytearray(data), rssi) 139 | else: 140 | return None 141 | 142 | def send_packet(self, data, preamble=None): 143 | """ Transmit a packet. If you've configured the RFM to use variable-length 144 | packets, this function will add a length byte for you. 145 | 146 | The radio will be returned to the standby state. 147 | 148 | data -- this should be a bytearray. If it isn't, we'll try and convert it, 149 | but you might end up with encoding issues, especially if you use 150 | unicode strings. 151 | preamble -- how long, in seconds, to send the preamble bytes for. Longer 152 | preambles may result in more reliable decoding, at the expense of 153 | spectrum use. 154 | """ 155 | data = bytearray(data) 156 | 157 | if self.config.packet_config_1.variable_length: 158 | data = [len(data)] + list(data) 159 | 160 | self.log.debug("Initialising Tx...") 161 | start = time() 162 | self.set_mode(OpMode.TX, wait=False) 163 | wait_for(lambda: self.read_register(IRQFlags1).tx_ready) 164 | 165 | self.log.debug("In Tx mode (took %.3fs)", time() - start) 166 | 167 | if preamble: 168 | sleep(preamble) 169 | 170 | self.write_fifo(data) 171 | wait_for(lambda: self.read_register(IRQFlags2).packet_sent) 172 | 173 | self.set_mode(OpMode.Standby) 174 | self.log.debug("Packet (%r) sent in %.3fs", data, time() - start) 175 | 176 | def set_mode(self, mode, wait=True): 177 | """ Change the mode of the radio. Mode values can be found in the OpMode class. 178 | 179 | wait -- wait for the mode_ready interrupt flag to be set before returning. 180 | Not needed if you're going to be checking for another status flag. 181 | """ 182 | start = time() 183 | self.config.opmode.mode = mode 184 | self.write_register(self.config.opmode) 185 | while wait: 186 | irqflags = self.read_register(IRQFlags1) 187 | if irqflags.mode_ready: 188 | duration = time() - start 189 | self.log.debug("Mode changed to %s in %.3fs", mode, duration) 190 | return 191 | sleep(0.005) 192 | if time() - start > 5: 193 | self.log.warn("Mode not set after 5 seconds, resetting module") 194 | self.reset() 195 | self.write_register(self.config.opmode) 196 | start = time() 197 | 198 | def get_rssi(self): 199 | """ Get the current RSSI in dBm. """ 200 | return -(self.spi_read(Register.RSSIVALUE) / 2) 201 | 202 | def get_rssi_threshold(self): 203 | """ Get the current RSSI threshold in dBm. """ 204 | return -(self.spi_read(Register.RSSITHRESH) / 2) 205 | 206 | def set_rssi_threshold(self, value): 207 | """ Set the RSSI threshold in dBm """ 208 | if not -127 < value < 0: 209 | raise ValueError("RSSI threshold out of range") 210 | self.spi_write(Register.RSSITHRESH, -int(value * 2)) 211 | 212 | def calibrate_rssi_threshold(self, samples=10): 213 | """ Try and estimate the local noise floor and set a good RSSI threshold. The RFM 214 | appears to work best when it has a good RSSI threshold set. 215 | 216 | We do this by taking n samples of the measured RSSI, 200ms apart, and discarding 217 | the highest (noisiest, most powerful) 80% of these. 218 | """ 219 | old_thresh = self.spi_read(Register.RSSITHRESH) 220 | 221 | # Set the threshold to the lowest possible value and start receiving 222 | self.spi_write(Register.RSSITHRESH, 0xff) 223 | self.set_mode(OpMode.RX, wait=False) 224 | 225 | wait_for(lambda: self.read_register(RSSIConfig).rssi_done) 226 | 227 | values = [] 228 | for i in range(0, samples): 229 | values.append(self.spi_read(Register.RSSIVALUE)) 230 | sleep(0.2) 231 | 232 | values = sorted(values) 233 | new_thresh = values[int(samples * 0.8)] - 6 234 | 235 | self.set_mode(OpMode.Standby) 236 | 237 | if old_thresh != new_thresh: 238 | self.log.info("Changing RSSI threshold %sdB -> %sdB", -old_thresh / 2, -new_thresh / 2) 239 | self.spi_write(Register.RSSITHRESH, new_thresh) 240 | 241 | def read_temperature(self): 242 | """ Read the temperature from the RFM's built-in sensor. 243 | This will switch the module to standby mode. 244 | """ 245 | self.set_mode(OpMode.Standby) 246 | reg = Temperature1() 247 | reg.start = True 248 | self.write_register(reg) 249 | wait_for(lambda: not self.read_register(Temperature1).running) 250 | 251 | return 168 - self.spi_read(Register.TEMP2) 252 | 253 | def read_register(self, register_cls): 254 | resp = self.spi_read(register_cls.REGISTER) 255 | return register_cls.unpack(resp) 256 | 257 | def write_register(self, register): 258 | self.spi_write(register.REGISTER, register.pack()) 259 | 260 | def spi_read(self, register): 261 | data = [register & ~0x80, 0] 262 | resp = self.spi.xfer2(data) 263 | return resp[1] 264 | 265 | def spi_burst_read(self, register, length): 266 | data = [register & ~0x80] + ([0] * (length)) 267 | # We get the length again as the first character of the buffer 268 | return self.spi.xfer2(data)[1:] 269 | 270 | def spi_write(self, register, value): 271 | data = [register | 0x80, value] 272 | self.spi.xfer2(data) 273 | 274 | def write_fifo(self, data): 275 | self.spi.xfer2([Register.FIFO | 0x80] + data) 276 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, absolute_import, print_function, unicode_literals 2 | from setuptools import find_packages, setup 3 | 4 | setup(name="rfm69", 5 | version="0.3", 6 | description="Library for accessing the HopeRF RFM69-series radio modules via GPIO/SPI.", 7 | author="Russ Garrett", 8 | author_email='russ@garrett.co.uk', 9 | platforms=["any"], 10 | license="MIT", 11 | url="http://github.com/russss/rfm69-python", 12 | packages=find_packages(), 13 | install_requires=[ 14 | 'enum >= 0.4.6', 15 | 'RPi.GPIO >= 0.6.0', 16 | 'spidev >= 3.0' 17 | ] 18 | ) 19 | --------------------------------------------------------------------------------