-
Notifications
You must be signed in to change notification settings - Fork 49
Fix power and frequency initiailzations #4
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
Changes from 8 commits
7bacbb0
c664b33
01ede57
a5e3432
7bf0b12
732a40a
81f1b7a
fa35c30
36f54f1
8f2d877
66492ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,7 @@ | |
adapted from the Radiohead library RF95 code from: | ||
http: www.airspayce.com/mikem/arduino/RadioHead/ | ||
|
||
* Author(s): Tony DiCola | ||
* Author(s): Tony DiCola, Jerry Needell | ||
""" | ||
import time | ||
import digitalio | ||
|
@@ -120,7 +120,7 @@ | |
_RH_RF95_PA_RAMP_2MS = const(0x01) | ||
_RH_RF95_PA_RAMP_1MS = const(0x02) | ||
_RH_RF95_PA_RAMP_500US = const(0x03) | ||
_RH_RF95_PA_RAMP_250US = const(0x0) | ||
_RH_RF95_PA_RAMP_250US = const(0x04) | ||
_RH_RF95_PA_RAMP_125US = const(0x05) | ||
_RH_RF95_PA_RAMP_100US = const(0x06) | ||
_RH_RF95_PA_RAMP_62US = const(0x07) | ||
|
@@ -212,7 +212,7 @@ | |
_RH_RF95_FXOSC = 32000000.0 | ||
|
||
# The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19 | ||
_RH_RF95_FSTEP = (_RH_RF95_FXOSC // 524288) | ||
_RH_RF95_FSTEP = (_RH_RF95_FXOSC / 524288) | ||
|
||
# RadioHead specific compatibility constants. | ||
_RH_BROADCAST_ADDRESS = const(0xFF) | ||
|
@@ -266,7 +266,7 @@ class RFM9x: | |
# at least as large as the FIFO on the chip (256 bytes)! Keep this on the | ||
# class level to ensure only one copy ever exists (with the trade-off that | ||
# this is NOT re-entrant or thread safe code by design). | ||
_BUFFER = bytearray(256) | ||
_BUFFER = bytearray(10) | ||
|
||
class _RegisterBits: | ||
# Class to simplify access to the many configuration bits avaialable | ||
|
@@ -334,9 +334,10 @@ def __set__(self, obj, val): | |
rx_done = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=6, bits=1) | ||
|
||
def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, | ||
high_power=True, baudrate=10000000): | ||
high_power=True, baudrate=5000000): | ||
self.high_power = high_power | ||
# Device support SPI mode 0 (polarity & phase = 0) up to a max of 10mhz. | ||
# Set Default Baudrate to 5MHz to avoid problems | ||
self._device = spi_device.SPIDevice(spi, cs, baudrate=baudrate, | ||
polarity=0, phase=0) | ||
# Setup reset as a digital input (default state for reset line according | ||
|
@@ -361,6 +362,9 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, | |
raise RuntimeError('Failed to configure radio for LoRa mode, check wiring!') | ||
except OSError: | ||
raise RuntimeError('Failed to communicate with radio, check wiring!') | ||
# clear default setting for access to LF registers if frquency > 525MHz | ||
if frequency > 525: | ||
self.low_frequency_mode = 0 | ||
# Setup entire 256 byte FIFO | ||
self._write_u8(_RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0x00) | ||
self._write_u8(_RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0x00) | ||
|
@@ -374,7 +378,7 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, | |
# Set preamble length (default 8 bytes to match radiohead). | ||
self.preamble_length = preamble_length | ||
# Set frequency | ||
self.frequency = frequency | ||
self.frequency_mhz = frequency | ||
# Set TX power to low defaut, 13 dB. | ||
self.tx_power = 13 | ||
|
||
|
@@ -494,6 +498,10 @@ def tx_power(self): | |
high power devices (RFM95/96/97/98, high_power=True) or -1 to 14 for low | ||
power devices. Only integer power levels are actually set (i.e. 12.5 | ||
will result in a value of 12 dBm). | ||
The actual maximum setting for high_power=True is 20dBm but for values > 20 | ||
the PA_BOOST will be enabled resultiung in ad additonla gain of 3dBm. | ||
Theactual setting is reduced by 3dBm. | ||
The reported value will reflect the reduced setting. | ||
""" | ||
if self.high_power: | ||
return self.output_power + 5 | ||
|
@@ -505,14 +513,17 @@ def tx_power(self, val): | |
if self.high_power: | ||
assert 5 <= val <= 23 | ||
# Enable power amp DAC if power is above 20 dB. | ||
# Lower setting by 3db when PA_BOOST enabled - see Data Sheet Section 6.4 | ||
if val > 20: | ||
self.pa_dac = _RH_RF95_PA_DAC_ENABLE | ||
val -= 3 | ||
else: | ||
self.pa_dac = _RH_RF95_PA_DAC_DISABLE | ||
self.pa_select = True | ||
self.output_power = (val - 5) & 0x0F | ||
else: | ||
assert -1 <= val <= 14 | ||
self.pa_select = False | ||
self.max_power = 0b111 # Allow max power output. | ||
self.output_power = (val + 1) & 0x0F | ||
|
||
|
@@ -523,10 +534,11 @@ def rssi(self): | |
# Remember in LoRa mode the payload register changes function to RSSI! | ||
return self._read_u8(_RH_RF95_REG_1A_PKT_RSSI_VALUE) - 137 | ||
|
||
def send(self, data): | ||
def send(self, data, timeout_s=2.): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK - this was just a holdover from the original code. The change makes sense to me. |
||
"""Send a string of data using the transmitter. You can only send 252 | ||
bytes at a time (limited by chip's FIFO size and appended headers). Note | ||
this appends a 4 byte header to be compatible with the RadioHead library. | ||
The timeout is just to prevent a hang (arbitrarily set to 2 Seconds). | ||
""" | ||
# Disable pylint warning to not use length as a check for zero. | ||
# This is a puzzling warning as the below code is clearly the most | ||
|
@@ -551,12 +563,15 @@ def send(self, data): | |
self.transmit() | ||
# Wait for tx done interrupt with explicit polling (not ideal but | ||
# best that can be done right now without interrupts). | ||
while not self.tx_done: | ||
pass | ||
# Clear interrupts. | ||
self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) | ||
start = time.monotonic() | ||
timed_out = False | ||
while not timed_out and not self.tx_done: | ||
if (time.monotonic() - start) >= timeout_s: | ||
timed_out = True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please throw a RuntimeException in the case where tx_done is still false. |
||
# Go back to idle mode after transmit. | ||
self.idle() | ||
# Clear interrupts. | ||
self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) | ||
|
||
def receive(self, timeout_s=0.5, keep_listening=True): | ||
"""Wait to receive a packet from the receiver. Will wait for up to | ||
|
@@ -576,32 +591,34 @@ def receive(self, timeout_s=0.5, keep_listening=True): | |
# enough, however it's the best that can be done from Python without | ||
# interrupt supports. | ||
start = time.monotonic() | ||
while not self.rx_done: | ||
timed_out = False | ||
while not timed_out and not self.rx_done: | ||
if (time.monotonic() - start) >= timeout_s: | ||
return None # Exceeded timeout. | ||
# Clear interrupt. | ||
self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) | ||
timed_out = True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Exception here too and it'll "return" early so you don't need the extra state. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As above, there is still code that needs to execute after the timeout. We could break this into two parts like it is for Arduino and have an "available" function that the user polls until a packet is received. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, returning None is fine with me. I believe we do want an exception for |
||
# Payload ready is set, a packet is in the FIFO. | ||
packet = None | ||
# Enter idle mode to stop receiving other packets. | ||
self.idle() | ||
# Grab the length of the received packet and check it has at least 5 | ||
# bytes to indicate the 4 byte header and at least 1 byte of user data. | ||
length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES) | ||
if length < 5: | ||
packet = None | ||
else: | ||
# Have a good packet, grab it from the FIFO. | ||
# Reset the fifo read ptr to the beginning of the packet. | ||
current_addr = self._read_u8(_RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR) | ||
self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr) | ||
# Read the first 4 bytes to grab the header. | ||
self._read_into(_RH_RF95_REG_00_FIFO, self._BUFFER, length=4) | ||
length -= 4 | ||
# Next read the remaining data into a result packet buffer. | ||
packet = bytearray(length) | ||
self._read_into(_RH_RF95_REG_00_FIFO, packet) | ||
# Listen again if necessary and return the result packet. | ||
if not timed_out: | ||
# Grab the length of the received packet and check it has at least 5 | ||
# bytes to indicate the 4 byte header and at least 1 byte of user data. | ||
length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES) | ||
if length < 5: | ||
packet = None | ||
else: | ||
# Have a good packet, grab it from the FIFO. | ||
# Reset the fifo read ptr to the beginning of the packet. | ||
current_addr = self._read_u8(_RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR) | ||
self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr) | ||
packet = bytearray(length) | ||
# Read the packet. | ||
self._read_into(_RH_RF95_REG_00_FIFO, packet) | ||
# strip off the header | ||
packet = packet[4:] | ||
# Listen again if necessary and return the result packet. | ||
if keep_listening: | ||
self.listen() | ||
else: | ||
# Enter idle mode to stop receiving other packets. | ||
self.idle() | ||
# Clear interrupt. | ||
self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF) | ||
return packet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sigh...My fingers are usually way ahead of my brain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, happens to me too. No worries. :-)