47
47
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_RFM69.git"
48
48
49
49
50
+ # pylint: disable=bad-whitespace
50
51
# Internal constants:
51
52
_REG_FIFO = const (0x00 )
52
53
_REG_OP_MODE = const (0x01 )
99
100
FS_MODE = 0b010
100
101
TX_MODE = 0b011
101
102
RX_MODE = 0b100
103
+ # pylint: enable=bad-whitespace
102
104
105
+ # Disable the silly too many instance members warning. Pylint has no knowledge
106
+ # of the context and is merely guessing at the proper amount of members. This
107
+ # is a complex chip which requires exposing many attributes and state. Disable
108
+ # the warning to work around the error.
109
+ # pylint: disable=too-many-instance-attributes
103
110
104
111
class RFM69 :
105
-
112
+ """Interface to a RFM69 series packet radio. Allows simple sending and
113
+ receiving of wireless data at supported frequencies of the radio
114
+ (433/915mhz). These chips are connected using a SPI interface and require
115
+ the following parameters to initialize:
116
+ - spi: The SPI bus connected to the chip. Ensure SCK, MOSI, and MISO are
117
+ connected.
118
+ - cs: A DigitalInOut object connected to the chip's CS/chip select line.
119
+ - reset: A DigitalInOut object connected to the chip's RST/reset line.
120
+ - frequency: The center frequency to configure for radio transmission and
121
+ reception. Must be a frequency supported by your hardware
122
+ (i.e. either 433 or 915mhz).
123
+
124
+ Note the D0/interrupt line is currently unused by this module and can
125
+ remain unconnected.
126
+
127
+ There are optional keyword parameters which may be specified during
128
+ initialization:
129
+ - sync_word: A byte string up to 8 bytes long which represents the
130
+ syncronization word used by received and transmitted packets.
131
+ Read the datasheet for a full understanding of this value!
132
+ However by default the library will set a value that matches
133
+ the RadioHead Arduino library.
134
+ - preamble_length: The number of bytes to pre-pend to a data packet as a
135
+ preamble. This is by default 4 to match the RadioHead
136
+ library.
137
+ - encryption_key: A 16 byte long string that represents the AES encryption
138
+ key to use when encrypting and decrypting packets. Both
139
+ the transmitter and receiver MUST have the same key value!
140
+ By default no encryption key is set or used.
141
+ - high_power: A boolean to indicate if the chip is a high power variant that
142
+ supports boosted transmission power. The default is True as
143
+ it supports the common RFM69HCW modules sold by Adafruit.
144
+
145
+ Remember this library makes a best effort at receiving packets with pure
146
+ Python code. Trying to receive packets too quickly will result in lost
147
+ data so limit yourself to simple scenarios of sending and receiving single
148
+ packets at a time.
149
+
150
+ Also note this library tries to be compatible with raw RadioHead Arduino
151
+ library communication. Advanced RadioHead features like address/node
152
+ specific packets or guaranteed delivery are not supported. Only simple
153
+ broadcast of packets to all listening radios is supported. Features like
154
+ addressing and guaranteed delivery need to be implemented at an application
155
+ level.
156
+ """
157
+
158
+ # Global buffer to hold data sent and received with the chip. This must be
159
+ # at least as large as the FIFO on the chip (66 bytes)! Keep this on the
160
+ # class level to ensure only one copy ever exists (with the trade-off that
161
+ # this is NOT re-entrant or thread safe code by design).
106
162
_BUFFER = bytearray (66 )
107
163
108
164
class _RegisterBits :
165
+ # Class to simplify access to the many configuration bits avaialable
166
+ # on the chip's registers. This is a subclass here instead of using
167
+ # a higher level module to increase the efficiency of memory usage
168
+ # (all of the instances of this bit class will share the same buffer
169
+ # used by the parent RFM69 class instance vs. each having their own
170
+ # buffer and taking too much memory).
171
+
172
+ # Quirk of pylint that it requires public methods for a class. This
173
+ # is a decorator class in Python and by design it has no public methods.
174
+ # Instead it uses dunder accessors like get and set below. For some
175
+ # reason pylint can't figure this out so disable the check.
176
+ # pylint: disable=too-few-public-methods
177
+
178
+ # Again pylint fails to see the true intent of this code and warns
179
+ # against private access by calling the write and read functions below.
180
+ # This is by design as this is an internally used class. Disable the
181
+ # check from pylint.
182
+ # pylint: disable=protected-access
109
183
110
184
def __init__ (self , address , * , offset = 0 , bits = 1 ):
111
185
assert 0 <= offset <= 7
@@ -129,6 +203,7 @@ def __set__(self, obj, val):
129
203
reg_value |= (val & 0xFF ) << self ._offset
130
204
obj ._write_u8 (self ._address , reg_value )
131
205
206
+ # Control bits from the registers of the chip:
132
207
data_mode = _RegisterBits (_REG_DATA_MOD , offset = 5 , bits = 2 )
133
208
134
209
modulation_type = _RegisterBits (_REG_DATA_MOD , offset = 3 , bits = 2 )
@@ -187,7 +262,7 @@ def __set__(self, obj, val):
187
262
188
263
payload_ready = _RegisterBits (_REG_IRQ_FLAGS2 , offset = 2 )
189
264
190
- def __init__ (self , spi , cs , reset , d0 , frequency , * , sync_word = '\x2d \xd4 ' ,
265
+ def __init__ (self , spi , cs , reset , frequency , * , sync_word = '\x2d \xd4 ' ,
191
266
preamble_length = 4 , encryption_key = None , high_power = True ):
192
267
self ._tx_power = 13
193
268
self .high_power = high_power
@@ -197,14 +272,6 @@ def __init__(self, spi, cs, reset, d0, frequency, *, sync_word='\x2d\xd4',
197
272
# Setup reset as a digital output that's low.
198
273
self ._reset = reset
199
274
self ._reset .switch_to_output (value = False )
200
- # Configure d0 as input to monitor interrupt line from chip.
201
- # This is not ideal as it requires polling from very slow Python code,
202
- # however it's a best effort for now until proper interrupt support
203
- # is available. The implication is that you can't receive data quickly
204
- # as you'll miss interrupts and the FIFO will overflow. Limit use
205
- # to low bandwidth single packet messages.
206
- self ._d0 = d0
207
- self ._d0 .switch_to_input ()
208
275
# Reset the chip.
209
276
self .reset ()
210
277
# Check the version of the chip.
@@ -266,6 +333,7 @@ def _read_into(self, address, buf, length=None):
266
333
device .readinto (buf , end = length )
267
334
268
335
def _read_u8 (self , address ):
336
+ # Read a single byte from the provided address and return it.
269
337
self ._read_into (address , self ._BUFFER , length = 1 )
270
338
return self ._BUFFER [0 ]
271
339
@@ -358,7 +426,8 @@ def temperature(self):
358
426
def operation_mode (self ):
359
427
"""Get and set the operation mode value. Unless you're manually
360
428
controlling the chip you shouldn't change the operation_mode with this
361
- property as other side-effects are required for changing logcial modes--use the idle(), sleep(), transmit(), listen() functions instead
429
+ property as other side-effects are required for changing logcial
430
+ modes--use the idle(), sleep(), transmit(), listen() functions instead
362
431
to signal intent for explicit logical modes.
363
432
"""
364
433
op_mode = self ._read_u8 (_REG_OP_MODE )
@@ -592,7 +661,13 @@ def send(self, data):
592
661
Note this appends a 4 byte header to be compatible with the RadioHead
593
662
library.
594
663
"""
664
+ # Disable pylint warning to not use length as a check for zero.
665
+ # This is a puzzling warning as the below code is clearly the most
666
+ # efficient and proper way to ensure a precondition that the provided
667
+ # buffer be within an expected range of bounds. Disable this check.
668
+ # pylint: disable=len-as-condition
595
669
assert 0 < len (data ) <= 60
670
+ # pylint: enable=len-as-condition
596
671
self .idle () # Stop receiving to clear FIFO and keep it clear.
597
672
# Fill the FIFO with a packet to send.
598
673
with self ._device as device :
@@ -602,10 +677,10 @@ def send(self, data):
602
677
# Add 4 bytes of headers to match RadioHead library.
603
678
# Just use the defaults for global broadcast to all receivers
604
679
# for now.
605
- self ._BUFFER [2 ] = _RH_BROADCAST_ADDRESS # txHeaderTo
606
- self ._BUFFER [3 ] = _RH_BROADCAST_ADDRESS # txHeaderFrom
607
- self ._BUFFER [4 ] = 0 # txHeaderId
608
- self ._BUFFER [5 ] = 0 # txHeaderFlags
680
+ self ._BUFFER [2 ] = _RH_BROADCAST_ADDRESS # txHeaderTo
681
+ self ._BUFFER [3 ] = _RH_BROADCAST_ADDRESS # txHeaderFrom
682
+ self ._BUFFER [4 ] = 0 # txHeaderId
683
+ self ._BUFFER [5 ] = 0 # txHeaderFlags
609
684
device .write (self ._BUFFER , end = 6 )
610
685
# Now send the payload.
611
686
device .write (data )
0 commit comments