You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

626 lines
30 KiB

  1. # The MIT License (MIT)
  2. #
  3. # Copyright (c) 2017 Tony DiCola for Adafruit Industries
  4. #
  5. # Permission is hereby granted, free of charge, to any person obtaining a copy
  6. # of this software and associated documentation files (the "Software"), to deal
  7. # in the Software without restriction, including without limitation the rights
  8. # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. # copies of the Software, and to permit persons to whom the Software is
  10. # furnished to do so, subject to the following conditions:
  11. #
  12. # The above copyright notice and this permission notice shall be included in
  13. # all copies or substantial portions of the Software.
  14. #
  15. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. # THE SOFTWARE.
  22. """
  23. `adafruit_rfm9x`
  24. ====================================================
  25. CircuitPython module for the RFM95/6/7/8 LoRa 433/915mhz radio modules. This is
  26. adapted from the Radiohead library RF95 code from:
  27. http: www.airspayce.com/mikem/arduino/RadioHead/
  28. * Author(s): Tony DiCola, Jerry Needell
  29. """
  30. import time
  31. import digitalio
  32. from micropython import const
  33. import adafruit_bus_device.spi_device as spi_device
  34. __version__ = "1.0.3"
  35. __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_rfm95.git"
  36. # pylint: disable=bad-whitespace
  37. # Internal constants:
  38. # Register names (FSK Mode even though we use LoRa instead, from table 85)
  39. _RH_RF95_REG_00_FIFO = const(0x00)
  40. _RH_RF95_REG_01_OP_MODE = const(0x01)
  41. _RH_RF95_REG_02_RESERVED = const(0x02)
  42. _RH_RF95_REG_03_RESERVED = const(0x03)
  43. _RH_RF95_REG_04_RESERVED = const(0x04)
  44. _RH_RF95_REG_05_RESERVED = const(0x05)
  45. _RH_RF95_REG_06_FRF_MSB = const(0x06)
  46. _RH_RF95_REG_07_FRF_MID = const(0x07)
  47. _RH_RF95_REG_08_FRF_LSB = const(0x08)
  48. _RH_RF95_REG_09_PA_CONFIG = const(0x09)
  49. _RH_RF95_REG_0A_PA_RAMP = const(0x0a)
  50. _RH_RF95_REG_0B_OCP = const(0x0b)
  51. _RH_RF95_REG_0C_LNA = const(0x0c)
  52. _RH_RF95_REG_0D_FIFO_ADDR_PTR = const(0x0d)
  53. _RH_RF95_REG_0E_FIFO_TX_BASE_ADDR = const(0x0e)
  54. _RH_RF95_REG_0F_FIFO_RX_BASE_ADDR = const(0x0f)
  55. _RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR = const(0x10)
  56. _RH_RF95_REG_11_IRQ_FLAGS_MASK = const(0x11)
  57. _RH_RF95_REG_12_IRQ_FLAGS = const(0x12)
  58. _RH_RF95_REG_13_RX_NB_BYTES = const(0x13)
  59. _RH_RF95_REG_14_RX_HEADER_CNT_VALUE_MSB = const(0x14)
  60. _RH_RF95_REG_15_RX_HEADER_CNT_VALUE_LSB = const(0x15)
  61. _RH_RF95_REG_16_RX_PACKET_CNT_VALUE_MSB = const(0x16)
  62. _RH_RF95_REG_17_RX_PACKET_CNT_VALUE_LSB = const(0x17)
  63. _RH_RF95_REG_18_MODEM_STAT = const(0x18)
  64. _RH_RF95_REG_19_PKT_SNR_VALUE = const(0x19)
  65. _RH_RF95_REG_1A_PKT_RSSI_VALUE = const(0x1a)
  66. _RH_RF95_REG_1B_RSSI_VALUE = const(0x1b)
  67. _RH_RF95_REG_1C_HOP_CHANNEL = const(0x1c)
  68. _RH_RF95_REG_1D_MODEM_CONFIG1 = const(0x1d)
  69. _RH_RF95_REG_1E_MODEM_CONFIG2 = const(0x1e)
  70. _RH_RF95_REG_1F_SYMB_TIMEOUT_LSB = const(0x1f)
  71. _RH_RF95_REG_20_PREAMBLE_MSB = const(0x20)
  72. _RH_RF95_REG_21_PREAMBLE_LSB = const(0x21)
  73. _RH_RF95_REG_22_PAYLOAD_LENGTH = const(0x22)
  74. _RH_RF95_REG_23_MAX_PAYLOAD_LENGTH = const(0x23)
  75. _RH_RF95_REG_24_HOP_PERIOD = const(0x24)
  76. _RH_RF95_REG_25_FIFO_RX_BYTE_ADDR = const(0x25)
  77. _RH_RF95_REG_26_MODEM_CONFIG3 = const(0x26)
  78. _RH_RF95_REG_40_DIO_MAPPING1 = const(0x40)
  79. _RH_RF95_REG_41_DIO_MAPPING2 = const(0x41)
  80. _RH_RF95_REG_42_VERSION = const(0x42)
  81. _RH_RF95_REG_4B_TCXO = const(0x4b)
  82. _RH_RF95_REG_4D_PA_DAC = const(0x4d)
  83. _RH_RF95_REG_5B_FORMER_TEMP = const(0x5b)
  84. _RH_RF95_REG_61_AGC_REF = const(0x61)
  85. _RH_RF95_REG_62_AGC_THRESH1 = const(0x62)
  86. _RH_RF95_REG_63_AGC_THRESH2 = const(0x63)
  87. _RH_RF95_REG_64_AGC_THRESH3 = const(0x64)
  88. # RH_RF95_REG_01_OP_MODE 0x01
  89. _RH_RF95_LONG_RANGE_MODE = const(0x80)
  90. _RH_RF95_ACCESS_SHARED_REG = const(0x40)
  91. _RH_RF95_MODE = const(0x07)
  92. _RH_RF95_MODE_SLEEP = const(0x00)
  93. _RH_RF95_MODE_STDBY = const(0x01)
  94. _RH_RF95_MODE_FSTX = const(0x02)
  95. _RH_RF95_MODE_TX = const(0x03)
  96. _RH_RF95_MODE_FSRX = const(0x04)
  97. _RH_RF95_MODE_RXCONTINUOUS = const(0x05)
  98. _RH_RF95_MODE_RXSINGLE = const(0x06)
  99. _RH_RF95_MODE_CAD = const(0x07)
  100. # RH_RF95_REG_09_PA_CONFIG 0x09
  101. _RH_RF95_PA_SELECT = const(0x80)
  102. _RH_RF95_MAX_POWER = const(0x70)
  103. _RH_RF95_OUTPUT_POWER = const(0x0f)
  104. # RH_RF95_REG_0A_PA_RAMP 0x0a
  105. _RH_RF95_LOW_PN_TX_PLL_OFF = const(0x10)
  106. _RH_RF95_PA_RAMP = const(0x0f)
  107. _RH_RF95_PA_RAMP_3_4MS = const(0x00)
  108. _RH_RF95_PA_RAMP_2MS = const(0x01)
  109. _RH_RF95_PA_RAMP_1MS = const(0x02)
  110. _RH_RF95_PA_RAMP_500US = const(0x03)
  111. _RH_RF95_PA_RAMP_250US = const(0x04)
  112. _RH_RF95_PA_RAMP_125US = const(0x05)
  113. _RH_RF95_PA_RAMP_100US = const(0x06)
  114. _RH_RF95_PA_RAMP_62US = const(0x07)
  115. _RH_RF95_PA_RAMP_50US = const(0x08)
  116. _RH_RF95_PA_RAMP_40US = const(0x09)
  117. _RH_RF95_PA_RAMP_31US = const(0x0a)
  118. _RH_RF95_PA_RAMP_25US = const(0x0b)
  119. _RH_RF95_PA_RAMP_20US = const(0x0c)
  120. _RH_RF95_PA_RAMP_15US = const(0x0d)
  121. _RH_RF95_PA_RAMP_12US = const(0x0e)
  122. _RH_RF95_PA_RAMP_10US = const(0x0f)
  123. # RH_RF95_REG_0B_OCP 0x0b
  124. _RH_RF95_OCP_ON = const(0x20)
  125. _RH_RF95_OCP_TRIM = const(0x1f)
  126. # RH_RF95_REG_0C_LNA 0x0c
  127. _RH_RF95_LNA_GAIN = const(0xe0)
  128. _RH_RF95_LNA_BOOST = const(0x03)
  129. _RH_RF95_LNA_BOOST_DEFAULT = const(0x00)
  130. _RH_RF95_LNA_BOOST_150PC = const(0x11)
  131. # RH_RF95_REG_11_IRQ_FLAGS_MASK 0x11
  132. _RH_RF95_RX_TIMEOUT_MASK = const(0x80)
  133. _RH_RF95_RX_DONE_MASK = const(0x40)
  134. _RH_RF95_PAYLOAD_CRC_ERROR_MASK = const(0x20)
  135. _RH_RF95_VALID_HEADER_MASK = const(0x10)
  136. _RH_RF95_TX_DONE_MASK = const(0x08)
  137. _RH_RF95_CAD_DONE_MASK = const(0x04)
  138. _RH_RF95_FHSS_CHANGE_CHANNEL_MASK = const(0x02)
  139. _RH_RF95_CAD_DETECTED_MASK = const(0x01)
  140. # RH_RF95_REG_12_IRQ_FLAGS 0x12
  141. _RH_RF95_RX_TIMEOUT = const(0x80)
  142. _RH_RF95_RX_DONE = const(0x40)
  143. _RH_RF95_PAYLOAD_CRC_ERROR = const(0x20)
  144. _RH_RF95_VALID_HEADER = const(0x10)
  145. _RH_RF95_TX_DONE = const(0x08)
  146. _RH_RF95_CAD_DONE = const(0x04)
  147. _RH_RF95_FHSS_CHANGE_CHANNEL = const(0x02)
  148. _RH_RF95_CAD_DETECTED = const(0x01)
  149. # RH_RF95_REG_18_MODEM_STAT 0x18
  150. _RH_RF95_RX_CODING_RATE = const(0xe0)
  151. _RH_RF95_MODEM_STATUS_CLEAR = const(0x10)
  152. _RH_RF95_MODEM_STATUS_HEADER_INFO_VALID = const(0x08)
  153. _RH_RF95_MODEM_STATUS_RX_ONGOING = const(0x04)
  154. _RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED = const(0x02)
  155. _RH_RF95_MODEM_STATUS_SIGNAL_DETECTED = const(0x01)
  156. # RH_RF95_REG_1C_HOP_CHANNEL 0x1c
  157. _RH_RF95_PLL_TIMEOUT = const(0x80)
  158. _RH_RF95_RX_PAYLOAD_CRC_IS_ON = const(0x40)
  159. _RH_RF95_FHSS_PRESENT_CHANNEL = const(0x3f)
  160. # RH_RF95_REG_1D_MODEM_CONFIG1 0x1d
  161. _RH_RF95_BW = const(0xc0)
  162. _RH_RF95_BW_125KHZ = const(0x00)
  163. _RH_RF95_BW_250KHZ = const(0x40)
  164. _RH_RF95_BW_500KHZ = const(0x80)
  165. _RH_RF95_BW_RESERVED = const(0xc0)
  166. _RH_RF95_CODING_RATE = const(0x38)
  167. _RH_RF95_CODING_RATE_4_5 = const(0x00)
  168. _RH_RF95_CODING_RATE_4_6 = const(0x08)
  169. _RH_RF95_CODING_RATE_4_7 = const(0x10)
  170. _RH_RF95_CODING_RATE_4_8 = const(0x18)
  171. _RH_RF95_IMPLICIT_HEADER_MODE_ON = const(0x04)
  172. _RH_RF95_RX_PAYLOAD_CRC_ON = const(0x02)
  173. _RH_RF95_LOW_DATA_RATE_OPTIMIZE = const(0x01)
  174. # RH_RF95_REG_1E_MODEM_CONFIG2 0x1e
  175. _RH_RF95_SPREADING_FACTOR = const(0xf0)
  176. _RH_RF95_SPREADING_FACTOR_64CPS = const(0x60)
  177. _RH_RF95_SPREADING_FACTOR_128CPS = const(0x70)
  178. _RH_RF95_SPREADING_FACTOR_256CPS = const(0x80)
  179. _RH_RF95_SPREADING_FACTOR_512CPS = const(0x90)
  180. _RH_RF95_SPREADING_FACTOR_1024CPS = const(0xa0)
  181. _RH_RF95_SPREADING_FACTOR_2048CPS = const(0xb0)
  182. _RH_RF95_SPREADING_FACTOR_4096CPS = const(0xc0)
  183. _RH_RF95_TX_CONTINUOUS_MOE = const(0x08)
  184. _RH_RF95_AGC_AUTO_ON = const(0x04)
  185. _RH_RF95_SYM_TIMEOUT_MSB = const(0x03)
  186. # RH_RF95_REG_4D_PA_DAC 0x4d
  187. _RH_RF95_PA_DAC_DISABLE = const(0x04)
  188. _RH_RF95_PA_DAC_ENABLE = const(0x07)
  189. # The crystal oscillator frequency of the module
  190. _RH_RF95_FXOSC = 32000000.0
  191. # The Frequency Synthesizer step = RH_RF95_FXOSC / 2^^19
  192. _RH_RF95_FSTEP = (_RH_RF95_FXOSC / 524288)
  193. # RadioHead specific compatibility constants.
  194. _RH_BROADCAST_ADDRESS = const(0xFF)
  195. # User facing constants:
  196. SLEEP_MODE = 0b000
  197. STANDBY_MODE = 0b001
  198. FS_TX_MODE = 0b010
  199. TX_MODE = 0b011
  200. FS_RX_MODE = 0b100
  201. RX_MODE = 0b101
  202. # pylint: enable=bad-whitespace
  203. # Disable the too many instance members warning. Pylint has no knowledge
  204. # of the context and is merely guessing at the proper amount of members. This
  205. # is a complex chip which requires exposing many attributes and state. Disable
  206. # the warning to work around the error.
  207. # pylint: disable=too-many-instance-attributes
  208. class RFM9x:
  209. """Interface to a RFM95/6/7/8 LoRa radio module. Allows sending and
  210. receivng bytes of data in long range LoRa mode at a support board frequency
  211. (433/915mhz).
  212. You must specify the following parameters:
  213. - spi: The SPI bus connected to the radio.
  214. - cs: The CS pin DigitalInOut connected to the radio.
  215. - reset: The reset/RST pin DigialInOut connected to the radio.
  216. - frequency: The frequency (in mhz) of the radio module (433/915mhz typically).
  217. You can optionally specify:
  218. - preamble_length: The length in bytes of the packet preamble (default 8).
  219. - high_power: Boolean to indicate a high power board (RFM95, etc.). Default
  220. is True for high power.
  221. - baudrate: Baud rate of the SPI connection, default is 10mhz but you might
  222. choose to lower to 1mhz if using long wires or a breadboard.
  223. Remember this library makes a best effort at receiving packets with pure
  224. Python code. Trying to receive packets too quickly will result in lost data
  225. so limit yourself to simple scenarios of sending and receiving single
  226. packets at a time.
  227. Also note this library tries to be compatible with raw RadioHead Arduino
  228. library communication. This means the library sets up the radio modulation
  229. to match RadioHead's defaults. Features like addressing and guaranteed
  230. delivery need to be implemented at an application level.
  231. """
  232. # Global buffer to hold data sent and received with the chip. This must be
  233. # at least as large as the FIFO on the chip (256 bytes)! Keep this on the
  234. # class level to ensure only one copy ever exists (with the trade-off that
  235. # this is NOT re-entrant or thread safe code by design).
  236. _BUFFER = bytearray(10)
  237. class _RegisterBits:
  238. # Class to simplify access to the many configuration bits avaialable
  239. # on the chip's registers. This is a subclass here instead of using
  240. # a higher level module to increase the efficiency of memory usage
  241. # (all of the instances of this bit class will share the same buffer
  242. # used by the parent RFM69 class instance vs. each having their own
  243. # buffer and taking too much memory).
  244. # Quirk of pylint that it requires public methods for a class. This
  245. # is a decorator class in Python and by design it has no public methods.
  246. # Instead it uses dunder accessors like get and set below. For some
  247. # reason pylint can't figure this out so disable the check.
  248. # pylint: disable=too-few-public-methods
  249. # Again pylint fails to see the true intent of this code and warns
  250. # against private access by calling the write and read functions below.
  251. # This is by design as this is an internally used class. Disable the
  252. # check from pylint.
  253. # pylint: disable=protected-access
  254. def __init__(self, address, *, offset=0, bits=1):
  255. assert 0 <= offset <= 7
  256. assert 1 <= bits <= 8
  257. assert (offset + bits) <= 8
  258. self._address = address
  259. self._mask = 0
  260. for _ in range(bits):
  261. self._mask <<= 1
  262. self._mask |= 1
  263. self._mask <<= offset
  264. self._offset = offset
  265. def __get__(self, obj, objtype):
  266. reg_value = obj._read_u8(self._address)
  267. return (reg_value & self._mask) >> self._offset
  268. def __set__(self, obj, val):
  269. reg_value = obj._read_u8(self._address)
  270. reg_value &= ~self._mask
  271. reg_value |= (val & 0xFF) << self._offset
  272. obj._write_u8(self._address, reg_value)
  273. operation_mode = _RegisterBits(_RH_RF95_REG_01_OP_MODE, bits=3)
  274. low_frequency_mode = _RegisterBits(_RH_RF95_REG_01_OP_MODE, offset=3, bits=1)
  275. modulation_type = _RegisterBits(_RH_RF95_REG_01_OP_MODE, offset=5, bits=2)
  276. # Long range/LoRa mode can only be set in sleep mode!
  277. long_range_mode = _RegisterBits(_RH_RF95_REG_01_OP_MODE, offset=7, bits=1)
  278. output_power = _RegisterBits(_RH_RF95_REG_09_PA_CONFIG, bits=4)
  279. max_power = _RegisterBits(_RH_RF95_REG_09_PA_CONFIG, offset=4, bits=3)
  280. pa_select = _RegisterBits(_RH_RF95_REG_09_PA_CONFIG, offset=7, bits=1)
  281. pa_dac = _RegisterBits(_RH_RF95_REG_4D_PA_DAC, bits=3)
  282. dio0_mapping = _RegisterBits(_RH_RF95_REG_40_DIO_MAPPING1, offset=6, bits=2)
  283. tx_done = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=3, bits=1)
  284. rx_done = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=6, bits=1)
  285. def __init__(self, spi, cs, reset, frequency, *, preamble_length=8,
  286. high_power=True, baudrate=5000000):
  287. self.high_power = high_power
  288. # Device support SPI mode 0 (polarity & phase = 0) up to a max of 10mhz.
  289. # Set Default Baudrate to 5MHz to avoid problems
  290. self._device = spi_device.SPIDevice(spi, cs, baudrate=baudrate,
  291. polarity=0, phase=0)
  292. # Setup reset as a digital input (default state for reset line according
  293. # to the datasheet). This line is pulled low as an output quickly to
  294. # trigger a reset. Note that reset MUST be done like this and set as
  295. # a high impedence input or else the chip cannot change modes (trust me!).
  296. self._reset = reset
  297. self._reset.switch_to_input(pull=digitalio.Pull.UP)
  298. self.reset()
  299. # No device type check! Catch an error from the very first request and
  300. # throw a nicer message to indicate possible wiring problems.
  301. try:
  302. # Set sleep mode, wait 10s and confirm in sleep mode (basic device check).
  303. # Also set long range mode (LoRa mode) as it can only be done in sleep.
  304. self.sleep()
  305. self.long_range_mode = True
  306. self._write_u8(_RH_RF95_REG_01_OP_MODE, 0b10001000)
  307. time.sleep(0.01)
  308. val = self._read_u8(_RH_RF95_REG_01_OP_MODE)
  309. print('op mode: {0}'.format(bin(val)))
  310. if self.operation_mode != SLEEP_MODE or not self.long_range_mode:
  311. raise RuntimeError('Failed to configure radio for LoRa mode, check wiring!')
  312. except OSError:
  313. raise RuntimeError('Failed to communicate with radio, check wiring!')
  314. # clear default setting for access to LF registers if frequency > 525MHz
  315. if frequency > 525:
  316. self.low_frequency_mode = 0
  317. # Setup entire 256 byte FIFO
  318. self._write_u8(_RH_RF95_REG_0E_FIFO_TX_BASE_ADDR, 0x00)
  319. self._write_u8(_RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0x00)
  320. # Set mode idle
  321. self.idle()
  322. # Set modem config to RadioHead compatible Bw125Cr45Sf128 mode.
  323. # Note no sync word is set for LoRa mode either!
  324. self._write_u8(_RH_RF95_REG_1D_MODEM_CONFIG1, 0x72) # Fei msb?
  325. self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, 0x74) # Fei lsb?
  326. self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb?
  327. # Set preamble length (default 8 bytes to match radiohead).
  328. self.preamble_length = preamble_length
  329. # Set frequency
  330. self.frequency_mhz = frequency
  331. # Set TX power to low defaut, 13 dB.
  332. self.tx_power = 13
  333. def _read_into(self, address, buf, length=None):
  334. # Read a number of bytes from the specified address into the provided
  335. # buffer. If length is not specified (the default) the entire buffer
  336. # will be filled.
  337. if length is None:
  338. length = len(buf)
  339. with self._device as device:
  340. self._BUFFER[0] = address & 0x7F # Strip out top bit to set 0
  341. # value (read).
  342. device.write(self._BUFFER, end=1)
  343. device.readinto(buf, end=length)
  344. def _read_u8(self, address):
  345. # Read a single byte from the provided address and return it.
  346. self._read_into(address, self._BUFFER, length=1)
  347. return self._BUFFER[0]
  348. def _write_from(self, address, buf, length=None):
  349. # Write a number of bytes to the provided address and taken from the
  350. # provided buffer. If no length is specified (the default) the entire
  351. # buffer is written.
  352. if length is None:
  353. length = len(buf)
  354. with self._device as device:
  355. self._BUFFER[0] = (address | 0x80) & 0xFF # Set top bit to 1 to
  356. # indicate a write.
  357. device.write(self._BUFFER, end=1)
  358. device.write(buf, end=length)
  359. def _write_u8(self, address, val):
  360. # Write a byte register to the chip. Specify the 7-bit address and the
  361. # 8-bit value to write to that address.
  362. with self._device as device:
  363. self._BUFFER[0] = (address | 0x80) & 0xFF # Set top bit to 1 to
  364. # indicate a write.
  365. self._BUFFER[1] = val & 0xFF
  366. device.write(self._BUFFER, end=2)
  367. def reset(self):
  368. """Perform a reset of the chip."""
  369. # See section 7.2.2 of the datasheet for reset description.
  370. self._reset.switch_to_output(value=False)
  371. time.sleep(0.0001) # 100 us
  372. self._reset.switch_to_input(pull=digitalio.Pull.UP)
  373. time.sleep(0.005) # 5 ms
  374. def idle(self):
  375. """Enter idle standby mode."""
  376. self.operation_mode = STANDBY_MODE
  377. def sleep(self):
  378. """Enter sleep mode."""
  379. self.operation_mode = SLEEP_MODE
  380. def listen(self):
  381. """Listen for packets to be received by the chip. Use :py:func:`receive`
  382. to listen, wait and retrieve packets as they're available.
  383. """
  384. self.operation_mode = RX_MODE
  385. self.dio0_mapping = 0b00 # Interrupt on rx done.
  386. def transmit(self):
  387. """Transmit a packet which is queued in the FIFO. This is a low level
  388. function for entering transmit mode and more. For generating and
  389. transmitting a packet of data use :py:func:`send` instead.
  390. """
  391. self.operation_mode = TX_MODE
  392. self.dio0_mapping = 0b01 # Interrupt on tx done.
  393. @property
  394. def preamble_length(self):
  395. """The length of the preamble for sent and received packets, an unsigned
  396. 16-bit value. Received packets must match this length or they are
  397. ignored! Set to 8 to match the RadioHead RFM95 library.
  398. """
  399. msb = self._read_u8(_RH_RF95_REG_20_PREAMBLE_MSB)
  400. lsb = self._read_u8(_RH_RF95_REG_21_PREAMBLE_LSB)
  401. return ((msb << 8) | lsb) & 0xFFFF
  402. @preamble_length.setter
  403. def preamble_length(self, val):
  404. assert 0 <= val <= 65535
  405. self._write_u8(_RH_RF95_REG_20_PREAMBLE_MSB, (val >> 8) & 0xFF)
  406. self._write_u8(_RH_RF95_REG_21_PREAMBLE_LSB, val & 0xFF)
  407. @property
  408. def frequency_mhz(self):
  409. """The frequency of the radio in Megahertz. Only the allowed values for
  410. your radio must be specified (i.e. 433 vs. 915 mhz)!
  411. """
  412. msb = self._read_u8(_RH_RF95_REG_06_FRF_MSB)
  413. mid = self._read_u8(_RH_RF95_REG_07_FRF_MID)
  414. lsb = self._read_u8(_RH_RF95_REG_08_FRF_LSB)
  415. frf = ((msb << 16) | (mid << 8) | lsb) & 0xFFFFFF
  416. frequency = (frf * _RH_RF95_FSTEP) / 1000000.0
  417. return frequency
  418. @frequency_mhz.setter
  419. def frequency_mhz(self, val):
  420. assert 240 <= val <= 960
  421. # Calculate FRF register 24-bit value.
  422. frf = int((val * 1000000.0) / _RH_RF95_FSTEP) & 0xFFFFFF
  423. # Extract byte values and update registers.
  424. msb = frf >> 16
  425. mid = (frf >> 8) & 0xFF
  426. lsb = frf & 0xFF
  427. self._write_u8(_RH_RF95_REG_06_FRF_MSB, msb)
  428. self._write_u8(_RH_RF95_REG_07_FRF_MID, mid)
  429. self._write_u8(_RH_RF95_REG_08_FRF_LSB, lsb)
  430. @property
  431. def tx_power(self):
  432. """The transmit power in dBm. Can be set to a value from 5 to 23 for
  433. high power devices (RFM95/96/97/98, high_power=True) or -1 to 14 for low
  434. power devices. Only integer power levels are actually set (i.e. 12.5
  435. will result in a value of 12 dBm).
  436. The actual maximum setting for high_power=True is 20dBm but for values > 20
  437. the PA_BOOST will be enabled resulting in an additional gain of 3dBm.
  438. The actual setting is reduced by 3dBm.
  439. The reported value will reflect the reduced setting.
  440. """
  441. if self.high_power:
  442. return self.output_power + 5
  443. return self.output_power - 1
  444. @tx_power.setter
  445. def tx_power(self, val):
  446. val = int(val)
  447. if self.high_power:
  448. assert 5 <= val <= 23
  449. # Enable power amp DAC if power is above 20 dB.
  450. # Lower setting by 3db when PA_BOOST enabled - see Data Sheet Section 6.4
  451. if val > 20:
  452. self.pa_dac = _RH_RF95_PA_DAC_ENABLE
  453. val -= 3
  454. else:
  455. self.pa_dac = _RH_RF95_PA_DAC_DISABLE
  456. self.pa_select = True
  457. self.output_power = (val - 5) & 0x0F
  458. else:
  459. assert -1 <= val <= 14
  460. self.pa_select = False
  461. self.max_power = 0b111 # Allow max power output.
  462. self.output_power = (val + 1) & 0x0F
  463. @property
  464. def rssi(self):
  465. """The received strength indicator (in dBm) of the last received message."""
  466. # Read RSSI register and convert to value using formula in datasheet.
  467. # Remember in LoRa mode the payload register changes function to RSSI!
  468. return self._read_u8(_RH_RF95_REG_1A_PKT_RSSI_VALUE) - 137
  469. def send(self, data, timeout=2.):
  470. """Send a string of data using the transmitter. You can only send 252
  471. bytes at a time (limited by chip's FIFO size and appended headers). Note
  472. this appends a 4 byte header to be compatible with the RadioHead library.
  473. The timeout is just to prevent a hang (arbitrarily set to 2 Seconds).
  474. """
  475. # Disable pylint warning to not use length as a check for zero.
  476. # This is a puzzling warning as the below code is clearly the most
  477. # efficient and proper way to ensure a precondition that the provided
  478. # buffer be within an expected range of bounds. Disable this check.
  479. # pylint: disable=len-as-condition
  480. assert 0 < len(data) <= 252
  481. # pylint: enable=len-as-condition
  482. self.idle() # Stop receiving to clear FIFO and keep it clear.
  483. # Fill the FIFO with a packet to send.
  484. self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, 0x00) # FIFO starts at 0.
  485. # Write header bytes.
  486. self._write_u8(_RH_RF95_REG_00_FIFO, _RH_BROADCAST_ADDRESS) # txHeaderTo
  487. self._write_u8(_RH_RF95_REG_00_FIFO, _RH_BROADCAST_ADDRESS) # txHeaderFrom
  488. self._write_u8(_RH_RF95_REG_00_FIFO, 0x00) # txHeaderId
  489. self._write_u8(_RH_RF95_REG_00_FIFO, 0x00) # txHeaderFlags
  490. # Write payload.
  491. self._write_from(_RH_RF95_REG_00_FIFO, data)
  492. # Write payload and header length.
  493. self._write_u8(_RH_RF95_REG_22_PAYLOAD_LENGTH, len(data) + 4)
  494. # Turn on transmit mode to send out the packet.
  495. self.transmit()
  496. # Wait for tx done interrupt with explicit polling (not ideal but
  497. # best that can be done right now without interrupts).
  498. start = time.monotonic()
  499. timed_out = False
  500. while not timed_out and not self.tx_done:
  501. if (time.monotonic() - start) >= timeout:
  502. timed_out = True
  503. # Go back to idle mode after transmit.
  504. self.idle()
  505. # Clear interrupts.
  506. self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF)
  507. if timed_out:
  508. raise RuntimeError('Timeout during packet send')
  509. def receive(self, timeout=0.5, keep_listening=True):
  510. """Wait to receive a packet from the receiver. Will wait for up to
  511. timeout amount of seconds for a packet to be received and decoded. If
  512. a packet is found the payload bytes are returned, otherwise None is
  513. returned (which indicates the timeout elapsed with no reception). Note
  514. this assumes a 4-byte header is prepended to the data for compatibilty
  515. with the RadioHead library (the header is not validated nor returned).
  516. If keep_listening is True (the default) the chip will immediately enter
  517. listening mode after reception of a packet, otherwise it will fall back
  518. to idle mode and ignore any future reception.
  519. """
  520. # Make sure we are listening for packets.
  521. self.listen()
  522. # Wait for the rx done interrupt. This is not ideal and will
  523. # surely miss or overflow the FIFO when packets aren't read fast
  524. # enough, however it's the best that can be done from Python without
  525. # interrupt supports.
  526. start = time.monotonic()
  527. timed_out = False
  528. while not timed_out and not self.rx_done:
  529. if (time.monotonic() - start) >= timeout:
  530. timed_out = True
  531. # Payload ready is set, a packet is in the FIFO.
  532. packet = None
  533. if not timed_out:
  534. # Grab the length of the received packet and check it has at least 5
  535. # bytes to indicate the 4 byte header and at least 1 byte of user data.
  536. length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES)
  537. if length < 5:
  538. packet = None
  539. else:
  540. # Have a good packet, grab it from the FIFO.
  541. # Reset the fifo read ptr to the beginning of the packet.
  542. current_addr = self._read_u8(_RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR)
  543. self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr)
  544. packet = bytearray(length)
  545. # Read the packet.
  546. self._read_into(_RH_RF95_REG_00_FIFO, packet)
  547. # strip off the header
  548. packet = packet[4:]
  549. # Listen again if necessary and return the result packet.
  550. if keep_listening:
  551. self.listen()
  552. else:
  553. # Enter idle mode to stop receiving other packets.
  554. self.idle()
  555. # Clear interrupt.
  556. self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF)
  557. return packet