tinygo.org/x/drivers@v0.27.1-0.20240509133757-7dbca2a54349/sx126x/sx126x.go (about) 1 // Package sx126x provides a driver for SX126x LoRa transceivers. 2 // Inspired from https://github.com/Lora-net/sx126x_driver/ 3 4 package sx126x 5 6 import ( 7 "errors" 8 "time" 9 10 "machine" 11 12 "tinygo.org/x/drivers" 13 "tinygo.org/x/drivers/lora" 14 ) 15 16 var ( 17 errWaitWhileBusyTimeout = errors.New("WaitWhileBusy Timeout") 18 errLowPowerTxNotSupported = errors.New("RFSWITCH_TX_LP not supported") 19 errRadioNotFound = errors.New("LoRa radio not found") 20 errUnexpectedRxRadioEvent = errors.New("Unexpected Radio Event during RX") 21 errUnexpectedTxRadioEvent = errors.New("Unexpected Radio Event during TX") 22 ) 23 24 const ( 25 DEVICE_TYPE_SX1261 = iota 26 DEVICE_TYPE_SX1262 = iota 27 DEVICE_TYPE_SX1268 = iota 28 ) 29 30 const ( 31 RFSWITCH_RX = iota 32 RFSWITCH_TX_LP = iota 33 RFSWITCH_TX_HP = iota 34 ) 35 36 const ( 37 PERIOD_PER_SEC = (uint32)(1000000 / 15.625) // SX1261 DS 13.1.4 38 SPI_BUFFER_SIZE = 256 39 RADIOEVENTCHAN_SIZE = 1 40 ) 41 42 // Device wraps an SPI connection to a SX126x device. 43 type Device struct { 44 spi drivers.SPI // SPI bus for module communication 45 rstPin machine.Pin // GPIO for reset pin 46 radioEventChan chan lora.RadioEvent // Channel for Receiving events 47 loraConf lora.Config // Current Lora configuration 48 controller RadioController // to manage interactions with the radio 49 deepSleep bool // Internal Sleep state 50 deviceType int // sx1261,sx1262,sx1268 (defaults sx1261) 51 spiTxBuf []byte // global Tx buffer to avoid heap allocations in interrupt 52 spiRxBuf []byte // global Rx buffer to avoid heap allocations in interrupt 53 54 } 55 56 // New creates a new SX126x connection. 57 func New(spi drivers.SPI) *Device { 58 return &Device{ 59 spi: spi, 60 radioEventChan: make(chan lora.RadioEvent, RADIOEVENTCHAN_SIZE), 61 spiTxBuf: make([]byte, SPI_BUFFER_SIZE), 62 spiRxBuf: make([]byte, SPI_BUFFER_SIZE), 63 } 64 } 65 66 const ( 67 SX126X_RTC_FREQ_IN_HZ uint32 = 64000 68 ) 69 70 // -------------------------------------------------- 71 // Helper functions 72 // -------------------------------------------------- 73 74 // timeoutMsToRtcSteps converts Timeout (in ms) to RTC Steps 75 func timeoutMsToRtcSteps(timeoutMs uint32) uint32 { 76 r := uint32(timeoutMs * (SX126X_RTC_FREQ_IN_HZ / 1000)) 77 return r 78 } 79 80 // -------------------------------------------------- 81 // 82 // Channel and events 83 // 84 // -------------------------------------------------- 85 // Get the RadioEvent channel of the device 86 func (d *Device) GetRadioEventChan() chan lora.RadioEvent { 87 return d.radioEventChan 88 } 89 90 // Specify device type (SX1261/2/8) 91 func (d *Device) SetDeviceType(devType int) { 92 d.deviceType = devType 93 } 94 95 // SetRadioControl let you define the RadioController 96 func (d *Device) SetRadioController(rc RadioController) error { 97 d.controller = rc 98 if err := d.controller.Init(); err != nil { 99 return err 100 } 101 d.controller.SetupInterrupts(d.HandleInterrupt) 102 103 return nil 104 } 105 106 // -------------------------------------------------- 107 // Operational modes functions 108 // -------------------------------------------------- 109 110 func (d *Device) Reset() { 111 d.rstPin.Low() 112 time.Sleep(100 * time.Millisecond) 113 d.rstPin.High() 114 time.Sleep(100 * time.Millisecond) 115 } 116 117 // DetectDevice() tries to detect the radio module by changing SyncWord value 118 func (d *Device) DetectDevice() bool { 119 bak := d.GetSyncWord() 120 d.SetSyncWord(0xBEEF) 121 tmp := d.GetSyncWord() 122 if tmp != 0xBEEF { 123 return false 124 } else { 125 d.SetSyncWord(bak) 126 return true 127 } 128 } 129 130 // SetSleep sets the device in SLEEP mode with the lowest current consumption possible. 131 func (d *Device) SetSleep() { 132 d.ExecSetCommand(SX126X_CMD_SET_SLEEP, []uint8{SX126X_SLEEP_START_WARM | SX126X_SLEEP_RTC_OFF}) 133 } 134 135 // SetStandby sets the device in a configuration mode which is at an intermediate level of consumption 136 func (d *Device) SetStandby() { 137 d.ExecSetCommand(SX126X_CMD_SET_STANDBY, []uint8{SX126X_STANDBY_RC}) 138 } 139 140 // SetFs sets the device in frequency synthesis mode where the PLL is locked to the carrier frequency. 141 func (d *Device) SetFs() { 142 d.ExecSetCommand(SX126X_CMD_SET_FS, []uint8{}) 143 } 144 145 // SetTxContinuousWave set device in test mode to generate a continuous wave (RF tone) 146 func (d *Device) SetTxContinuousWave() { 147 if d.controller != nil { 148 d.controller.SetRfSwitchMode(RFSWITCH_TX_HP) 149 } 150 d.ExecSetCommand(SX126X_CMD_SET_TX_CONTINUOUS_WAVE, []uint8{}) 151 } 152 153 // SetTxContinuousPreamble set device in test mode to constantly modulate LoRa preamble symbols. 154 // Take care to initialize all Lora settings like it's done in Tx before calling this function 155 // If you don't init properly all the settings, it'll fail 156 func (d *Device) SetTxContinuousPreamble() { 157 if d.controller != nil { 158 d.controller.SetRfSwitchMode(RFSWITCH_TX_HP) 159 } 160 d.ExecSetCommand(SX126X_CMD_SET_TX_INFINITE_PREAMBLE, []uint8{}) 161 } 162 163 // SetTx() sets the device in TX mode 164 // timeout is expressed in RTC Step unit (15uS) 165 // The device will stay in Tx until countdown or packet transmitted 166 // Value of 0x000000 will disable timer and device will stay TX 167 func (d *Device) SetTx(timeoutRtcStep uint32) { 168 var p [3]uint8 169 p[0] = uint8((timeoutRtcStep >> 16) & 0xFF) 170 p[1] = uint8((timeoutRtcStep >> 8) & 0xFF) 171 p[2] = uint8((timeoutRtcStep >> 0) & 0xFF) 172 d.ExecSetCommand(SX126X_CMD_SET_TX, p[:]) 173 } 174 175 // SetRx() sets the device in RX mode 176 // timeout is expressed in RTC Step unit (15uS) 177 // Value of 0x000000 => No timeout. Rx Single mode. 178 // Value of 0xffffff => Rx Continuous mode 179 // Other values => Timeout active. The device remains in RX until countdown or packet received 180 func (d *Device) SetRx(timeoutRtcStep uint32) { 181 var p [3]uint8 182 p[0] = uint8(((timeoutRtcStep >> 16) & 0xFF)) 183 p[1] = uint8(((timeoutRtcStep >> 8) & 0xFF)) 184 p[2] = uint8(((timeoutRtcStep >> 0) & 0xFF)) 185 d.ExecSetCommand(SX126X_CMD_SET_RX, p[:]) 186 } 187 188 // StopTimerOnPreamble allows the user to select if the timer is stopped upon preamble detection of SyncWord / header detection. 189 func (d *Device) StopTimerOnPreamble(enable bool) { 190 var p [1]uint8 191 if enable { 192 p[0] = 1 193 } else { 194 p[0] = 0 195 } 196 d.ExecSetCommand(SX126X_CMD_STOP_TIMER_ON_PREAMBLE, p[:]) 197 } 198 199 // SetRegulatorMode sets the regulator more (depends on hardware implementation) 200 func (d *Device) SetRegulatorMode(mode uint8) { 201 p := []uint8{mode} 202 d.ExecSetCommand(SX126X_CMD_SET_REGULATOR_MODE, p[:]) 203 } 204 205 // Calibrate starts the calibration of a block defined by calibParam 206 func (d *Device) Calibrate(calibParam uint8) { 207 p := []uint8{calibParam} 208 d.ExecSetCommand(SX126X_CMD_CALIBRATE, p[:]) 209 } 210 211 // CalibrateImage calibrates the image rejection of the device for the device operating 212 func (d *Device) CalibrateImage(freq uint32) { 213 var calFreq [2]uint8 214 if freq > 900000000 { 215 calFreq[0] = 0xE1 216 calFreq[1] = 0xE9 217 } else if freq > 850000000 { 218 calFreq[0] = 0xD7 219 calFreq[1] = 0xD8 220 } else if freq > 770000000 { 221 calFreq[0] = 0xC1 222 calFreq[1] = 0xC5 223 } else if freq > 460000000 { 224 calFreq[0] = 0x75 225 calFreq[1] = 0x81 226 } else if freq > 425000000 { 227 calFreq[0] = 0x6B 228 calFreq[1] = 0x6F 229 } 230 d.ExecSetCommand(SX126X_CMD_CALIBRATE_IMAGE, calFreq[:]) 231 } 232 233 // SetPaConfig sets the Power Amplifier configuration 234 // deviceSel: 0 for SX1262, 1 for SX1261 235 func (d *Device) SetPaConfig(paDutyCycle, hpMax, deviceSel, paLut uint8) { 236 var p [4]uint8 237 p[0] = paDutyCycle 238 p[1] = hpMax 239 p[2] = deviceSel 240 p[3] = paLut 241 d.ExecSetCommand(SX126X_CMD_SET_PA_CONFIG, p[:]) 242 } 243 244 // SetRxTxFallbackMode defines into which mode the chip goes after a successful transmission or after a packet reception. 245 func (d *Device) SetRxTxFallbackMode(fallbackMode uint8) { 246 d.ExecSetCommand(SX126X_CMD_SET_RX_TX_FALLBACK_MODE, []uint8{fallbackMode}) 247 } 248 249 // -------------------------------------------------- 250 // Registers and Buffers 251 // -------------------------------------------------- 252 253 // ReadRegister reads register value 254 func (d *Device) ReadRegister(addr, size uint16) ([]uint8, error) { 255 d.CheckDeviceReady() 256 d.controller.SetNss(false) 257 // Send command 258 d.spiTxBuf = d.spiTxBuf[:0] 259 d.spiTxBuf = append(d.spiTxBuf, SX126X_CMD_READ_REGISTER, uint8((addr&0xFF00)>>8), uint8(addr&0x00FF), 0x00) 260 d.spi.Tx(d.spiTxBuf, nil) 261 // Read registers 262 d.spiRxBuf = d.spiRxBuf[0:size] 263 d.spi.Tx(nil, d.spiRxBuf) 264 d.controller.SetNss(true) 265 d.controller.WaitWhileBusy() 266 return d.spiRxBuf, nil 267 } 268 269 // WriteRegister writes value to register 270 func (d *Device) WriteRegister(addr uint16, data []uint8) { 271 d.CheckDeviceReady() 272 d.controller.SetNss(false) 273 d.spiTxBuf = d.spiTxBuf[:0] 274 d.spiTxBuf = append(d.spiTxBuf, SX126X_CMD_WRITE_REGISTER, uint8((addr&0xFF00)>>8), uint8(addr&0x00FF)) 275 d.spiTxBuf = append(d.spiTxBuf, data...) 276 d.spi.Tx(d.spiTxBuf, nil) 277 d.controller.SetNss(true) 278 d.controller.WaitWhileBusy() 279 } 280 281 // WriteBuffer write data from current buffer position 282 func (d *Device) WriteBuffer(data []uint8) { 283 p := []uint8{0} 284 p = append(p, data...) 285 d.ExecSetCommand(SX126X_CMD_WRITE_BUFFER, p) 286 } 287 288 // ReadBuffer Reads size bytes from current buffer position 289 func (d *Device) ReadBuffer(size uint8) []uint8 { 290 ret := d.ExecGetCommand(SX126X_CMD_READ_BUFFER, size) 291 return ret 292 } 293 294 // -------------------------------------------------- 295 // DIO and IRQ 296 // -------------------------------------------------- 297 298 // SetDioIrqParams configures DIO Irq 299 func (d *Device) SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask uint16) { 300 var p [8]uint8 301 p[0] = uint8((irqMask >> 8) & 0xFF) 302 p[1] = uint8(irqMask & 0xFF) 303 p[2] = uint8((dio1Mask >> 8) & 0xFF) 304 p[3] = uint8(dio1Mask & 0xFF) 305 p[4] = uint8((dio2Mask >> 8) & 0xFF) 306 p[5] = uint8(dio2Mask & 0xFF) 307 p[6] = uint8((dio3Mask >> 8) & 0xFF) 308 p[7] = uint8(dio3Mask & 0xFF) 309 d.ExecSetCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, p[:]) 310 } 311 312 // GetIrqStatus returns IRQ status 313 func (d *Device) GetIrqStatus() (irqStatus uint16) { 314 r := d.ExecGetCommand(SX126X_CMD_GET_IRQ_STATUS, 2) 315 ret := (uint16(r[0]) << 8) | uint16(r[1]) 316 return ret 317 } 318 319 // ClearIrqStatus clears IRQ flags 320 func (d *Device) ClearIrqStatus(clearIrqParams uint16) { 321 var p [2]uint8 322 p[0] = uint8((clearIrqParams >> 8) & 0xFF) 323 p[1] = uint8(clearIrqParams & 0xFF) 324 d.ExecSetCommand(SX126X_CMD_CLEAR_IRQ_STATUS, p[:]) 325 } 326 327 // -------------------------------------------------- 328 // Communication Status Information 329 // -------------------------------------------------- 330 331 // GetStatus returns radio status(13.5.1) 332 func (d *Device) GetStatus() (radioStatus uint8) { 333 r := d.ExecGetCommand(SX126X_CMD_GET_STATUS, 1) 334 return r[0] 335 } 336 337 // GetRxBufferStatus returns the length of the last received packet (PayloadLengthRx) 338 // and the address of the first byte received (RxStartBufferPointer). (13.5.2) 339 func (d *Device) GetRxBufferStatus() (payloadLengthRx uint8, rxStartBufferPointer uint8) { 340 r := d.ExecGetCommand(SX126X_CMD_GET_RX_BUFFER_STATUS, 2) 341 return r[0], r[1] 342 } 343 344 // GetPackeType returns current Packet Type (13.4.3) 345 func (d *Device) GetPacketType() (packetType uint8) { 346 r := d.ExecGetCommand(SX126X_CMD_GET_PACKET_TYPE, 1) 347 return r[0] 348 } 349 350 // GetDeviceErrors returns current Device Errors 351 func (d *Device) GetDeviceErrors() uint16 { 352 r := d.ExecGetCommand(SX126X_CMD_GET_DEVICE_ERRORS, 2) 353 ret := uint16(r[0]<<8 + r[1]) 354 return ret 355 } 356 357 // ClearDeviceErrors clears device Errors 358 func (d *Device) ClearDeviceErrors() { 359 p := [2]uint8{0x00, 0x00} 360 d.ExecSetCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, p[:]) 361 } 362 363 // GetStats returns the number of informations received on a few last packets 364 // Lora: NbPktReceived, NbPktCrcError, NbPktHeaderErr 365 func (d *Device) GetLoraStats() (nbPktReceived, nbPktCrcError, nbPktHeaderErr uint16) { 366 r := d.ExecGetCommand(SX126X_CMD_GET_STATS, 6) 367 return uint16(r[0]<<8 | r[1]), uint16(r[2]<<8 | r[3]), uint16(r[4]<<8 | r[5]) 368 } 369 370 // --------------------------------------- 371 // PACKET / RADIO / PROTOCOL CONFIGURATION 372 // --------------------------------------- 373 374 // SetPacketType sets the packet type 375 func (d *Device) SetPacketType(packetType uint8) { 376 var p [1]uint8 377 p[0] = packetType 378 d.ExecSetCommand(SX126X_CMD_SET_PACKET_TYPE, p[:]) 379 } 380 381 // SetSyncWord defines the Sync Word to yse 382 func (d *Device) SetSyncWord(sw uint16) { 383 var p [2]uint8 384 d.loraConf.SyncWord = sw 385 p[0] = uint8((d.loraConf.SyncWord >> 8) & 0xFF) 386 p[1] = uint8((d.loraConf.SyncWord >> 0) & 0xFF) 387 d.WriteRegister(SX126X_REG_LORA_SYNC_WORD_MSB, p[:]) 388 } 389 390 // GetSyncWord gets the Sync Word to use 391 func (d *Device) GetSyncWord() uint16 { 392 p, _ := d.ReadRegister(SX126X_REG_LORA_SYNC_WORD_MSB, 2) 393 r := uint16(p[0])<<8 + uint16(p[1]) 394 return r 395 } 396 397 // SetPublicNetwork sets Sync Word to 0x3444 (Public) or 0x1424 (Private) 398 func (d *Device) SetPublicNetwork(enable bool) { 399 if enable { 400 d.SetSyncWord(SX126X_LORA_MAC_PUBLIC_SYNCWORD) 401 } else { 402 d.SetSyncWord(SX126X_LORA_MAC_PRIVATE_SYNCWORD) 403 } 404 } 405 406 // SetPacketParam sets various packet-related params 407 func (d *Device) SetPacketParam(preambleLength uint16, headerType, crcType, payloadLength, invertIQ uint8) { 408 var p [6]uint8 409 p[0] = uint8((preambleLength >> 8) & 0xFF) 410 p[1] = uint8(preambleLength & 0xFF) 411 p[2] = headerType 412 p[3] = payloadLength 413 p[4] = crcType 414 p[5] = invertIQ 415 d.ExecSetCommand(SX126X_CMD_SET_PACKET_PARAMS, p[:]) 416 } 417 418 // SetBufferBaseAddress sets base address for buffer 419 func (d *Device) SetBufferBaseAddress(txBaseAddress, rxBaseAddress uint8) { 420 var p [2]uint8 421 p[0] = txBaseAddress 422 p[1] = rxBaseAddress 423 d.ExecSetCommand(SX126X_CMD_SET_BUFFER_BASE_ADDRESS, p[:]) 424 } 425 426 // SetRfFrequency sets the radio frequency 427 func (d *Device) SetRfFrequency(frequency uint32) { 428 var p [4]uint8 429 freq := uint32((uint64(frequency) << 25) / 32000000) 430 p[0] = uint8((freq >> 24) & 0xFF) 431 p[1] = uint8((freq >> 16) & 0xFF) 432 p[2] = uint8((freq >> 8) & 0xFF) 433 p[3] = uint8((freq >> 0) & 0xFF) 434 d.ExecSetCommand(SX126X_CMD_SET_RF_FREQUENCY, p[:]) 435 } 436 437 // SetCurrentLimit sets max current in the module 438 func (d *Device) SetCurrentLimit(limit uint8) { 439 if limit > 140 { 440 limit = 140 441 } 442 rawLimit := uint8(float32(limit) / 2.5) 443 p := []uint8{rawLimit} 444 d.WriteRegister(SX126X_REG_OCP_CONFIGURATION, p[:]) 445 } 446 447 // SetTxConfig sets power and rampup time 448 func (d *Device) SetTxParams(power int8, rampTime uint8) { 449 var p [2]uint8 450 451 if d.deviceType == DEVICE_TYPE_SX1261 { 452 if power == 15 { 453 d.SetPaConfig(0x06, 0x00, 0x01, 0x01) 454 } else { 455 d.SetPaConfig(0x04, 0x00, 0x01, 0x01) 456 } 457 if power > 14 { 458 power = 14 459 } else if power < -3 { 460 power = -3 461 } 462 d.SetCurrentLimit(80) // Set max current limit to 80mA 463 } else { // sx1262 and sx1268 464 d.SetPaConfig(0x04, 0x07, 0x00, 0x01) 465 if power > 22 { 466 power = 22 467 } else if power < -3 { 468 power = -3 469 } 470 d.SetCurrentLimit(140) // Set max current limit to 140 mA 471 } 472 473 p[0] = uint8(power) 474 p[1] = rampTime 475 d.ExecSetCommand(SX126X_CMD_SET_TX_PARAMS, p[:]) 476 } 477 478 // SetModulationParams sets the Lora modulation frequency 479 func (d *Device) SetModulationParams(spreadingFactor, bandwidth, codingRate, lowDataRateOptimize uint8) { 480 var p [4]uint8 481 p[0] = spreadingFactor 482 p[1] = bandwidth 483 p[2] = codingRate 484 p[3] = lowDataRateOptimize 485 d.ExecSetCommand(SX126X_CMD_SET_MODULATION_PARAMS, p[:]) 486 } 487 488 // CheckDeviceReady sleep until all busy flags clears 489 func (d *Device) CheckDeviceReady() error { 490 if d.deepSleep == true { 491 d.controller.SetNss(false) 492 time.Sleep(time.Millisecond) 493 d.controller.SetNss(true) 494 d.deepSleep = false 495 } 496 return d.controller.WaitWhileBusy() 497 } 498 499 // ExecSetCommand send a command to configure the peripheral 500 func (d *Device) ExecSetCommand(cmd uint8, buf []uint8) { 501 d.CheckDeviceReady() 502 if cmd == SX126X_CMD_SET_SLEEP { 503 d.deepSleep = true 504 } else { 505 d.deepSleep = false 506 } 507 d.controller.SetNss(false) 508 // Send command and params 509 d.spiTxBuf = d.spiTxBuf[:0] 510 d.spiTxBuf = append(d.spiTxBuf, cmd) 511 d.spiTxBuf = append(d.spiTxBuf, buf...) 512 d.spi.Tx(d.spiTxBuf, nil) 513 d.controller.SetNss(true) 514 if cmd != SX126X_CMD_SET_SLEEP { 515 d.controller.WaitWhileBusy() 516 } 517 } 518 519 // ExecGetCommand queries the peripheral the peripheral 520 func (d *Device) ExecGetCommand(cmd uint8, size uint8) []uint8 { 521 d.CheckDeviceReady() 522 d.controller.SetNss(false) 523 // Send the command and flush first status byte (as not used) 524 d.spiTxBuf = d.spiTxBuf[:0] 525 d.spiTxBuf = append(d.spiTxBuf, cmd, 0x00) 526 d.spi.Tx(d.spiTxBuf, nil) 527 // Read resp 528 d.spiRxBuf = d.spiRxBuf[:size] 529 d.spi.Tx(nil, d.spiRxBuf) 530 d.controller.SetNss(true) 531 d.controller.WaitWhileBusy() 532 return d.spiRxBuf 533 } 534 535 // 536 // Configuration 537 // 538 539 // SetFrequency() Sets current Lora Frequency 540 // NB: Change will be applied at next RX / TX 541 func (d *Device) SetFrequency(freq uint32) { 542 d.loraConf.Freq = freq 543 } 544 545 // SetIqMode() defines the current IQ Mode (Standard/Inverted) 546 // NB: Change will be applied at next RX / TX 547 func (d *Device) SetIqMode(mode uint8) { 548 if mode == 0 { 549 d.loraConf.Iq = lora.IQStandard 550 } else { 551 d.loraConf.Iq = lora.IQInverted 552 } 553 } 554 555 // SetCodingRate() sets current Lora Coding Rate 556 // NB: Change will be applied at next RX / TX 557 func (d *Device) SetCodingRate(cr uint8) { 558 d.loraConf.Cr = cr 559 } 560 561 // SetBandwidth() sets current Lora Bandwidth 562 // NB: Change will be applied at next RX / TX 563 func (d *Device) SetBandwidth(bw uint8) { 564 d.loraConf.Bw = bw 565 } 566 567 // SetCrc() sets current CRC mode (ON/OFF) 568 // NB: Change will be applied at next RX / TX 569 func (d *Device) SetCrc(enable bool) { 570 if enable { 571 d.loraConf.Crc = lora.CRCOn 572 } else { 573 d.loraConf.Crc = lora.CRCOn 574 } 575 } 576 577 // SetSpreadingFactor sets current Lora Spreading Factor 578 // NB: Change will be applied at next RX / TX 579 func (d *Device) SetSpreadingFactor(sf uint8) { 580 d.loraConf.Sf = sf 581 } 582 583 // SetPreambleLength sets current Lora Preamble Length 584 // NB: Change will be applied at next RX / TX 585 func (d *Device) SetPreambleLength(pl uint16) { 586 d.loraConf.Preamble = pl 587 } 588 589 // SetTxPowerDbm sets current Lora TX Power in DBm 590 // NB: Change will be applied at next RX / TX 591 func (d *Device) SetTxPower(txpow int8) { 592 d.loraConf.LoraTxPowerDBm = txpow 593 } 594 595 // SetHeaderType sets implicit or explicit header mode 596 // NB: Change will be applied at next RX / TX 597 func (d *Device) SetHeaderType(headerType uint8) { 598 d.loraConf.HeaderType = headerType 599 } 600 601 // 602 // Lora functions 603 // 604 // 605 606 // LoraConfig() defines Lora configuration for next Lora operations 607 func (d *Device) LoraConfig(cnf lora.Config) { 608 // Save given configuration 609 d.loraConf = cnf 610 d.loraConf.SyncWord = syncword(int(cnf.SyncWord)) 611 // Switch to standby prior to configuration changes 612 d.SetStandby() 613 // Clear errors, disable radio interrupts for the moment 614 d.ClearDeviceErrors() 615 d.ClearIrqStatus(SX126X_IRQ_ALL) 616 d.SetDioIrqParams(0x00, 0x00, 0x00, 0x00) 617 // Define radio operation mode 618 d.SetPacketType(SX126X_PACKET_TYPE_LORA) 619 d.SetRfFrequency(d.loraConf.Freq) 620 d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr) 621 d.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U) 622 d.SetSyncWord(d.loraConf.SyncWord) 623 d.SetBufferBaseAddress(0, 0) 624 } 625 626 // Tx sends a lora packet, (with timeout) 627 func (d *Device) Tx(pkt []uint8, timeoutMs uint32) error { 628 if d.loraConf.Freq == 0 { 629 return lora.ErrUndefinedLoraConf 630 } 631 632 if d.controller != nil { 633 err := d.controller.SetRfSwitchMode(RFSWITCH_TX_HP) 634 if err != nil { 635 return err 636 } 637 } 638 639 d.ClearIrqStatus(SX126X_IRQ_ALL) 640 irqVal := uint16(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR) 641 d.SetStandby() 642 d.SetPacketType(SX126X_PACKET_TYPE_LORA) 643 d.SetRfFrequency(d.loraConf.Freq) 644 d.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U) 645 d.SetBufferBaseAddress(0, 0) 646 d.WriteBuffer(pkt) 647 d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr) 648 d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, uint8(len(pkt)), d.loraConf.Iq) 649 d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE) 650 d.SetSyncWord(d.loraConf.SyncWord) 651 d.SetTx(timeoutMsToRtcSteps(timeoutMs)) 652 653 msg := <-d.GetRadioEventChan() 654 if msg.EventType != lora.RadioEventTxDone { 655 return errUnexpectedTxRadioEvent 656 } 657 return nil 658 } 659 660 // LoraRx tries to receive a Lora packet (with timeout in milliseconds) 661 func (d *Device) Rx(timeoutMs uint32) ([]uint8, error) { 662 if d.loraConf.Freq == 0 { 663 return nil, lora.ErrUndefinedLoraConf 664 } 665 666 if d.controller != nil { 667 err := d.controller.SetRfSwitchMode(RFSWITCH_RX) 668 if err != nil { 669 return nil, err 670 } 671 } 672 673 d.ClearIrqStatus(SX126X_IRQ_ALL) 674 irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR) 675 d.SetStandby() 676 d.SetBufferBaseAddress(0, 0) 677 d.SetRfFrequency(d.loraConf.Freq) 678 d.SetModulationParams(d.loraConf.Sf, bandwidth(d.loraConf.Bw), d.loraConf.Cr, d.loraConf.Ldr) 679 d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq) 680 d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE) 681 d.SetRx(timeoutMsToRtcSteps(timeoutMs)) 682 683 msg := <-d.GetRadioEventChan() 684 685 if msg.EventType == lora.RadioEventTimeout { 686 return nil, nil 687 } else if msg.EventType != lora.RadioEventRxDone { 688 return nil, errUnexpectedRxRadioEvent 689 } 690 691 pLen, pStart := d.GetRxBufferStatus() 692 d.SetBufferBaseAddress(0, pStart+1) 693 pkt := d.ReadBuffer(pLen + 1) 694 pkt = pkt[1:] 695 696 return pkt, nil 697 } 698 699 // HandleInterrupt must be called by main code on DIO state change. 700 func (d *Device) HandleInterrupt() { 701 st := d.GetIrqStatus() 702 d.ClearIrqStatus(SX126X_IRQ_ALL) 703 704 if (st & SX126X_IRQ_RX_DONE) > 0 { 705 select { 706 case d.radioEventChan <- lora.RadioEvent{lora.RadioEventRxDone, uint16(st), nil}: 707 default: 708 } 709 } 710 711 if (st & SX126X_IRQ_TX_DONE) > 0 { 712 select { 713 case d.radioEventChan <- lora.RadioEvent{lora.RadioEventTxDone, uint16(st), nil}: 714 default: 715 } 716 } 717 718 if (st & SX126X_IRQ_TIMEOUT) > 0 { 719 select { 720 case d.radioEventChan <- lora.RadioEvent{lora.RadioEventTimeout, uint16(st), nil}: 721 default: 722 } 723 724 } 725 726 if (st & SX126X_IRQ_CRC_ERR) > 0 { 727 select { 728 case d.radioEventChan <- lora.RadioEvent{lora.RadioEventCrcError, uint16(st), nil}: 729 730 default: 731 } 732 } 733 734 } 735 736 func bandwidth(bw uint8) uint8 { 737 switch bw { 738 case lora.Bandwidth_7_8: 739 return SX126X_LORA_BW_7_8 740 case lora.Bandwidth_10_4: 741 return SX126X_LORA_BW_10_4 742 case lora.Bandwidth_15_6: 743 return SX126X_LORA_BW_15_6 744 case lora.Bandwidth_20_8: 745 return SX126X_LORA_BW_20_8 746 case lora.Bandwidth_31_25: 747 return SX126X_LORA_BW_31_25 748 case lora.Bandwidth_41_7: 749 return SX126X_LORA_BW_41_7 750 case lora.Bandwidth_62_5: 751 return SX126X_LORA_BW_62_5 752 case lora.Bandwidth_125_0: 753 return SX126X_LORA_BW_125_0 754 case lora.Bandwidth_250_0: 755 return SX126X_LORA_BW_250_0 756 case lora.Bandwidth_500_0: 757 return SX126X_LORA_BW_500_0 758 default: 759 return 0 760 } 761 } 762 763 func syncword(sw int) uint16 { 764 if sw == lora.SyncPublic { 765 return SX126X_LORA_MAC_PUBLIC_SYNCWORD 766 } 767 return SX126X_LORA_MAC_PRIVATE_SYNCWORD 768 }