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  }