Files
drivers/sx126x/sx126x.go
deadprogram 1bb1b621c6 all: correct go fmt
Signed-off-by: deadprogram <ron@hybridgroup.com>
2022-09-25 13:23:16 +02:00

702 lines
20 KiB
Go

// Package sx126x provides a driver for SX126x LoRa transceivers.
// Inspired from https://github.com/Lora-net/sx126x_driver/
package sx126x
import (
"errors"
"time"
"tinygo.org/x/drivers"
)
// SX126X radio transceiver RF_IN and RF_OUT may be connected
// to RF Switch. This interface allows the creation of struct
// that can drive the RF Switch (Used in Lora RX and Lora Tx)
type RFSwitch interface {
InitRFSwitch()
SetRfSwitchMode(mode int) error
}
const (
DEVICE_TYPE_SX1261 = iota
DEVICE_TYPE_SX1262 = iota
DEVICE_TYPE_SX1268 = iota
)
const (
RFSWITCH_RX = iota
RFSWITCH_TX_LP = iota
RFSWITCH_TX_HP = iota
)
const (
RadioEventRxDone = iota
RadioEventTxDone = iota
RadioEventTimeout = iota
RadioEventWatchdog = iota
RadioEventCrcError = iota
RadioEventUnhandled = iota
)
// RadioEvent are used for communicating in the radio Event Channel
type RadioEvent struct {
EventType int
IRQStatus uint16
EventData []byte
}
const (
PERIOD_PER_SEC = (uint32)(1000000 / 15.625) // SX1261 DS 13.1.4
SPI_BUFFER_SIZE = 256
)
// Device wraps an SPI connection to a SX127x device.
type Device struct {
spi drivers.SPI // SPI bus for module communication
radioEventChan chan RadioEvent // Channel for Receiving events
loraConf LoraConfig // Current Lora configuration
rfswitch RFSwitch // RF Switch, if any
deepSleep bool // Internal Sleep state
deviceType int // sx1261,sx1262,sx1268 (defaults sx1261)
spiBuffer [SPI_BUFFER_SIZE]uint8
}
// Config holds the LoRa configuration parameters
type LoraConfig struct {
Freq uint32 // Frequency
Cr uint8 // Coding Rate
Sf uint8 // Spread Factor
Bw uint8 // Bandwidth
Ldr uint8 // Low Data Rate
Preamble uint16 // PreambleLength
SyncWord uint16 // Sync Word
HeaderType uint8 // Header : Implicit/explicit
Crc uint8 // CRC : Yes/No
Iq uint8 // iq : Standard/inverted
LoraTxPowerDBm int8 // Tx power in Dbm
}
const (
SX126X_RTC_FREQ_IN_HZ uint32 = 64000
)
var (
errUndefinedLoraConf = errors.New("Undefined Lora configuration")
)
// --------------------------------------------------
// Helper functions
// --------------------------------------------------
// timeoutMsToRtcSteps converts Timeout (in ms) to RTC Steps
func timeoutMsToRtcSteps(timeoutMs uint32) uint32 {
r := uint32(timeoutMs * (SX126X_RTC_FREQ_IN_HZ / 1000))
return r
}
// --------------------------------------------------
//
// Channel and events
//
// --------------------------------------------------
// NewRadioEvent() returns a new RadioEvent that can be used in the RadioChannel
func NewRadioEvent(eType int, irqStatus uint16, eData []byte) RadioEvent {
r := RadioEvent{EventType: eType, IRQStatus: irqStatus, EventData: eData}
return r
}
// Get the RadioEvent channel of the device
func (d *Device) GetRadioEventChan() chan RadioEvent {
return d.radioEventChan
}
// Specify device type (SX1261/2/8)
func (d *Device) SetDeviceType(devType int) {
d.deviceType = devType
}
// SetRfSwitch let you define a custom RF Switch driver if needed
func (d *Device) SetRfSwitch(rfswitch RFSwitch) {
d.rfswitch = rfswitch
d.rfswitch.InitRFSwitch()
}
// --------------------------------------------------
// Operational modes functions
// --------------------------------------------------
// DetectDevice() tries to detect the radio module by changing SyncWord value
func (d *Device) DetectDevice() bool {
bak := d.GetSyncWord()
d.SetSyncWord(0xBEEF)
tmp := d.GetSyncWord()
if tmp != 0xBEEF {
return false
} else {
d.SetSyncWord(bak)
return true
}
}
// SetSleep sets the device in SLEEP mode with the lowest current consumption possible.
func (d *Device) SetSleep() {
d.ExecSetCommand(SX126X_CMD_SET_SLEEP, []uint8{SX126X_SLEEP_START_WARM | SX126X_SLEEP_RTC_OFF})
}
// SetStandby sets the device in a configuration mode which is at an intermediate level of consumption
func (d *Device) SetStandby() {
d.ExecSetCommand(SX126X_CMD_SET_STANDBY, []uint8{SX126X_STANDBY_RC})
}
// SetFs sets the device in frequency synthesis mode where the PLL is locked to the carrier frequency.
func (d *Device) SetFs() {
d.ExecSetCommand(SX126X_CMD_SET_FS, []uint8{})
}
// SetTxContinuousWave set device in test mode to generate a continuous wave (RF tone)
func (d *Device) SetTxContinuousWave() {
if d.rfswitch != nil {
d.rfswitch.SetRfSwitchMode(RFSWITCH_TX_HP)
}
d.ExecSetCommand(SX126X_CMD_SET_TX_CONTINUOUS_WAVE, []uint8{})
}
// SetTxContinuousPreamble set device in test mode to constantly modulate LoRa preamble symbols.
// Take care to initialize all Lora settings like it's done in LoraTx before calling this function
// If you don't init properly all the settings, it'll fail
func (d *Device) SetTxContinuousPreamble() {
if d.rfswitch != nil {
d.rfswitch.SetRfSwitchMode(RFSWITCH_TX_HP)
}
d.ExecSetCommand(SX126X_CMD_SET_TX_INFINITE_PREAMBLE, []uint8{})
}
// SetTx() sets the device in TX mode
// timeout is expressed in RTC Step unit (15uS)
// The device will stay in Tx until countdown or packet transmitted
// Value of 0x000000 will disable timer and device will stay TX
func (d *Device) SetTx(timeoutRtcStep uint32) {
var p [3]uint8
p[0] = uint8((timeoutRtcStep >> 16) & 0xFF)
p[1] = uint8((timeoutRtcStep >> 8) & 0xFF)
p[2] = uint8((timeoutRtcStep >> 0) & 0xFF)
d.ExecSetCommand(SX126X_CMD_SET_TX, p[:])
}
// SetRx() sets the device in RX mode
// timeout is expressed in RTC Step unit (15uS)
// Value of 0x000000 => No timeout. Rx Single mode.
// Value of 0xffffff => Rx Continuous mode
// Other values => Timeout active. The device remains in RX until countdown or packet received
func (d *Device) SetRx(timeoutRtcStep uint32) {
var p [3]uint8
p[0] = uint8(((timeoutRtcStep >> 16) & 0xFF))
p[1] = uint8(((timeoutRtcStep >> 8) & 0xFF))
p[2] = uint8(((timeoutRtcStep >> 0) & 0xFF))
d.ExecSetCommand(SX126X_CMD_SET_RX, p[:])
}
// StopTimerOnPreamble allows the user to select if the timer is stopped upon preamble detection of SyncWord / header detection.
func (d *Device) StopTimerOnPreamble(enable bool) {
var p [1]uint8
if enable {
p[0] = 1
} else {
p[0] = 0
}
d.ExecSetCommand(SX126X_CMD_STOP_TIMER_ON_PREAMBLE, p[:])
}
// SetRegulatorMode sets the regulator more (depends on hardware implementation)
func (d *Device) SetRegulatorMode(mode uint8) {
p := []uint8{mode}
d.ExecSetCommand(SX126X_CMD_SET_REGULATOR_MODE, p[:])
}
// Calibrate starts the calibration of a block defined by calibParam
func (d *Device) Calibrate(calibParam uint8) {
p := []uint8{calibParam}
d.ExecSetCommand(SX126X_CMD_CALIBRATE, p[:])
}
// CalibrateImage calibrates the image rejection of the device for the device operating
func (d *Device) CalibrateImage(freq uint32) {
var calFreq [2]uint8
if freq > 900000000 {
calFreq[0] = 0xE1
calFreq[1] = 0xE9
} else if freq > 850000000 {
calFreq[0] = 0xD7
calFreq[1] = 0xD8
} else if freq > 770000000 {
calFreq[0] = 0xC1
calFreq[1] = 0xC5
} else if freq > 460000000 {
calFreq[0] = 0x75
calFreq[1] = 0x81
} else if freq > 425000000 {
calFreq[0] = 0x6B
calFreq[1] = 0x6F
}
d.ExecSetCommand(SX126X_CMD_CALIBRATE_IMAGE, calFreq[:])
}
// SetPaConfig sets the Power Amplifier configuration
// deviceSel: 0 for SX1262, 1 for SX1261
func (d *Device) SetPaConfig(paDutyCycle, hpMax, deviceSel, paLut uint8) {
var p [4]uint8
p[0] = paDutyCycle
p[1] = hpMax
p[2] = deviceSel
p[3] = paLut
d.ExecSetCommand(SX126X_CMD_SET_PA_CONFIG, p[:])
}
// SetRxTxFallbackMode defines into which mode the chip goes after a successful transmission or after a packet reception.
func (d *Device) SetRxTxFallbackMode(fallbackMode uint8) {
d.ExecSetCommand(SX126X_CMD_SET_RX_TX_FALLBACK_MODE, []uint8{fallbackMode})
}
// --------------------------------------------------
// Registers and Buffers
// --------------------------------------------------
// ReadRegister reads register value
func (d *Device) ReadRegister(addr, size uint16) ([]uint8, error) {
d.CheckDeviceReady()
d.SpiSetNss(false)
// Send command
cmd := []uint8{SX126X_CMD_READ_REGISTER, uint8((addr & 0xFF00) >> 8), uint8(addr & 0x00FF), 0x00}
d.spi.Tx(cmd, nil)
ret := d.spiBuffer[0:size]
d.spi.Tx(nil, ret)
d.SpiSetNss(true)
d.WaitBusy()
return ret, nil
}
// WriteRegister writes value to register
func (d *Device) WriteRegister(addr uint16, data []uint8) {
d.CheckDeviceReady()
d.SpiSetNss(false)
cmd := []uint8{SX126X_CMD_WRITE_REGISTER, uint8((addr & 0xFF00) >> 8), uint8(addr & 0x00FF)}
d.spi.Tx(append(cmd, data...), nil)
d.SpiSetNss(true)
d.WaitBusy()
}
// WriteBuffer write data from current buffer position
func (d *Device) WriteBuffer(data []uint8) {
p := []uint8{0}
p = append(p, data...)
d.ExecSetCommand(SX126X_CMD_WRITE_BUFFER, p)
}
// ReadBuffer Reads size bytes from current buffer position
func (d *Device) ReadBuffer(size uint8) []uint8 {
ret := d.ExecGetCommand(SX126X_CMD_READ_BUFFER, size)
return ret
}
// --------------------------------------------------
// DIO and IRQ
// --------------------------------------------------
// SetDioIrqParams configures DIO Irq
func (d *Device) SetDioIrqParams(irqMask, dio1Mask, dio2Mask, dio3Mask uint16) {
var p [8]uint8
p[0] = uint8((irqMask >> 8) & 0xFF)
p[1] = uint8(irqMask & 0xFF)
p[2] = uint8((dio1Mask >> 8) & 0xFF)
p[3] = uint8(dio1Mask & 0xFF)
p[4] = uint8((dio2Mask >> 8) & 0xFF)
p[5] = uint8(dio2Mask & 0xFF)
p[6] = uint8((dio3Mask >> 8) & 0xFF)
p[7] = uint8(dio3Mask & 0xFF)
d.ExecSetCommand(SX126X_CMD_SET_DIO_IRQ_PARAMS, p[:])
}
// GetIrqStatus returns IRQ status
func (d *Device) GetIrqStatus() (irqStatus uint16) {
r := d.ExecGetCommand(SX126X_CMD_GET_IRQ_STATUS, 2)
ret := (uint16(r[0]) << 8) | uint16(r[1])
return ret
}
// ClearIrqStatus clears IRQ flags
func (d *Device) ClearIrqStatus(clearIrqParams uint16) {
var p [2]uint8
p[0] = uint8((clearIrqParams >> 8) & 0xFF)
p[1] = uint8(clearIrqParams & 0xFF)
d.ExecSetCommand(SX126X_CMD_CLEAR_IRQ_STATUS, p[:])
}
// --------------------------------------------------
// Communication Status Information
// --------------------------------------------------
// GetStatus returns radio status(13.5.1)
func (d *Device) GetStatus() (radioStatus uint8) {
r := d.ExecGetCommand(SX126X_CMD_GET_STATUS, 1)
return r[0]
}
// GetRxBufferStatus returns the length of the last received packet (PayloadLengthRx)
// and the address of the first byte received (RxStartBufferPointer). (13.5.2)
func (d *Device) GetRxBufferStatus() (payloadLengthRx uint8, rxStartBufferPointer uint8) {
r := d.ExecGetCommand(SX126X_CMD_GET_RX_BUFFER_STATUS, 2)
return r[0], r[1]
}
// GetPackeType returns current Packet Type (13.4.3)
func (d *Device) GetPacketType() (packetType uint8) {
r := d.ExecGetCommand(SX126X_CMD_GET_PACKET_TYPE, 1)
return r[0]
}
// GetDeviceErrors returns current Device Errors
func (d *Device) GetDeviceErrors() uint16 {
r := d.ExecGetCommand(SX126X_CMD_GET_DEVICE_ERRORS, 2)
ret := uint16(r[0]<<8 + r[1])
return ret
}
// ClearDeviceErrors clears device Errors
func (d *Device) ClearDeviceErrors() {
p := [2]uint8{0x00, 0x00}
d.ExecSetCommand(SX126X_CMD_CLEAR_DEVICE_ERRORS, p[:])
}
// GetStats returns the number of informations received on a few last packets
// Lora: NbPktReceived, NbPktCrcError, NbPktHeaderErr
func (d *Device) GetLoraStats() (nbPktReceived, nbPktCrcError, nbPktHeaderErr uint16) {
r := d.ExecGetCommand(SX126X_CMD_GET_STATS, 6)
return uint16(r[0]<<8 | r[1]), uint16(r[2]<<8 | r[3]), uint16(r[4]<<8 | r[5])
}
// ---------------------------------------
// PACKET / RADIO / PROTOCOL CONFIGURATION
// ---------------------------------------
// SetPacketType sets the packet type
func (d *Device) SetPacketType(packetType uint8) {
var p [1]uint8
p[0] = packetType
d.ExecSetCommand(SX126X_CMD_SET_PACKET_TYPE, p[:])
}
// SetSyncWord defines the Sync Word to yse
func (d *Device) SetSyncWord(syncword uint16) {
var p [2]uint8
d.loraConf.SyncWord = syncword
p[0] = uint8((syncword >> 8) & 0xFF)
p[1] = uint8((syncword >> 0) & 0xFF)
d.WriteRegister(SX126X_REG_LORA_SYNC_WORD_MSB, p[:])
}
// GetSyncWord gets the Sync Word to use
func (d *Device) GetSyncWord() uint16 {
p, _ := d.ReadRegister(SX126X_REG_LORA_SYNC_WORD_MSB, 2)
r := uint16(p[0])<<8 + uint16(p[1])
return r
}
// SetLoraPublicNetwork sets Sync Word to 0x3444 (Public) or 0x1424 (Private)
func (d *Device) SetLoraPublicNetwork(enable bool) {
if enable {
d.SetSyncWord(SX126X_LORA_MAC_PUBLIC_SYNCWORD)
} else {
d.SetSyncWord(SX126X_LORA_MAC_PRIVATE_SYNCWORD)
}
}
// SetPacketParam sets various packet-related params
func (d *Device) SetPacketParam(preambleLength uint16, headerType, crcType, payloadLength, invertIQ uint8) {
var p [6]uint8
p[0] = uint8((preambleLength >> 8) & 0xFF)
p[1] = uint8(preambleLength & 0xFF)
p[2] = headerType
p[3] = payloadLength
p[4] = crcType
p[5] = invertIQ
d.ExecSetCommand(SX126X_CMD_SET_PACKET_PARAMS, p[:])
}
// SetBufferBaseAddress sets base address for buffer
func (d *Device) SetBufferBaseAddress(txBaseAddress, rxBaseAddress uint8) {
var p [2]uint8
p[0] = txBaseAddress
p[1] = rxBaseAddress
d.ExecSetCommand(SX126X_CMD_SET_BUFFER_BASE_ADDRESS, p[:])
}
// SetRfFrequency sets the radio frequency
func (d *Device) SetRfFrequency(frequency uint32) {
var p [4]uint8
freq := uint32((uint64(frequency) << 25) / 32000000)
p[0] = uint8((freq >> 24) & 0xFF)
p[1] = uint8((freq >> 16) & 0xFF)
p[2] = uint8((freq >> 8) & 0xFF)
p[3] = uint8((freq >> 0) & 0xFF)
d.ExecSetCommand(SX126X_CMD_SET_RF_FREQUENCY, p[:])
}
// SetCurrentLimit sets max current in the module
func (d *Device) SetCurrentLimit(limit uint8) {
if limit > 140 {
limit = 140
}
rawLimit := uint8(float32(limit) / 2.5)
p := []uint8{rawLimit}
d.WriteRegister(SX126X_REG_OCP_CONFIGURATION, p[:])
}
// SetTxConfig sets power and rampup time
func (d *Device) SetTxParams(power int8, rampTime uint8) {
var p [2]uint8
if d.deviceType == DEVICE_TYPE_SX1261 {
if power == 15 {
d.SetPaConfig(0x06, 0x00, 0x01, 0x01)
} else {
d.SetPaConfig(0x04, 0x00, 0x01, 0x01)
}
if power > 14 {
power = 14
} else if power < -3 {
power = -3
}
d.SetCurrentLimit(80) // Set max current limit to 80mA
} else { // sx1262 and sx1268
d.SetPaConfig(0x04, 0x07, 0x00, 0x01)
if power > 22 {
power = 22
} else if power < -3 {
power = -3
}
d.SetCurrentLimit(140) // Set max current limit to 140 mA
}
p[0] = uint8(power)
p[1] = rampTime
d.ExecSetCommand(SX126X_CMD_SET_TX_PARAMS, p[:])
}
// SetModulationParams sets the Lora modulation frequency
func (d *Device) SetModulationParams(spreadingFactor, bandwidth, codingRate, lowDataRateOptimize uint8) {
var p [4]uint8
p[0] = spreadingFactor
p[1] = bandwidth
p[2] = codingRate
p[3] = lowDataRateOptimize
d.ExecSetCommand(SX126X_CMD_SET_MODULATION_PARAMS, p[:])
}
// CheckDeviceReady sleep until all busy flags clears
func (d *Device) CheckDeviceReady() error {
if d.deepSleep == true {
d.SpiSetNss(false)
time.Sleep(time.Millisecond)
d.SpiSetNss(true)
d.deepSleep = false
}
return d.WaitBusy()
}
// ExecSetCommand send a command to configure the peripheral
func (d *Device) ExecSetCommand(cmd uint8, buf []uint8) {
d.CheckDeviceReady()
if cmd == SX126X_CMD_SET_SLEEP {
d.deepSleep = true
} else {
d.deepSleep = false
}
d.SpiSetNss(false)
// Send command and params
d.spi.Tx(append([]uint8{cmd}, buf...), nil)
d.SpiSetNss(true)
if cmd != SX126X_CMD_SET_SLEEP {
d.WaitBusy()
}
}
// ExecGetCommand queries the peripheral the peripheral
func (d *Device) ExecGetCommand(cmd uint8, size uint8) []uint8 {
d.CheckDeviceReady()
d.SpiSetNss(false)
// Send the command and flush first status byte (as not used)
d.spi.Tx([]uint8{cmd, 0x00}, nil)
d.spi.Tx(nil, d.spiBuffer[:size])
d.SpiSetNss(true)
d.WaitBusy()
return d.spiBuffer[:size]
}
//
// Configuration
//
// SetLoraFrequency() Sets current Lora Frequency
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraFrequency(freq uint32) {
d.loraConf.Freq = d.loraConf.Freq
}
// SetLoraIqMode() defines the current IQ Mode (Standard/Inverted)
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraIqMode(mode uint8) {
if mode == 0 {
d.loraConf.Iq = SX126X_LORA_IQ_STANDARD
} else {
d.loraConf.Iq = SX126X_LORA_IQ_INVERTED
}
}
// SetLoraCodingRate() sets current Lora Coding Rate
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraCodingRate(cr uint8) {
d.loraConf.Cr = cr
}
// SetLoraBandwidth() sets current Lora Bandwidth
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraBandwidth(bw uint8) {
d.loraConf.Cr = bw
}
// SetLoraCrc() sets current CRC mode (ON/OFF)
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraCrc(enable bool) {
if enable {
d.loraConf.Crc = SX126X_LORA_CRC_ON
} else {
d.loraConf.Crc = SX126X_LORA_CRC_OFF
}
}
// SetLoraSpreadingFactor setc surrent Lora Spreading Factor
// NB: Change will be applied at next RX / TX
func (d *Device) SetLoraSpreadingFactor(sf uint8) {
d.loraConf.Sf = sf
}
//
// Lora functions
//
//
// LoraConfig() defines Lora configuration for next Lora operations
func (d *Device) LoraConfig(cnf LoraConfig) {
// Save given configuration
d.loraConf = cnf
// Switch to standby prior to configuration changes
d.SetStandby()
// Clear errors, disable radio interrupts for the moment
d.ClearDeviceErrors()
d.ClearIrqStatus(SX126X_IRQ_ALL)
d.SetDioIrqParams(0x00, 0x00, 0x00, 0x00)
// Define radio operation mode
d.SetPacketType(SX126X_PACKET_TYPE_LORA)
d.SetRfFrequency(d.loraConf.Freq)
d.SetModulationParams(d.loraConf.Sf, d.loraConf.Bw, d.loraConf.Cr, d.loraConf.Ldr)
d.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U)
d.SetSyncWord(d.loraConf.SyncWord)
d.SetBufferBaseAddress(0, 0)
}
// LoraTx sends a lora packet, (with timeout)
func (d *Device) LoraTx(pkt []uint8, timeoutMs uint32) error {
if d.loraConf.Freq == 0 {
return errUndefinedLoraConf
}
if d.rfswitch != nil {
err := d.rfswitch.SetRfSwitchMode(RFSWITCH_TX_HP)
if err != nil {
return err
}
}
d.ClearIrqStatus(SX126X_IRQ_ALL)
irqVal := uint16(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
d.SetStandby()
d.SetPacketType(SX126X_PACKET_TYPE_LORA)
d.SetRfFrequency(d.loraConf.Freq)
d.SetTxParams(d.loraConf.LoraTxPowerDBm, SX126X_PA_RAMP_200U)
d.SetBufferBaseAddress(0, 0)
d.WriteBuffer(pkt)
d.SetModulationParams(d.loraConf.Sf, d.loraConf.Bw, d.loraConf.Cr, d.loraConf.Ldr)
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, uint8(len(pkt)), d.loraConf.Iq)
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
d.SetSyncWord(d.loraConf.SyncWord)
d.SetTx(timeoutMsToRtcSteps(timeoutMs))
msg := <-d.GetRadioEventChan()
if msg.EventType != RadioEventTxDone {
return errors.New("Unexpected Radio Event while TX")
}
return nil
}
// LoraRx tries to receive a Lora packet (with timeout in milliseconds)
func (d *Device) LoraRx(timeoutMs uint32) ([]uint8, error) {
if d.loraConf.Freq == 0 {
return nil, errUndefinedLoraConf
}
if d.rfswitch != nil {
err := d.rfswitch.SetRfSwitchMode(RFSWITCH_RX)
if err != nil {
return nil, err
}
}
d.ClearIrqStatus(SX126X_IRQ_ALL)
irqVal := uint16(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR)
d.SetStandby()
d.SetBufferBaseAddress(0, 0)
d.SetModulationParams(d.loraConf.Sf, d.loraConf.Bw, d.loraConf.Cr, d.loraConf.Ldr)
d.SetPacketParam(d.loraConf.Preamble, d.loraConf.HeaderType, d.loraConf.Crc, 0xFF, d.loraConf.Iq)
d.SetDioIrqParams(irqVal, irqVal, SX126X_IRQ_NONE, SX126X_IRQ_NONE)
d.SetRx(timeoutMsToRtcSteps(timeoutMs))
msg := <-d.GetRadioEventChan()
if msg.EventType == RadioEventTimeout {
return nil, nil
} else if msg.EventType != RadioEventRxDone {
return nil, errors.New("Unexpected Radio Event while RX")
}
pLen, pStart := d.GetRxBufferStatus()
d.SetBufferBaseAddress(0, pStart+1)
pkt := d.ReadBuffer(pLen + 1)
pkt = pkt[1:]
return pkt, nil
}
// HandleInterrupt must be called by main code on DIO state change.
func (d *Device) HandleInterrupt() {
st := d.GetIrqStatus()
d.ClearIrqStatus(SX126X_IRQ_ALL)
rChan := d.GetRadioEventChan()
if (st & SX126X_IRQ_RX_DONE) > 0 {
rChan <- NewRadioEvent(RadioEventRxDone, st, nil)
}
if (st & SX126X_IRQ_TX_DONE) > 0 {
rChan <- NewRadioEvent(RadioEventTxDone, st, nil)
}
if (st & SX126X_IRQ_TIMEOUT) > 0 {
rChan <- NewRadioEvent(RadioEventTimeout, st, nil)
}
if (st & SX126X_IRQ_CRC_ERR) > 0 {
rChan <- NewRadioEvent(RadioEventCrcError, st, nil)
}
}