pamoja.radios.sx127x
The Semtech SX1276, SX1277, SX1278, and SX1279, as the register values they take.
These radios, and modules built on them such as the RFM95W, are driven through registers. Each SPI transaction starts with an address byte whose top bit is set for a write, followed by the data, and the address advances with each byte except at the FIFO. These functions give the addresses, the values a LoRa link and an output power put in them, and the readings decoded, from the SX1276/77/78/79 datasheet (Rev 7), so a program with its own SPI access can drive the chip.
1"""The Semtech SX1276, SX1277, SX1278, and SX1279, as the register values they take. 2 3These radios, and modules built on them such as the RFM95W, are driven through registers. 4Each SPI transaction starts with an address byte whose top bit is set for a write, followed 5by the data, and the address advances with each byte except at the FIFO. These functions 6give the addresses, the values a LoRa link and an output power put in them, and the 7readings decoded, from the SX1276/77/78/79 datasheet (Rev 7), so a program with its own SPI 8access can drive the chip. 9""" 10 11from __future__ import annotations 12 13from enum import Enum, IntEnum, IntFlag 14 15from pamoja._native import ( 16 LinkBudget, 17 LoraLink, 18 Sx127xHighBwOptimize as HighBwOptimize, 19 Sx127xModem as Modem, 20 Sx127xModemStatus as ModemStatus, 21 Sx127xPacketStatus as PacketStatus, 22 Sx127xSpuriousReception as SpuriousReception, 23 Sx127xTxPower as TxPower, 24) 25from pamoja._native import sx127x_automatic_if as _automatic_if 26from pamoja._native import sx127x_constants as _constants 27from pamoja._native import sx127x_frequency_from_word as _frequency_from_word 28from pamoja._native import sx127x_frequency_word as _frequency_word 29from pamoja._native import sx127x_fsk_op_mode as _fsk_op_mode 30from pamoja._native import sx127x_high_bw_optimize as _high_bw_optimize 31from pamoja._native import sx127x_image_cal_start as _image_cal_start 32from pamoja._native import sx127x_invert_iq as _invert_iq 33from pamoja._native import sx127x_invert_iq_2 as _invert_iq_2 34from pamoja._native import sx127x_irq_flags as _irq_flags 35from pamoja._native import sx127x_lora_op_mode as _lora_op_mode 36from pamoja._native import sx127x_mode_from_op_mode as _mode_from_op_mode 37from pamoja._native import sx127x_modem as _modem 38from pamoja._native import sx127x_modem_status as _modem_status 39from pamoja._native import sx127x_ocp_register as _ocp_register 40from pamoja._native import sx127x_packet_status as _packet_status 41from pamoja._native import sx127x_read_address as _read_address 42from pamoja._native import sx127x_registers as _registers 43from pamoja._native import sx127x_rssi_dbm as _rssi_dbm 44from pamoja._native import sx127x_spurious_reception as _spurious_reception 45from pamoja._native import sx127x_symbol_timeout as _symbol_timeout 46from pamoja._native import sx127x_tx_power as _tx_power 47from pamoja._native import sx127x_tx_power_under_ceiling as _tx_power_under_ceiling 48from pamoja._native import sx127x_write_address as _write_address 49 50__all__ = [ 51 "IMAGE_CAL_RUNNING", 52 "IMAGE_CAL_START", 53 "LNA_BOOSTED", 54 "PA_DAC_DEFAULT", 55 "PA_DAC_HIGH_POWER", 56 "SYNC_WORD_PRIVATE", 57 "SYNC_WORD_PUBLIC", 58 "TCXO_INPUT_ON", 59 "VERSION", 60 "WRITE", 61 "Dio0", 62 "HighBwOptimize", 63 "Irq", 64 "Mode", 65 "Modem", 66 "ModemStatus", 67 "PaOutput", 68 "PacketStatus", 69 "Register", 70 "SpuriousReception", 71 "TxPower", 72 "automatic_if", 73 "frequency_from_word", 74 "frequency_word", 75 "fsk_op_mode", 76 "high_bw_optimize", 77 "image_cal_start", 78 "invert_iq", 79 "invert_iq_2", 80 "lora_op_mode", 81 "mode_from_op_mode", 82 "modem", 83 "modem_status", 84 "ocp_register", 85 "packet_status", 86 "read_address", 87 "rssi_dbm", 88 "spurious_reception", 89 "symbol_timeout", 90 "tx_power", 91 "tx_power_under_ceiling", 92 "write_address", 93] 94 95_REGISTERS = _registers() 96_CONSTANTS = _constants() 97_IRQ_FLAGS = _irq_flags() 98 99#: The RegVersion value of an SX1276, SX1277, SX1278, or SX1279. 100VERSION = _CONSTANTS["version"] 101#: The bit of an address byte that makes an access a write. 102WRITE = _CONSTANTS["write"] 103#: The sync word the datasheet reserves for LoRaWAN networks. 104SYNC_WORD_PUBLIC = _CONSTANTS["syncWordPublic"] 105#: The private sync word, and the chip's reset value. 106SYNC_WORD_PRIVATE = _CONSTANTS["syncWordPrivate"] 107#: RegPaDac at its reset value. 108PA_DAC_DEFAULT = _CONSTANTS["paDacDefault"] 109#: RegPaDac with the +20 dBm setting on PA_BOOST. 110PA_DAC_HIGH_POWER = _CONSTANTS["paDacHighPower"] 111#: The RegImageCal bit that starts a calibration. 112IMAGE_CAL_START = _CONSTANTS["imageCalStart"] 113#: The RegImageCal bit set while a calibration runs. 114IMAGE_CAL_RUNNING = _CONSTANTS["imageCalRunning"] 115#: RegLna with maximum gain and the high frequency LNA boost. 116LNA_BOOSTED = _CONSTANTS["lnaBoosted"] 117#: RegTcxo for a module clocked by a TCXO. 118TCXO_INPUT_ON = _CONSTANTS["tcxoInputOn"] 119 120 121class Register(IntEnum): 122 """The register addresses, from Table 41 of the datasheet with the LoRa page selected.""" 123 124 #: RegFifo, the LoRa data buffer, read or written at RegFifoAddrPtr. 125 FIFO = _REGISTERS["fifo"] 126 #: RegOpMode: LoRa or FSK, the register page, and the operating mode. 127 OP_MODE = _REGISTERS["opMode"] 128 #: RegFrfMsb, the top byte of the carrier word. 129 FRF_MSB = _REGISTERS["frfMsb"] 130 #: RegFrfMid, the middle byte of the carrier word. 131 FRF_MID = _REGISTERS["frfMid"] 132 #: RegFrfLsb, the low byte of the carrier word. 133 FRF_LSB = _REGISTERS["frfLsb"] 134 #: RegPaConfig: the amplifier output, its maximum, and the power. 135 PA_CONFIG = _REGISTERS["paConfig"] 136 #: RegPaRamp, the amplifier ramp time. 137 PA_RAMP = _REGISTERS["paRamp"] 138 #: RegOcp, the amplifier current limit. 139 OCP = _REGISTERS["ocp"] 140 #: RegLna, the LNA gain and current. 141 LNA = _REGISTERS["lna"] 142 #: RegFifoAddrPtr, where the next RegFifo access lands. 143 FIFO_ADDR_PTR = _REGISTERS["fifoAddrPtr"] 144 #: RegFifoTxBaseAddr, where a transmitted payload starts. 145 FIFO_TX_BASE_ADDR = _REGISTERS["fifoTxBaseAddr"] 146 #: RegFifoRxBaseAddr, where received payloads start. 147 FIFO_RX_BASE_ADDR = _REGISTERS["fifoRxBaseAddr"] 148 #: RegFifoRxCurrentAddr, where the last received packet starts. 149 FIFO_RX_CURRENT_ADDR = _REGISTERS["fifoRxCurrentAddr"] 150 #: RegIrqFlagsMask, the interrupts masked off. 151 IRQ_FLAGS_MASK = _REGISTERS["irqFlagsMask"] 152 #: RegIrqFlags, the interrupts raised, each cleared by writing it back as a 1. 153 IRQ_FLAGS = _REGISTERS["irqFlags"] 154 #: RegRxNbBytes, the payload length of the last packet received. 155 RX_NB_BYTES = _REGISTERS["rxNbBytes"] 156 #: RegModemStat, the live state of the modem. 157 MODEM_STAT = _REGISTERS["modemStat"] 158 #: RegPktSnrValue, the SNR of the last packet in quarters of a decibel. 159 PKT_SNR_VALUE = _REGISTERS["pktSnrValue"] 160 #: RegPktRssiValue, the RSSI of the last packet. 161 PKT_RSSI_VALUE = _REGISTERS["pktRssiValue"] 162 #: RegRssiValue, the RSSI the receiver hears right now. 163 RSSI_VALUE = _REGISTERS["rssiValue"] 164 #: RegHopChannel, the PLL lock and the CRC the last header announced. 165 HOP_CHANNEL = _REGISTERS["hopChannel"] 166 #: RegModemConfig1: bandwidth, coding rate, and header mode. 167 MODEM_CONFIG_1 = _REGISTERS["modemConfig1"] 168 #: RegModemConfig2: spreading factor, CRC, and the top bits of the symbol timeout. 169 MODEM_CONFIG_2 = _REGISTERS["modemConfig2"] 170 #: RegSymbTimeoutLsb, the low byte of the symbol timeout. 171 SYMB_TIMEOUT_LSB = _REGISTERS["symbTimeoutLsb"] 172 #: RegPreambleMsb, the high byte of the preamble length. 173 PREAMBLE_MSB = _REGISTERS["preambleMsb"] 174 #: RegPreambleLsb, the low byte of the preamble length. 175 PREAMBLE_LSB = _REGISTERS["preambleLsb"] 176 #: RegPayloadLength, the payload length to send. 177 PAYLOAD_LENGTH = _REGISTERS["payloadLength"] 178 #: RegMaxPayloadLength, the longest payload a received header may announce. 179 MAX_PAYLOAD_LENGTH = _REGISTERS["maxPayloadLength"] 180 #: RegModemConfig3: low data rate optimization and the automatic gain control. 181 MODEM_CONFIG_3 = _REGISTERS["modemConfig3"] 182 #: RegRssiWideband, a wideband RSSI sample. 183 RSSI_WIDEBAND = _REGISTERS["rssiWideband"] 184 #: RegIfFreq2, which the spurious reception erratum sets. 185 IF_FREQ_2 = _REGISTERS["ifFreq2"] 186 #: RegIfFreq1, which the spurious reception erratum clears. 187 IF_FREQ_1 = _REGISTERS["ifFreq1"] 188 #: RegDetectOptimize: the automatic IF and the detection optimization. 189 DETECT_OPTIMIZE = _REGISTERS["detectOptimize"] 190 #: RegInvertIQ, the IQ polarity of each path. 191 INVERT_IQ = _REGISTERS["invertIq"] 192 #: RegHighBwOptimize1, which the 500 kHz erratum sets. 193 HIGH_BW_OPTIMIZE_1 = _REGISTERS["highBwOptimize1"] 194 #: RegDetectionThreshold, the LoRa detection threshold. 195 DETECTION_THRESHOLD = _REGISTERS["detectionThreshold"] 196 #: RegSyncWord, the LoRa sync word. 197 SYNC_WORD = _REGISTERS["syncWord"] 198 #: RegHighBwOptimize2, which the 500 kHz erratum sets. 199 HIGH_BW_OPTIMIZE_2 = _REGISTERS["highBwOptimize2"] 200 #: RegInvertIQ2, which completes an IQ inversion. 201 INVERT_IQ_2 = _REGISTERS["invertIq2"] 202 #: RegImageCal, at the address of RegInvertIQ2 on the FSK page. 203 IMAGE_CAL = _REGISTERS["imageCal"] 204 #: RegDioMapping1, the events DIO0 to DIO3 signal. 205 DIO_MAPPING_1 = _REGISTERS["dioMapping1"] 206 #: RegDioMapping2, the events DIO4 and DIO5 signal. 207 DIO_MAPPING_2 = _REGISTERS["dioMapping2"] 208 #: RegVersion, the silicon revision. 209 VERSION = _REGISTERS["version"] 210 #: RegTcxo, a crystal or a TCXO on XTA. 211 TCXO = _REGISTERS["tcxo"] 212 #: RegPaDac, the +20 dBm setting of PA_BOOST. 213 PA_DAC = _REGISTERS["paDac"] 214 215 216class Dio0(IntEnum): 217 """The RegDioMapping1 values that route an event to DIO0, from Table 18 of the datasheet.""" 218 219 #: DIO0 signals RxDone. 220 RX_DONE = _CONSTANTS["dio0RxDone"] 221 #: DIO0 signals TxDone. 222 TX_DONE = _CONSTANTS["dio0TxDone"] 223 #: DIO0 signals CadDone. 224 CAD_DONE = _CONSTANTS["dio0CadDone"] 225 226 227class Irq(IntFlag): 228 """The LoRa interrupt flags of RegIrqFlags.""" 229 230 #: A single reception timed out before a preamble arrived. 231 RX_TIMEOUT = _IRQ_FLAGS["rxTimeout"] 232 #: A packet has been received. 233 RX_DONE = _IRQ_FLAGS["rxDone"] 234 #: The payload failed its CRC. 235 PAYLOAD_CRC_ERROR = _IRQ_FLAGS["payloadCrcError"] 236 #: A valid header was received. 237 VALID_HEADER = _IRQ_FLAGS["validHeader"] 238 #: The payload has been transmitted. 239 TX_DONE = _IRQ_FLAGS["txDone"] 240 #: Channel activity detection finished. 241 CAD_DONE = _IRQ_FLAGS["cadDone"] 242 #: Frequency hopping moved to the next channel. 243 FHSS_CHANGE_CHANNEL = _IRQ_FLAGS["fhssChangeChannel"] 244 #: Channel activity detection heard a LoRa signal. 245 CAD_DETECTED = _IRQ_FLAGS["cadDetected"] 246 247 248class PaOutput(str, Enum): 249 """The amplifier output a module wires to its antenna. 250 251 The SPI interface cannot see which output a module uses, so the caller names it. 252 """ 253 254 #: The high efficiency amplifier on RFO_LF or RFO_HF, -4 to +15 dBm. 255 RFO = "Rfo" 256 #: The regulated amplifier on PA_BOOST, +2 to +20 dBm, as on the RFM95W. 257 PA_BOOST = "PaBoost" 258 259 260class Mode(str, Enum): 261 """The operating modes of RegOpMode.""" 262 263 #: Only the SPI interface and the registers are powered; the only mode that may switch modems. 264 SLEEP = "Sleep" 265 #: The oscillator and the baseband are on. 266 STANDBY = "Standby" 267 #: The PLL is locked for transmit. 268 FS_TX = "FsTx" 269 #: One packet goes out, then the chip returns to standby. 270 TX = "Tx" 271 #: The PLL is locked for receive. 272 FS_RX = "FsRx" 273 #: The receiver takes packet after packet. 274 RX_CONTINUOUS = "RxContinuous" 275 #: The receiver waits for one packet or the symbol timeout. 276 RX_SINGLE = "RxSingle" 277 #: Channel activity detection looks for a LoRa preamble. 278 CAD = "Cad" 279 280 281def frequency_word(frequency_hz: int) -> int: 282 """Return the 24-bit RegFrf word for a frequency. 283 284 :param frequency_hz: The carrier frequency in hertz. 285 :returns: The frequency times 2^19 over the 32 MHz crystal, rounded to the nearest step. 286 287 >>> hex(frequency_word(868_100_000)) 288 '0xd90666' 289 """ 290 return _frequency_word(frequency_hz) 291 292 293def frequency_from_word(word: int) -> int: 294 """Return the frequency a RegFrf word selects. 295 296 :param word: The 24-bit frequency word. 297 :returns: The carrier frequency in hertz. 298 """ 299 return _frequency_from_word(word) 300 301 302def read_address(address: int) -> int: 303 """Return the address byte that reads a register. 304 305 :param address: The register address. 306 :returns: The address with the write bit clear. 307 """ 308 return _read_address(address) 309 310 311def write_address(address: int) -> int: 312 """Return the address byte that writes a register. 313 314 :param address: The register address. 315 :returns: The address with the write bit set. 316 """ 317 return _write_address(address) 318 319 320def lora_op_mode(mode: Mode | str) -> int: 321 """Return the RegOpMode value for a LoRa operating mode. 322 323 :param mode: The operating mode. 324 :returns: The register value, with the LoRa register page selected. 325 :raises ValueError: If no mode goes by that name. 326 """ 327 return _lora_op_mode(Mode(mode).value) 328 329 330def fsk_op_mode(mode: Mode | str) -> int: 331 """Return the RegOpMode value for an FSK operating mode, which image calibration needs. 332 333 :param mode: The operating mode. 334 :returns: The register value. 335 :raises ValueError: If no mode goes by that name. 336 """ 337 return _fsk_op_mode(Mode(mode).value) 338 339 340def mode_from_op_mode(op_mode: int) -> Mode: 341 """Return the operating mode a RegOpMode value holds. 342 343 :param op_mode: The register value. 344 :returns: The mode. 345 """ 346 return Mode(_mode_from_op_mode(op_mode)) 347 348 349def modem(link: LoraLink, frequency_hz: int, symbol_timeout: int = 0) -> Modem: 350 """Return the LoRa modem registers for a link at a carrier. 351 352 :param link: The link settings. 353 :param frequency_hz: The carrier frequency, which rules out 250 and 500 kHz below 175 MHz. 354 :param symbol_timeout: A single reception timeout in symbols, whose top bits go in 355 RegModemConfig2. 356 :returns: RegModemConfig1 to 3 and the SF6 detection settings. 357 :raises PamojaError: If the SX127x cannot use the link at the carrier. 358 """ 359 return _modem(link, frequency_hz, symbol_timeout) 360 361 362def symbol_timeout(link: LoraLink, timeout_us: int) -> int: 363 """Return a single reception timeout in the link's symbols. 364 365 :param link: The link settings, whose symbol time counts the timeout. 366 :param timeout_us: How long to listen for a preamble, in microseconds. 367 :returns: The timeout rounded up to whole symbols, from 4 to 1023. 368 """ 369 return _symbol_timeout(link, timeout_us) 370 371 372def tx_power(output: PaOutput | str, output_dbm: int) -> TxPower: 373 """Choose the amplifier settings for an output power. 374 375 :param output: The amplifier output the module uses. 376 :param output_dbm: The output power wanted, in dBm. 377 :returns: The settings, clamped to what the output delivers. 378 :raises ValueError: If no output goes by that name. 379 """ 380 return _tx_power(PaOutput(output).value, output_dbm) 381 382 383def tx_power_under_ceiling( 384 output: PaOutput | str, budget: LinkBudget, eirp_ceiling_dbm: float 385) -> TxPower: 386 """Choose the amplifier settings that keep a link's EIRP at or under a ceiling. 387 388 :param output: The amplifier output the module uses. 389 :param budget: The link budget, whose transmitting antenna and cable apply. 390 :param eirp_ceiling_dbm: The EIRP limit in dBm. 391 :returns: The settings, rounded down to whole decibels. 392 :raises ValueError: If no output goes by that name. 393 """ 394 return _tx_power_under_ceiling(PaOutput(output).value, budget, eirp_ceiling_dbm) 395 396 397def ocp_register(milliamps: int) -> int: 398 """Return RegOcp for a current limit. 399 400 :param milliamps: The most current the amplifier may draw. 401 :returns: The register value with the protection on. 402 """ 403 return _ocp_register(milliamps) 404 405 406def invert_iq(receive: bool, transmit: bool) -> int: 407 """Return RegInvertIQ for the IQ polarity of each path. 408 409 :param receive: Whether to invert the receive path, as a LoRaWAN device does for downlinks. 410 :param transmit: Whether to invert the transmit path, as a gateway does. 411 :returns: The register value, with the transmit bit set for normal IQ as the reference 412 drivers have it. 413 """ 414 return _invert_iq(receive, transmit) 415 416 417def invert_iq_2(inverted: bool) -> int: 418 """Return RegInvertIQ2 for the path in use. 419 420 :param inverted: Whether that path is inverted. 421 :returns: 0x19 when inverted, else 0x1D. 422 """ 423 return _invert_iq_2(inverted) 424 425 426def high_bw_optimize(link: LoraLink, frequency_hz: int) -> HighBwOptimize: 427 """Return the writes of the 500 kHz sensitivity erratum. 428 429 :param link: The link settings, whose bandwidth decides. 430 :param frequency_hz: The carrier frequency in hertz. 431 :returns: RegHighBwOptimize1 and, where it is written, RegHighBwOptimize2. 432 :raises PamojaError: If the SX127x has no such bandwidth. 433 """ 434 return _high_bw_optimize(link, frequency_hz) 435 436 437def spurious_reception(link: LoraLink) -> SpuriousReception: 438 """Return the receive settings of the spurious reception erratum. 439 440 :param link: The link settings, whose bandwidth decides. 441 :returns: The automatic IF, the hand-set IF, and the carrier offset. 442 :raises PamojaError: If the SX127x has no such bandwidth. 443 """ 444 return _spurious_reception(link) 445 446 447def image_cal_start(current: int) -> int: 448 """Return RegImageCal to start a calibration. 449 450 :param current: The register's current value. 451 :returns: The value with ImageCalStart set and AutoImageCalOn clear. 452 """ 453 return _image_cal_start(current) 454 455 456def automatic_if(current: int, on: bool) -> int: 457 """Return RegDetectOptimize with AutomaticIFOn set or clear. 458 459 :param current: The register's current value. 460 :param on: Whether the automatic IF stays on. 461 :returns: The register value. 462 """ 463 return _automatic_if(current, on) 464 465 466def packet_status(answer: bytes, frequency_hz: int) -> PacketStatus: 467 """Decode RegPktSnrValue and RegPktRssiValue, read together. 468 469 :param answer: The two register values, SNR first. 470 :param frequency_hz: The carrier the packet was heard at, which picks the RF port's offset. 471 :returns: The three signal levels, exact to a hundredth of a decibel. 472 :raises ValueError: If the answer is not two bytes. 473 """ 474 return _packet_status(bytes(answer), frequency_hz) 475 476 477def rssi_dbm(byte: int, frequency_hz: int) -> float: 478 """Decode RegRssiValue. 479 480 :param byte: The register value. 481 :param frequency_hz: The carrier the receiver is tuned to. 482 :returns: The signal power the receiver hears right now, in dBm. 483 """ 484 return _rssi_dbm(byte, frequency_hz) 485 486 487def modem_status(byte: int) -> ModemStatus: 488 """Decode RegModemStat. 489 490 :param byte: The register value. 491 :returns: The modem's live state. 492 """ 493 return _modem_status(byte)
217class Dio0(IntEnum): 218 """The RegDioMapping1 values that route an event to DIO0, from Table 18 of the datasheet.""" 219 220 #: DIO0 signals RxDone. 221 RX_DONE = _CONSTANTS["dio0RxDone"] 222 #: DIO0 signals TxDone. 223 TX_DONE = _CONSTANTS["dio0TxDone"] 224 #: DIO0 signals CadDone. 225 CAD_DONE = _CONSTANTS["dio0CadDone"]
The RegDioMapping1 values that route an event to DIO0, from Table 18 of the datasheet.
228class Irq(IntFlag): 229 """The LoRa interrupt flags of RegIrqFlags.""" 230 231 #: A single reception timed out before a preamble arrived. 232 RX_TIMEOUT = _IRQ_FLAGS["rxTimeout"] 233 #: A packet has been received. 234 RX_DONE = _IRQ_FLAGS["rxDone"] 235 #: The payload failed its CRC. 236 PAYLOAD_CRC_ERROR = _IRQ_FLAGS["payloadCrcError"] 237 #: A valid header was received. 238 VALID_HEADER = _IRQ_FLAGS["validHeader"] 239 #: The payload has been transmitted. 240 TX_DONE = _IRQ_FLAGS["txDone"] 241 #: Channel activity detection finished. 242 CAD_DONE = _IRQ_FLAGS["cadDone"] 243 #: Frequency hopping moved to the next channel. 244 FHSS_CHANGE_CHANNEL = _IRQ_FLAGS["fhssChangeChannel"] 245 #: Channel activity detection heard a LoRa signal. 246 CAD_DETECTED = _IRQ_FLAGS["cadDetected"]
The LoRa interrupt flags of RegIrqFlags.
261class Mode(str, Enum): 262 """The operating modes of RegOpMode.""" 263 264 #: Only the SPI interface and the registers are powered; the only mode that may switch modems. 265 SLEEP = "Sleep" 266 #: The oscillator and the baseband are on. 267 STANDBY = "Standby" 268 #: The PLL is locked for transmit. 269 FS_TX = "FsTx" 270 #: One packet goes out, then the chip returns to standby. 271 TX = "Tx" 272 #: The PLL is locked for receive. 273 FS_RX = "FsRx" 274 #: The receiver takes packet after packet. 275 RX_CONTINUOUS = "RxContinuous" 276 #: The receiver waits for one packet or the symbol timeout. 277 RX_SINGLE = "RxSingle" 278 #: Channel activity detection looks for a LoRa preamble. 279 CAD = "Cad"
The operating modes of RegOpMode.
249class PaOutput(str, Enum): 250 """The amplifier output a module wires to its antenna. 251 252 The SPI interface cannot see which output a module uses, so the caller names it. 253 """ 254 255 #: The high efficiency amplifier on RFO_LF or RFO_HF, -4 to +15 dBm. 256 RFO = "Rfo" 257 #: The regulated amplifier on PA_BOOST, +2 to +20 dBm, as on the RFM95W. 258 PA_BOOST = "PaBoost"
The amplifier output a module wires to its antenna.
The SPI interface cannot see which output a module uses, so the caller names it.
122class Register(IntEnum): 123 """The register addresses, from Table 41 of the datasheet with the LoRa page selected.""" 124 125 #: RegFifo, the LoRa data buffer, read or written at RegFifoAddrPtr. 126 FIFO = _REGISTERS["fifo"] 127 #: RegOpMode: LoRa or FSK, the register page, and the operating mode. 128 OP_MODE = _REGISTERS["opMode"] 129 #: RegFrfMsb, the top byte of the carrier word. 130 FRF_MSB = _REGISTERS["frfMsb"] 131 #: RegFrfMid, the middle byte of the carrier word. 132 FRF_MID = _REGISTERS["frfMid"] 133 #: RegFrfLsb, the low byte of the carrier word. 134 FRF_LSB = _REGISTERS["frfLsb"] 135 #: RegPaConfig: the amplifier output, its maximum, and the power. 136 PA_CONFIG = _REGISTERS["paConfig"] 137 #: RegPaRamp, the amplifier ramp time. 138 PA_RAMP = _REGISTERS["paRamp"] 139 #: RegOcp, the amplifier current limit. 140 OCP = _REGISTERS["ocp"] 141 #: RegLna, the LNA gain and current. 142 LNA = _REGISTERS["lna"] 143 #: RegFifoAddrPtr, where the next RegFifo access lands. 144 FIFO_ADDR_PTR = _REGISTERS["fifoAddrPtr"] 145 #: RegFifoTxBaseAddr, where a transmitted payload starts. 146 FIFO_TX_BASE_ADDR = _REGISTERS["fifoTxBaseAddr"] 147 #: RegFifoRxBaseAddr, where received payloads start. 148 FIFO_RX_BASE_ADDR = _REGISTERS["fifoRxBaseAddr"] 149 #: RegFifoRxCurrentAddr, where the last received packet starts. 150 FIFO_RX_CURRENT_ADDR = _REGISTERS["fifoRxCurrentAddr"] 151 #: RegIrqFlagsMask, the interrupts masked off. 152 IRQ_FLAGS_MASK = _REGISTERS["irqFlagsMask"] 153 #: RegIrqFlags, the interrupts raised, each cleared by writing it back as a 1. 154 IRQ_FLAGS = _REGISTERS["irqFlags"] 155 #: RegRxNbBytes, the payload length of the last packet received. 156 RX_NB_BYTES = _REGISTERS["rxNbBytes"] 157 #: RegModemStat, the live state of the modem. 158 MODEM_STAT = _REGISTERS["modemStat"] 159 #: RegPktSnrValue, the SNR of the last packet in quarters of a decibel. 160 PKT_SNR_VALUE = _REGISTERS["pktSnrValue"] 161 #: RegPktRssiValue, the RSSI of the last packet. 162 PKT_RSSI_VALUE = _REGISTERS["pktRssiValue"] 163 #: RegRssiValue, the RSSI the receiver hears right now. 164 RSSI_VALUE = _REGISTERS["rssiValue"] 165 #: RegHopChannel, the PLL lock and the CRC the last header announced. 166 HOP_CHANNEL = _REGISTERS["hopChannel"] 167 #: RegModemConfig1: bandwidth, coding rate, and header mode. 168 MODEM_CONFIG_1 = _REGISTERS["modemConfig1"] 169 #: RegModemConfig2: spreading factor, CRC, and the top bits of the symbol timeout. 170 MODEM_CONFIG_2 = _REGISTERS["modemConfig2"] 171 #: RegSymbTimeoutLsb, the low byte of the symbol timeout. 172 SYMB_TIMEOUT_LSB = _REGISTERS["symbTimeoutLsb"] 173 #: RegPreambleMsb, the high byte of the preamble length. 174 PREAMBLE_MSB = _REGISTERS["preambleMsb"] 175 #: RegPreambleLsb, the low byte of the preamble length. 176 PREAMBLE_LSB = _REGISTERS["preambleLsb"] 177 #: RegPayloadLength, the payload length to send. 178 PAYLOAD_LENGTH = _REGISTERS["payloadLength"] 179 #: RegMaxPayloadLength, the longest payload a received header may announce. 180 MAX_PAYLOAD_LENGTH = _REGISTERS["maxPayloadLength"] 181 #: RegModemConfig3: low data rate optimization and the automatic gain control. 182 MODEM_CONFIG_3 = _REGISTERS["modemConfig3"] 183 #: RegRssiWideband, a wideband RSSI sample. 184 RSSI_WIDEBAND = _REGISTERS["rssiWideband"] 185 #: RegIfFreq2, which the spurious reception erratum sets. 186 IF_FREQ_2 = _REGISTERS["ifFreq2"] 187 #: RegIfFreq1, which the spurious reception erratum clears. 188 IF_FREQ_1 = _REGISTERS["ifFreq1"] 189 #: RegDetectOptimize: the automatic IF and the detection optimization. 190 DETECT_OPTIMIZE = _REGISTERS["detectOptimize"] 191 #: RegInvertIQ, the IQ polarity of each path. 192 INVERT_IQ = _REGISTERS["invertIq"] 193 #: RegHighBwOptimize1, which the 500 kHz erratum sets. 194 HIGH_BW_OPTIMIZE_1 = _REGISTERS["highBwOptimize1"] 195 #: RegDetectionThreshold, the LoRa detection threshold. 196 DETECTION_THRESHOLD = _REGISTERS["detectionThreshold"] 197 #: RegSyncWord, the LoRa sync word. 198 SYNC_WORD = _REGISTERS["syncWord"] 199 #: RegHighBwOptimize2, which the 500 kHz erratum sets. 200 HIGH_BW_OPTIMIZE_2 = _REGISTERS["highBwOptimize2"] 201 #: RegInvertIQ2, which completes an IQ inversion. 202 INVERT_IQ_2 = _REGISTERS["invertIq2"] 203 #: RegImageCal, at the address of RegInvertIQ2 on the FSK page. 204 IMAGE_CAL = _REGISTERS["imageCal"] 205 #: RegDioMapping1, the events DIO0 to DIO3 signal. 206 DIO_MAPPING_1 = _REGISTERS["dioMapping1"] 207 #: RegDioMapping2, the events DIO4 and DIO5 signal. 208 DIO_MAPPING_2 = _REGISTERS["dioMapping2"] 209 #: RegVersion, the silicon revision. 210 VERSION = _REGISTERS["version"] 211 #: RegTcxo, a crystal or a TCXO on XTA. 212 TCXO = _REGISTERS["tcxo"] 213 #: RegPaDac, the +20 dBm setting of PA_BOOST. 214 PA_DAC = _REGISTERS["paDac"]
The register addresses, from Table 41 of the datasheet with the LoRa page selected.
457def automatic_if(current: int, on: bool) -> int: 458 """Return RegDetectOptimize with AutomaticIFOn set or clear. 459 460 :param current: The register's current value. 461 :param on: Whether the automatic IF stays on. 462 :returns: The register value. 463 """ 464 return _automatic_if(current, on)
Return RegDetectOptimize with AutomaticIFOn set or clear.
Parameters
- current: The register's current value.
- on: Whether the automatic IF stays on. :returns: The register value.
294def frequency_from_word(word: int) -> int: 295 """Return the frequency a RegFrf word selects. 296 297 :param word: The 24-bit frequency word. 298 :returns: The carrier frequency in hertz. 299 """ 300 return _frequency_from_word(word)
Return the frequency a RegFrf word selects.
Parameters
- word: The 24-bit frequency word. :returns: The carrier frequency in hertz.
282def frequency_word(frequency_hz: int) -> int: 283 """Return the 24-bit RegFrf word for a frequency. 284 285 :param frequency_hz: The carrier frequency in hertz. 286 :returns: The frequency times 2^19 over the 32 MHz crystal, rounded to the nearest step. 287 288 >>> hex(frequency_word(868_100_000)) 289 '0xd90666' 290 """ 291 return _frequency_word(frequency_hz)
Return the 24-bit RegFrf word for a frequency.
Parameters
- frequency_hz: The carrier frequency in hertz. :returns: The frequency times 2^19 over the 32 MHz crystal, rounded to the nearest step.
>>> hex(frequency_word(868_100_000))
'0xd90666'
331def fsk_op_mode(mode: Mode | str) -> int: 332 """Return the RegOpMode value for an FSK operating mode, which image calibration needs. 333 334 :param mode: The operating mode. 335 :returns: The register value. 336 :raises ValueError: If no mode goes by that name. 337 """ 338 return _fsk_op_mode(Mode(mode).value)
Return the RegOpMode value for an FSK operating mode, which image calibration needs.
Parameters
- mode: The operating mode. :returns: The register value.
Raises
- ValueError: If no mode goes by that name.
427def high_bw_optimize(link: LoraLink, frequency_hz: int) -> HighBwOptimize: 428 """Return the writes of the 500 kHz sensitivity erratum. 429 430 :param link: The link settings, whose bandwidth decides. 431 :param frequency_hz: The carrier frequency in hertz. 432 :returns: RegHighBwOptimize1 and, where it is written, RegHighBwOptimize2. 433 :raises PamojaError: If the SX127x has no such bandwidth. 434 """ 435 return _high_bw_optimize(link, frequency_hz)
Return the writes of the 500 kHz sensitivity erratum.
Parameters
- link: The link settings, whose bandwidth decides.
- frequency_hz: The carrier frequency in hertz. :returns: RegHighBwOptimize1 and, where it is written, RegHighBwOptimize2.
Raises
- PamojaError: If the SX127x has no such bandwidth.
448def image_cal_start(current: int) -> int: 449 """Return RegImageCal to start a calibration. 450 451 :param current: The register's current value. 452 :returns: The value with ImageCalStart set and AutoImageCalOn clear. 453 """ 454 return _image_cal_start(current)
Return RegImageCal to start a calibration.
Parameters
- current: The register's current value. :returns: The value with ImageCalStart set and AutoImageCalOn clear.
407def invert_iq(receive: bool, transmit: bool) -> int: 408 """Return RegInvertIQ for the IQ polarity of each path. 409 410 :param receive: Whether to invert the receive path, as a LoRaWAN device does for downlinks. 411 :param transmit: Whether to invert the transmit path, as a gateway does. 412 :returns: The register value, with the transmit bit set for normal IQ as the reference 413 drivers have it. 414 """ 415 return _invert_iq(receive, transmit)
Return RegInvertIQ for the IQ polarity of each path.
Parameters
- receive: Whether to invert the receive path, as a LoRaWAN device does for downlinks.
- transmit: Whether to invert the transmit path, as a gateway does. :returns: The register value, with the transmit bit set for normal IQ as the reference drivers have it.
418def invert_iq_2(inverted: bool) -> int: 419 """Return RegInvertIQ2 for the path in use. 420 421 :param inverted: Whether that path is inverted. 422 :returns: 0x19 when inverted, else 0x1D. 423 """ 424 return _invert_iq_2(inverted)
Return RegInvertIQ2 for the path in use.
Parameters
- inverted: Whether that path is inverted. :returns: 0x19 when inverted, else 0x1D.
321def lora_op_mode(mode: Mode | str) -> int: 322 """Return the RegOpMode value for a LoRa operating mode. 323 324 :param mode: The operating mode. 325 :returns: The register value, with the LoRa register page selected. 326 :raises ValueError: If no mode goes by that name. 327 """ 328 return _lora_op_mode(Mode(mode).value)
Return the RegOpMode value for a LoRa operating mode.
Parameters
- mode: The operating mode. :returns: The register value, with the LoRa register page selected.
Raises
- ValueError: If no mode goes by that name.
341def mode_from_op_mode(op_mode: int) -> Mode: 342 """Return the operating mode a RegOpMode value holds. 343 344 :param op_mode: The register value. 345 :returns: The mode. 346 """ 347 return Mode(_mode_from_op_mode(op_mode))
Return the operating mode a RegOpMode value holds.
Parameters
- op_mode: The register value. :returns: The mode.
350def modem(link: LoraLink, frequency_hz: int, symbol_timeout: int = 0) -> Modem: 351 """Return the LoRa modem registers for a link at a carrier. 352 353 :param link: The link settings. 354 :param frequency_hz: The carrier frequency, which rules out 250 and 500 kHz below 175 MHz. 355 :param symbol_timeout: A single reception timeout in symbols, whose top bits go in 356 RegModemConfig2. 357 :returns: RegModemConfig1 to 3 and the SF6 detection settings. 358 :raises PamojaError: If the SX127x cannot use the link at the carrier. 359 """ 360 return _modem(link, frequency_hz, symbol_timeout)
Return the LoRa modem registers for a link at a carrier.
Parameters
- link: The link settings.
- frequency_hz: The carrier frequency, which rules out 250 and 500 kHz below 175 MHz.
- symbol_timeout: A single reception timeout in symbols, whose top bits go in RegModemConfig2. :returns: RegModemConfig1 to 3 and the SF6 detection settings.
Raises
- PamojaError: If the SX127x cannot use the link at the carrier.
488def modem_status(byte: int) -> ModemStatus: 489 """Decode RegModemStat. 490 491 :param byte: The register value. 492 :returns: The modem's live state. 493 """ 494 return _modem_status(byte)
Decode RegModemStat.
Parameters
- byte: The register value. :returns: The modem's live state.
398def ocp_register(milliamps: int) -> int: 399 """Return RegOcp for a current limit. 400 401 :param milliamps: The most current the amplifier may draw. 402 :returns: The register value with the protection on. 403 """ 404 return _ocp_register(milliamps)
Return RegOcp for a current limit.
Parameters
- milliamps: The most current the amplifier may draw. :returns: The register value with the protection on.
467def packet_status(answer: bytes, frequency_hz: int) -> PacketStatus: 468 """Decode RegPktSnrValue and RegPktRssiValue, read together. 469 470 :param answer: The two register values, SNR first. 471 :param frequency_hz: The carrier the packet was heard at, which picks the RF port's offset. 472 :returns: The three signal levels, exact to a hundredth of a decibel. 473 :raises ValueError: If the answer is not two bytes. 474 """ 475 return _packet_status(bytes(answer), frequency_hz)
Decode RegPktSnrValue and RegPktRssiValue, read together.
Parameters
- answer: The two register values, SNR first.
- frequency_hz: The carrier the packet was heard at, which picks the RF port's offset. :returns: The three signal levels, exact to a hundredth of a decibel.
Raises
- ValueError: If the answer is not two bytes.
303def read_address(address: int) -> int: 304 """Return the address byte that reads a register. 305 306 :param address: The register address. 307 :returns: The address with the write bit clear. 308 """ 309 return _read_address(address)
Return the address byte that reads a register.
Parameters
- address: The register address. :returns: The address with the write bit clear.
478def rssi_dbm(byte: int, frequency_hz: int) -> float: 479 """Decode RegRssiValue. 480 481 :param byte: The register value. 482 :param frequency_hz: The carrier the receiver is tuned to. 483 :returns: The signal power the receiver hears right now, in dBm. 484 """ 485 return _rssi_dbm(byte, frequency_hz)
Decode RegRssiValue.
Parameters
- byte: The register value.
- frequency_hz: The carrier the receiver is tuned to. :returns: The signal power the receiver hears right now, in dBm.
438def spurious_reception(link: LoraLink) -> SpuriousReception: 439 """Return the receive settings of the spurious reception erratum. 440 441 :param link: The link settings, whose bandwidth decides. 442 :returns: The automatic IF, the hand-set IF, and the carrier offset. 443 :raises PamojaError: If the SX127x has no such bandwidth. 444 """ 445 return _spurious_reception(link)
Return the receive settings of the spurious reception erratum.
Parameters
- link: The link settings, whose bandwidth decides. :returns: The automatic IF, the hand-set IF, and the carrier offset.
Raises
- PamojaError: If the SX127x has no such bandwidth.
363def symbol_timeout(link: LoraLink, timeout_us: int) -> int: 364 """Return a single reception timeout in the link's symbols. 365 366 :param link: The link settings, whose symbol time counts the timeout. 367 :param timeout_us: How long to listen for a preamble, in microseconds. 368 :returns: The timeout rounded up to whole symbols, from 4 to 1023. 369 """ 370 return _symbol_timeout(link, timeout_us)
Return a single reception timeout in the link's symbols.
Parameters
- link: The link settings, whose symbol time counts the timeout.
- timeout_us: How long to listen for a preamble, in microseconds. :returns: The timeout rounded up to whole symbols, from 4 to 1023.
373def tx_power(output: PaOutput | str, output_dbm: int) -> TxPower: 374 """Choose the amplifier settings for an output power. 375 376 :param output: The amplifier output the module uses. 377 :param output_dbm: The output power wanted, in dBm. 378 :returns: The settings, clamped to what the output delivers. 379 :raises ValueError: If no output goes by that name. 380 """ 381 return _tx_power(PaOutput(output).value, output_dbm)
Choose the amplifier settings for an output power.
Parameters
- output: The amplifier output the module uses.
- output_dbm: The output power wanted, in dBm. :returns: The settings, clamped to what the output delivers.
Raises
- ValueError: If no output goes by that name.
384def tx_power_under_ceiling( 385 output: PaOutput | str, budget: LinkBudget, eirp_ceiling_dbm: float 386) -> TxPower: 387 """Choose the amplifier settings that keep a link's EIRP at or under a ceiling. 388 389 :param output: The amplifier output the module uses. 390 :param budget: The link budget, whose transmitting antenna and cable apply. 391 :param eirp_ceiling_dbm: The EIRP limit in dBm. 392 :returns: The settings, rounded down to whole decibels. 393 :raises ValueError: If no output goes by that name. 394 """ 395 return _tx_power_under_ceiling(PaOutput(output).value, budget, eirp_ceiling_dbm)
Choose the amplifier settings that keep a link's EIRP at or under a ceiling.
Parameters
- output: The amplifier output the module uses.
- budget: The link budget, whose transmitting antenna and cable apply.
- eirp_ceiling_dbm: The EIRP limit in dBm. :returns: The settings, rounded down to whole decibels.
Raises
- ValueError: If no output goes by that name.
312def write_address(address: int) -> int: 313 """Return the address byte that writes a register. 314 315 :param address: The register address. 316 :returns: The address with the write bit set. 317 """ 318 return _write_address(address)
Return the address byte that writes a register.
Parameters
- address: The register address. :returns: The address with the write bit set.