64
64
_REG_FEI_MSB = const (0x1D )
65
65
_REG_MODEM_CONFIG = const (0x26 )
66
66
_REG_PAYLOAD_LENGTH = const (0x22 )
67
- _REG_FIFO_POINTER = const (0x0d )
67
+ _REG_FIFO_POINTER = const (0x0D )
68
68
_REG_FIFO_BASE_ADDR = const (0x80 )
69
69
_REG_OPERATING_MODE = const (0x01 )
70
70
_REG_VERSION = const (0x42 )
77
77
_REG_DIO_MAPPING_1 = const (0x40 )
78
78
79
79
# Freq synth step
80
- _FSTEP = (32000000.0 / 524288 )
80
+ _FSTEP = 32000000.0 / 524288
81
+
81
82
82
83
class TTN :
83
84
"""TTN Class
84
85
"""
85
- def __init__ (self , dev_address , net_key , app_key , country = 'US' ):
86
+
87
+ def __init__ (self , dev_address , net_key , app_key , country = "US" ):
86
88
"""Interface for TheThingsNetwork
87
89
:param bytearray dev_address: TTN Device Address.
88
90
:param bytearray net_key: TTN Network Key.
@@ -123,27 +125,36 @@ def network_key(self):
123
125
class TinyLoRa :
124
126
"""TinyLoRa Interface
125
127
"""
128
+
126
129
# SPI Write Buffer
127
130
_BUFFER = bytearray (2 )
128
131
129
132
# pylint: disable=too-many-arguments
130
- def __init__ (self , spi , cs , irq , ttn_config , channel = None ):
133
+ def __init__ (self , spi , cs , irq , rst , ttn_config , channel = None ):
131
134
"""Interface for a HopeRF RFM95/6/7/8(w) radio module. Sets module up for sending to
132
135
The Things Network.
133
136
134
137
:param ~busio.SPI spi: The SPI bus the device is on
135
138
:param ~digitalio.DigitalInOut cs: Chip select pin (RFM_NSS)
136
139
:param ~digitalio.DigitalInOut irq: RFM's DIO0 Pin (RFM_DIO0)
140
+ :param ~digitalio.DigitalInOut rst: RFM's RST Pin (RFM_RST)
137
141
:param TTN ttn_config: TTN Configuration.
138
142
:param int channel: Frequency Channel.
139
143
"""
140
144
self ._irq = irq
141
145
self ._irq .switch_to_input ()
142
146
self ._cs = cs
143
147
self ._cs .switch_to_output ()
148
+ self ._rst = rst
149
+ self ._rst .switch_to_output ()
144
150
# Set up SPI Device on Mode 0
145
- self ._device = adafruit_bus_device .spi_device .SPIDevice (spi , self ._cs , baudrate = 4000000 ,
146
- polarity = 0 , phase = 0 )
151
+ self ._device = adafruit_bus_device .spi_device .SPIDevice (
152
+ spi , self ._cs , baudrate = 4000000 , polarity = 0 , phase = 0
153
+ )
154
+ self ._rst .value = False
155
+ time .sleep (0.0001 ) # 100 us
156
+ self ._rst .value = True
157
+ time .sleep (0.005 ) # 5 ms
147
158
# Verify the version of the RFM module
148
159
self ._version = self ._read_u8 (_REG_VERSION )
149
160
if self ._version != 18 :
@@ -158,16 +169,16 @@ def __init__(self, spi, cs, irq, ttn_config, channel=None):
158
169
self ._modemcfg = None
159
170
self .set_datarate ("SF7BW125" )
160
171
# Set regional frequency plan
161
- if 'US' in ttn_config .country :
172
+ if "US" in ttn_config .country :
162
173
from adafruit_tinylora .ttn_usa import TTN_FREQS
163
174
self ._frequencies = TTN_FREQS
164
- elif ttn_config .country == 'AS' :
175
+ elif ttn_config .country == "AS" :
165
176
from adafruit_tinylora .ttn_as import TTN_FREQS
166
177
self ._frequencies = TTN_FREQS
167
- elif ttn_config .country == 'AU' :
178
+ elif ttn_config .country == "AU" :
168
179
from adafruit_tinylora .ttn_au import TTN_FREQS
169
180
self ._frequencies = TTN_FREQS
170
- elif ttn_config .country == 'EU' :
181
+ elif ttn_config .country == "EU" :
171
182
from adafruit_tinylora .ttn_eu import TTN_FREQS
172
183
self ._frequencies = TTN_FREQS
173
184
else :
@@ -181,16 +192,44 @@ def __init__(self, spi, cs, irq, ttn_config, channel=None):
181
192
# Init FrameCounter
182
193
self .frame_counter = 0
183
194
# Set up RFM9x for LoRa Mode
184
- for pair in ((_REG_OPERATING_MODE , _MODE_SLEEP ), (_REG_OPERATING_MODE , _MODE_LORA ),
185
- (_REG_PA_CONFIG , 0xFF ), (_REG_PREAMBLE_DETECT , 0x25 ),
186
- (_REG_PREAMBLE_MSB , 0x00 ), (_REG_PREAMBLE_LSB , 0x08 ),
187
- (_REG_MODEM_CONFIG , 0x0C ), (_REG_TIMER1_COEF , 0x34 ),
188
- (_REG_NODE_ADDR , 0x27 ), (_REG_IMAGE_CAL , 0x1D ),
189
- (_REG_RSSI_CONFIG , 0x80 ), (_REG_RSSI_COLLISION , 0x00 )):
195
+ for pair in (
196
+ (_REG_OPERATING_MODE , _MODE_SLEEP ),
197
+ (_REG_OPERATING_MODE , _MODE_LORA ),
198
+ (_REG_PA_CONFIG , 0xFF ),
199
+ (_REG_PREAMBLE_DETECT , 0x25 ),
200
+ (_REG_PREAMBLE_MSB , 0x00 ),
201
+ (_REG_PREAMBLE_LSB , 0x08 ),
202
+ (_REG_MODEM_CONFIG , 0x0C ),
203
+ (_REG_TIMER1_COEF , 0x34 ),
204
+ (_REG_NODE_ADDR , 0x27 ),
205
+ (_REG_IMAGE_CAL , 0x1D ),
206
+ (_REG_RSSI_CONFIG , 0x80 ),
207
+ (_REG_RSSI_COLLISION , 0x00 ),
208
+ ):
190
209
self ._write_u8 (pair [0 ], pair [1 ])
191
210
# Give the lora object ttn configuration
192
211
self ._ttn_config = ttn_config
193
212
213
+
214
+ def __enter__ (self ):
215
+ return self
216
+
217
+ def __exit__ (self , exception_type , exception_value , traceback ):
218
+ self .deinit ()
219
+
220
+ def deinit (self ):
221
+ """Deinitializes the TinyLoRa object properties and pins."""
222
+ self ._irq = None
223
+ self ._rst = None
224
+ self ._cs = None
225
+ self .frame_counter = 0
226
+ self ._rfm_msb = None
227
+ self ._rfm_mid = None
228
+ self ._rfm_lsb = None
229
+ self ._sf = None
230
+ self ._bw = None
231
+ self ._modemcfg = None
232
+
194
233
def send_data (self , data , data_length , frame_counter , timeout = 2 ):
195
234
"""Function to assemble and send data
196
235
:param data: data to send
@@ -205,8 +244,12 @@ def send_data(self, data, data_length, frame_counter, timeout=2):
205
244
enc_data [0 :data_length ] = data [0 :data_length ]
206
245
# encrypt data (enc_data is overwritten in this function)
207
246
self .frame_counter = frame_counter
208
- aes = AES (self ._ttn_config .device_address , self ._ttn_config .app_key ,
209
- self ._ttn_config .network_key , self .frame_counter )
247
+ aes = AES (
248
+ self ._ttn_config .device_address ,
249
+ self ._ttn_config .app_key ,
250
+ self ._ttn_config .network_key ,
251
+ self .frame_counter ,
252
+ )
210
253
enc_data = aes .encrypt (enc_data )
211
254
# append preamble to packet
212
255
lora_pkt [0 ] = const (_REG_DIO_MAPPING_1 )
@@ -221,14 +264,14 @@ def send_data(self, data, data_length, frame_counter, timeout=2):
221
264
# set length of LoRa packet
222
265
lora_pkt_len = 9
223
266
# load encrypted data into lora_pkt
224
- lora_pkt [lora_pkt_len : lora_pkt_len + data_length ] = enc_data [0 :data_length ]
267
+ lora_pkt [lora_pkt_len : lora_pkt_len + data_length ] = enc_data [0 :data_length ]
225
268
# recalculate packet length
226
269
lora_pkt_len += data_length
227
270
# Calculate MIC
228
271
mic = bytearray (4 )
229
272
mic = aes .calculate_mic (lora_pkt , lora_pkt_len , mic )
230
273
# load mic in package
231
- lora_pkt [lora_pkt_len : lora_pkt_len + 4 ] = mic [0 :4 ]
274
+ lora_pkt [lora_pkt_len : lora_pkt_len + 4 ] = mic [0 :4 ]
232
275
# recalculate packet length (add MIC length)
233
276
lora_pkt_len += 4
234
277
self .send_packet (lora_pkt , lora_pkt_len , timeout )
@@ -252,11 +295,16 @@ def send_packet(self, lora_packet, packet_length, timeout):
252
295
self ._rfm_mid = self ._frequencies [self ._tx_random ][1 ]
253
296
self ._rfm_msb = self ._frequencies [self ._tx_random ][0 ]
254
297
# Set up frequency registers
255
- for pair in ((_REG_FRF_MSB , self ._rfm_msb ), (_REG_FRF_MID , self ._rfm_mid ),
256
- (_REG_FRF_LSB , self ._rfm_lsb ), (_REG_FEI_LSB , self ._sf ),
257
- (_REG_FEI_MSB , self ._bw ), (_REG_MODEM_CONFIG , self ._modemcfg ),
258
- (_REG_PAYLOAD_LENGTH , packet_length ),
259
- (_REG_FIFO_POINTER , _REG_FIFO_BASE_ADDR )):
298
+ for pair in (
299
+ (_REG_FRF_MSB , self ._rfm_msb ),
300
+ (_REG_FRF_MID , self ._rfm_mid ),
301
+ (_REG_FRF_LSB , self ._rfm_lsb ),
302
+ (_REG_FEI_LSB , self ._sf ),
303
+ (_REG_FEI_MSB , self ._bw ),
304
+ (_REG_MODEM_CONFIG , self ._modemcfg ),
305
+ (_REG_PAYLOAD_LENGTH , packet_length ),
306
+ (_REG_FIFO_POINTER , _REG_FIFO_BASE_ADDR ),
307
+ ):
260
308
self ._write_u8 (pair [0 ], pair [1 ])
261
309
# fill the FIFO buffer with the LoRa payload
262
310
for k in range (packet_length ):
@@ -267,21 +315,26 @@ def send_packet(self, lora_packet, packet_length, timeout):
267
315
start = time .monotonic ()
268
316
timed_out = False
269
317
while not timed_out and not self ._irq .value :
270
- if (time .monotonic () - start ) >= timeout :
318
+ if (time .monotonic () - start ) >= timeout :
271
319
timed_out = True
272
320
# switch RFM to sleep operating mode
273
321
self ._write_u8 (_REG_OPERATING_MODE , _MODE_SLEEP )
274
322
if timed_out :
275
- raise RuntimeError (' Timeout during packet send' )
323
+ raise RuntimeError (" Timeout during packet send" )
276
324
277
325
def set_datarate (self , datarate ):
278
326
"""Sets the RFM Datarate
279
327
:param datarate: Bandwidth and Frequency Plan
280
328
"""
281
- data_rates = {'SF7BW125' :(0x74 , 0x72 , 0x04 ), 'SF7BW250' :(0x74 , 0x82 , 0x04 ),
282
- 'SF8BW125' :(0x84 , 0x72 , 0x04 ), 'SF9BW125' :(0x94 , 0x72 , 0x04 ),
283
- 'SF10BW125' :(0xA4 , 0x72 , 0x04 ), 'SF11BW125' :(0xB4 , 0x72 , 0x0C ),
284
- 'SF12BW125' :(0xC4 , 0x72 , 0x0C )}
329
+ data_rates = {
330
+ "SF7BW125" : (0x74 , 0x72 , 0x04 ),
331
+ "SF7BW250" : (0x74 , 0x82 , 0x04 ),
332
+ "SF8BW125" : (0x84 , 0x72 , 0x04 ),
333
+ "SF9BW125" : (0x94 , 0x72 , 0x04 ),
334
+ "SF10BW125" : (0xA4 , 0x72 , 0x04 ),
335
+ "SF11BW125" : (0xB4 , 0x72 , 0x0C ),
336
+ "SF12BW125" : (0xC4 , 0x72 , 0x0C ),
337
+ }
285
338
try :
286
339
self ._sf , self ._bw , self ._modemcfg = data_rates [datarate ]
287
340
except KeyError :
@@ -323,7 +376,7 @@ def _write_u8(self, address, val):
323
376
:param val: Data to write.
324
377
"""
325
378
with self ._device as device :
326
- self ._BUFFER [0 ] = ( address | 0x80 ) # MSB 1 to Write
379
+ self ._BUFFER [0 ] = address | 0x80 # MSB 1 to Write
327
380
self ._BUFFER [1 ] = val
328
381
# pylint: disable=no-member
329
382
device .write (self ._BUFFER , end = 2 )
0 commit comments