Skip to content

Add reset parameter #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
117 changes: 85 additions & 32 deletions adafruit_tinylora/adafruit_tinylora.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
_REG_FEI_MSB = const(0x1D)
_REG_MODEM_CONFIG = const(0x26)
_REG_PAYLOAD_LENGTH = const(0x22)
_REG_FIFO_POINTER = const(0x0d)
_REG_FIFO_POINTER = const(0x0D)
_REG_FIFO_BASE_ADDR = const(0x80)
_REG_OPERATING_MODE = const(0x01)
_REG_VERSION = const(0x42)
Expand All @@ -77,12 +77,14 @@
_REG_DIO_MAPPING_1 = const(0x40)

# Freq synth step
_FSTEP = (32000000.0 / 524288)
_FSTEP = 32000000.0 / 524288


class TTN:
"""TTN Class
"""
def __init__(self, dev_address, net_key, app_key, country='US'):

def __init__(self, dev_address, net_key, app_key, country="US"):
"""Interface for TheThingsNetwork
:param bytearray dev_address: TTN Device Address.
:param bytearray net_key: TTN Network Key.
Expand Down Expand Up @@ -123,27 +125,36 @@ def network_key(self):
class TinyLoRa:
"""TinyLoRa Interface
"""

# SPI Write Buffer
_BUFFER = bytearray(2)

# pylint: disable=too-many-arguments
def __init__(self, spi, cs, irq, ttn_config, channel=None):
def __init__(self, spi, cs, irq, rst, ttn_config, channel=None):
"""Interface for a HopeRF RFM95/6/7/8(w) radio module. Sets module up for sending to
The Things Network.

:param ~busio.SPI spi: The SPI bus the device is on
:param ~digitalio.DigitalInOut cs: Chip select pin (RFM_NSS)
:param ~digitalio.DigitalInOut irq: RFM's DIO0 Pin (RFM_DIO0)
:param ~digitalio.DigitalInOut rst: RFM's RST Pin (RFM_RST)
:param TTN ttn_config: TTN Configuration.
:param int channel: Frequency Channel.
"""
self._irq = irq
self._irq.switch_to_input()
self._cs = cs
self._cs.switch_to_output()
self._rst = rst
self._rst.switch_to_output()
# Set up SPI Device on Mode 0
self._device = adafruit_bus_device.spi_device.SPIDevice(spi, self._cs, baudrate=4000000,
polarity=0, phase=0)
self._device = adafruit_bus_device.spi_device.SPIDevice(
spi, self._cs, baudrate=4000000, polarity=0, phase=0
)
self._rst.value = False
time.sleep(0.0001) # 100 us
self._rst.value = True
time.sleep(0.005) # 5 ms
# Verify the version of the RFM module
self._version = self._read_u8(_REG_VERSION)
if self._version != 18:
Expand All @@ -158,16 +169,16 @@ def __init__(self, spi, cs, irq, ttn_config, channel=None):
self._modemcfg = None
self.set_datarate("SF7BW125")
# Set regional frequency plan
if 'US' in ttn_config.country:
if "US" in ttn_config.country:
from adafruit_tinylora.ttn_usa import TTN_FREQS
self._frequencies = TTN_FREQS
elif ttn_config.country == 'AS':
elif ttn_config.country == "AS":
from adafruit_tinylora.ttn_as import TTN_FREQS
self._frequencies = TTN_FREQS
elif ttn_config.country == 'AU':
elif ttn_config.country == "AU":
from adafruit_tinylora.ttn_au import TTN_FREQS
self._frequencies = TTN_FREQS
elif ttn_config.country == 'EU':
elif ttn_config.country == "EU":
from adafruit_tinylora.ttn_eu import TTN_FREQS
self._frequencies = TTN_FREQS
else:
Expand All @@ -181,16 +192,44 @@ def __init__(self, spi, cs, irq, ttn_config, channel=None):
# Init FrameCounter
self.frame_counter = 0
# Set up RFM9x for LoRa Mode
for pair in ((_REG_OPERATING_MODE, _MODE_SLEEP), (_REG_OPERATING_MODE, _MODE_LORA),
(_REG_PA_CONFIG, 0xFF), (_REG_PREAMBLE_DETECT, 0x25),
(_REG_PREAMBLE_MSB, 0x00), (_REG_PREAMBLE_LSB, 0x08),
(_REG_MODEM_CONFIG, 0x0C), (_REG_TIMER1_COEF, 0x34),
(_REG_NODE_ADDR, 0x27), (_REG_IMAGE_CAL, 0x1D),
(_REG_RSSI_CONFIG, 0x80), (_REG_RSSI_COLLISION, 0x00)):
for pair in (
(_REG_OPERATING_MODE, _MODE_SLEEP),
(_REG_OPERATING_MODE, _MODE_LORA),
(_REG_PA_CONFIG, 0xFF),
(_REG_PREAMBLE_DETECT, 0x25),
(_REG_PREAMBLE_MSB, 0x00),
(_REG_PREAMBLE_LSB, 0x08),
(_REG_MODEM_CONFIG, 0x0C),
(_REG_TIMER1_COEF, 0x34),
(_REG_NODE_ADDR, 0x27),
(_REG_IMAGE_CAL, 0x1D),
(_REG_RSSI_CONFIG, 0x80),
(_REG_RSSI_COLLISION, 0x00),
):
self._write_u8(pair[0], pair[1])
# Give the lora object ttn configuration
self._ttn_config = ttn_config


def __enter__(self):
return self

def __exit__(self, exception_type, exception_value, traceback):
self.deinit()

def deinit(self):
"""Deinitializes the TinyLoRa object properties and pins."""
self._irq = None
self._rst = None
self._cs = None
self.frame_counter = 0
self._rfm_msb = None
self._rfm_mid = None
self._rfm_lsb = None
self._sf = None
self._bw = None
self._modemcfg = None

def send_data(self, data, data_length, frame_counter, timeout=2):
"""Function to assemble and send data
:param data: data to send
Expand All @@ -205,8 +244,12 @@ def send_data(self, data, data_length, frame_counter, timeout=2):
enc_data[0:data_length] = data[0:data_length]
# encrypt data (enc_data is overwritten in this function)
self.frame_counter = frame_counter
aes = AES(self._ttn_config.device_address, self._ttn_config.app_key,
self._ttn_config.network_key, self.frame_counter)
aes = AES(
self._ttn_config.device_address,
self._ttn_config.app_key,
self._ttn_config.network_key,
self.frame_counter,
)
enc_data = aes.encrypt(enc_data)
# append preamble to packet
lora_pkt[0] = const(_REG_DIO_MAPPING_1)
Expand All @@ -221,14 +264,14 @@ def send_data(self, data, data_length, frame_counter, timeout=2):
# set length of LoRa packet
lora_pkt_len = 9
# load encrypted data into lora_pkt
lora_pkt[lora_pkt_len:lora_pkt_len+data_length] = enc_data[0:data_length]
lora_pkt[lora_pkt_len : lora_pkt_len + data_length] = enc_data[0:data_length]
# recalculate packet length
lora_pkt_len += data_length
# Calculate MIC
mic = bytearray(4)
mic = aes.calculate_mic(lora_pkt, lora_pkt_len, mic)
# load mic in package
lora_pkt[lora_pkt_len:lora_pkt_len+4] = mic[0:4]
lora_pkt[lora_pkt_len : lora_pkt_len + 4] = mic[0:4]
# recalculate packet length (add MIC length)
lora_pkt_len += 4
self.send_packet(lora_pkt, lora_pkt_len, timeout)
Expand All @@ -252,11 +295,16 @@ def send_packet(self, lora_packet, packet_length, timeout):
self._rfm_mid = self._frequencies[self._tx_random][1]
self._rfm_msb = self._frequencies[self._tx_random][0]
# Set up frequency registers
for pair in ((_REG_FRF_MSB, self._rfm_msb), (_REG_FRF_MID, self._rfm_mid),
(_REG_FRF_LSB, self._rfm_lsb), (_REG_FEI_LSB, self._sf),
(_REG_FEI_MSB, self._bw), (_REG_MODEM_CONFIG, self._modemcfg),
(_REG_PAYLOAD_LENGTH, packet_length),
(_REG_FIFO_POINTER, _REG_FIFO_BASE_ADDR)):
for pair in (
(_REG_FRF_MSB, self._rfm_msb),
(_REG_FRF_MID, self._rfm_mid),
(_REG_FRF_LSB, self._rfm_lsb),
(_REG_FEI_LSB, self._sf),
(_REG_FEI_MSB, self._bw),
(_REG_MODEM_CONFIG, self._modemcfg),
(_REG_PAYLOAD_LENGTH, packet_length),
(_REG_FIFO_POINTER, _REG_FIFO_BASE_ADDR),
):
self._write_u8(pair[0], pair[1])
# fill the FIFO buffer with the LoRa payload
for k in range(packet_length):
Expand All @@ -267,21 +315,26 @@ def send_packet(self, lora_packet, packet_length, timeout):
start = time.monotonic()
timed_out = False
while not timed_out and not self._irq.value:
if(time.monotonic() - start) >= timeout:
if (time.monotonic() - start) >= timeout:
timed_out = True
# switch RFM to sleep operating mode
self._write_u8(_REG_OPERATING_MODE, _MODE_SLEEP)
if timed_out:
raise RuntimeError('Timeout during packet send')
raise RuntimeError("Timeout during packet send")

def set_datarate(self, datarate):
"""Sets the RFM Datarate
:param datarate: Bandwidth and Frequency Plan
"""
data_rates = {'SF7BW125':(0x74, 0x72, 0x04), 'SF7BW250':(0x74, 0x82, 0x04),
'SF8BW125':(0x84, 0x72, 0x04), 'SF9BW125':(0x94, 0x72, 0x04),
'SF10BW125':(0xA4, 0x72, 0x04), 'SF11BW125':(0xB4, 0x72, 0x0C),
'SF12BW125':(0xC4, 0x72, 0x0C)}
data_rates = {
"SF7BW125": (0x74, 0x72, 0x04),
"SF7BW250": (0x74, 0x82, 0x04),
"SF8BW125": (0x84, 0x72, 0x04),
"SF9BW125": (0x94, 0x72, 0x04),
"SF10BW125": (0xA4, 0x72, 0x04),
"SF11BW125": (0xB4, 0x72, 0x0C),
"SF12BW125": (0xC4, 0x72, 0x0C),
}
try:
self._sf, self._bw, self._modemcfg = data_rates[datarate]
except KeyError:
Expand Down Expand Up @@ -323,7 +376,7 @@ def _write_u8(self, address, val):
:param val: Data to write.
"""
with self._device as device:
self._BUFFER[0] = (address | 0x80) # MSB 1 to Write
self._BUFFER[0] = address | 0x80 # MSB 1 to Write
self._BUFFER[1] = val
# pylint: disable=no-member
device.write(self._BUFFER, end=2)
4 changes: 3 additions & 1 deletion examples/tinylora_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
# RFM9x Breakout Pinouts
cs = digitalio.DigitalInOut(board.D5)
irq = digitalio.DigitalInOut(board.D6)
rst = digitalio.DigitalInOut(board.D4)

# Feather M0 RFM9x Pinouts
# cs = digitalio.DigitalInOut(board.RFM9X_CS)
# irq = digitalio.DigitalInOut(board.RFM9X_D0)
# rst = digitalio.DigitalInOut(board.RFM9x_RST)

# TTN Device Address, 4 Bytes, MSB
devaddr = bytearray([0x00, 0x00, 0x00, 0x00])
Expand All @@ -31,7 +33,7 @@

ttn_config = TTN(devaddr, nwkey, app, country='US')

lora = TinyLoRa(spi, cs, irq, ttn_config)
lora = TinyLoRa(spi, cs, irq, rst, ttn_config)

while True:
data = bytearray(b"\x43\x57\x54\x46")
Expand Down
4 changes: 3 additions & 1 deletion examples/tinylora_simpletest_si7021.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,12 @@
# RFM9x Breakout Pinouts
cs = digitalio.DigitalInOut(board.D5)
irq = digitalio.DigitalInOut(board.D6)
rst = digitalio.DigitalInOut(board.D4)

# Feather M0 RFM9x Pinouts
# cs = digitalio.DigitalInOut(board.RFM9X_CS)
# irq = digitalio.DigitalInOut(board.RFM9X_D0)
# rst = digitalio.DigitalInOut(board.RFM9x_RST)

# TTN Device Address, 4 Bytes, MSB
devaddr = bytearray([0x00, 0x00, 0x00, 0x00])
Expand All @@ -39,7 +41,7 @@

ttn_config = TTN(devaddr, nwkey, app, country='US')

lora = TinyLoRa(spi, cs, irq, ttn_config)
lora = TinyLoRa(spi, cs, irq, rst, ttn_config)

# Data Packet to send to TTN
data = bytearray(4)
Expand Down
4 changes: 3 additions & 1 deletion examples/tinylora_simpletest_single_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
# RFM9x Breakout Pinouts
cs = digitalio.DigitalInOut(board.D5)
irq = digitalio.DigitalInOut(board.D6)
rst = digitalio.DigitalInOut(board.D4)

# Feather M0 RFM9x Pinouts
# cs = digitalio.DigitalInOut(board.RFM9X_CS)
# irq = digitalio.DigitalInOut(board.RFM9X_D0)
# rst = digitalio.DigitalInOut(board.RFM9x_RST)

# TTN Device Address, 4 Bytes, MSB
devaddr = bytearray([0x00, 0x00, 0x00, 0x00])
Expand All @@ -32,7 +34,7 @@
ttn_config = TTN(devaddr, nwkey, app, country='US')

# Broadcasting on channel 0 in US Region - 903.9 MHz
lora = TinyLoRa(spi, cs, irq, ttn_config, channel=0)
lora = TinyLoRa(spi, cs, irq, rst, ttn_config, channel=0)

while True:
data = bytearray(b"\x43\x57\x54\x46")
Expand Down