Closed QiaoTuCodes closed 2 years ago
Hi, instead of just copy all the python files into your pyboard, you can try to compile the python files into the firmware then flash it to your pyboard.
oh! so i just copy the lib all files to micropython firmware freezing folder and compile bin files . flash it to pyboard may can used right ?
Yes, hopefully this will resolve the memory problem, otherwise have to use board that has more memory, i.e. ESP32 based board, etc.
okey! trying thank you bro!
hello bro. a new problem say:
Traceback (most recent call last): File "main.py", line 4, in File "sx1262.py", line 20, in init File "sx126x.py", line 46, in init TypeError: extra keyword arguments given MicroPython v1.15 on 2021-11-10: pyBoard Plus with STM32F407VGT6
i checked the 3 files error line codes but nothing. just full copy from your sample. so what happend? how can i do that?
I think may be in the file sx126x.py, line 46
self.spi = SPI(0, baudrate=2000000, pins=(clk, mosi, miso))
pins
keyword argument might not be compatible with pyboard's micropython.
May be you can try modify the SPI object calling code here and try again.
oh yeah! great! i'll also think may default useing from machine import SPI , Pin
maybe change 'from pyb import SPI , Pin' will be fix the compatible. i'll trying... thank you.
maybe the 2 libs it's not identical
help sir. a new problem again:
Traceback (most recent call last): File "main.py", line 4, in <module> File "sx1268.py", line 20, in __init__ File "sx126x.py", line 46, in __init__ TypeError: extra keyword arguments given MicroPython v1.15 on 2021-11-13; PYBv1.1_CN with STM32F405RG Type "help()" for more information.
i don't know why? check all codes not change that.
i just change my Pin ports.
It is back to the same problem you encountered initially. I think it's best if you can send me your modified code, let me have a look.
Paste your modified code here is fine.
okey zip pack for U. so thank you very much!
Can you paste your modified sx126x.py code to the comment instead?
okey!
`from _sx126x import *
from sys import implementation
if implementation.name == 'micropython': from machine import SPI, Pin from utime import sleep_ms, sleep_us, ticks_ms, ticks_us, ticks_diff
if implementation.name == 'circuitpython': import digitalio import busio from time import sleep, monotonic_ns
_MS_PER_NS = const(1000000)
_US_PER_NS = const(1000)
_MS_PER_S = const(1000)
_TICKS_MAX = const(536870911)
_TICKS_PERIOD = const(536870912)
_TICKS_HALFPERIOD = const(268435456)
def sleep_ms(ms):
sleep(ms/1000)
def sleep_us(us):
sleep(us/1000000)
def ticks_ms():
return (monotonic_ns() // _MS_PER_NS) & _TICKS_MAX
def ticks_us():
return (monotonic_ns() // _US_PER_NS) & _TICKS_MAX
def ticks_diff(end, start):
diff = (end - start) & _TICKS_MAX
diff = ((diff + _TICKS_HALFPERIOD) & _TICKS_MAX) - _TICKS_HALFPERIOD
return diff
class SX126X:
def __init__(self, cs, irq, rst, gpio, clk='Y6', mosi='Y8', miso='Y7'):
self._irq = irq
if implementation.name == 'micropython':
try:
self.spi = SPI(2, mode=SPI.MASTER, baudrate=2000000, pins=(clk, mosi, miso)) # Pycom variant uPy
except:
self.spi = SPI(2, baudrate=2000000, pins=(clk, mosi, miso)) # Generic variant uPy
self.cs = Pin(cs, mode=Pin.OUT)
self.cs = Pin(cs, mode=Pin.OUT)
self.irq = Pin(irq, mode=Pin.IN)
self.rst = Pin(rst, mode=Pin.OUT)
self.gpio = Pin(gpio, mode=Pin.IN)
if implementation.name == 'circuitpython':
self.spi = busio.SPI(clk, MOSI=mosi, MISO=miso)
while not self.spi.try_lock():
pass
self.spi.configure(baudrate=2000000, phase=0, polarity=0, bits=8)
self.spi.unlock()
self.cs = digitalio.DigitalInOut(cs)
self.cs.switch_to_output(value=True)
self.irq = digitalio.DigitalInOut(irq)
self.irq.switch_to_input()
self.rst = digitalio.DigitalInOut(rst)
self.rst.switch_to_output(value=True)
self.gpio = digitalio.DigitalInOut(gpio)
self.gpio.switch_to_input()
self._bwKhz = 0
self._sf = 0
self._bw = 0
self._cr = 0
self._ldro = 0
self._crcType = 0
self._preambleLength = 0
self._tcxoDelay = 0
self._headerType = 0
self._implicitLen = 0
self._txIq = 0
self._rxIq = 0
self._invertIQ = 0
self._ldroAuto = True
self._br = 0
self._freqDev = 0
self._rxBw = 0
self._rxBwKhz = 0
self._pulseShape = 0
self._crcTypeFSK = 0
self._preambleLengthFSK = 0
self._addrComp = 0
self._syncWordLength = 0
self._whitening = 0
self._packetType = 0
self._dataRate = 0
self._packetLength = 0
self._preambleDetectorLength = 0
def begin(self, bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO=False, txIq=False, rxIq=False):
self._bwKhz = bw
self._sf = sf
self._bw = SX126X_LORA_BW_125_0
self._cr = SX126X_LORA_CR_4_7
self._ldro = 0x00
self._crcType = SX126X_LORA_CRC_ON
self._preambleLength = preambleLength
self._tcxoDelay = 0
self._headerType = SX126X_LORA_HEADER_EXPLICIT
self._implicitLen = 0xFF
self._txIq = txIq
self._rxIq = rxIq
self._invertIQ = SX126X_LORA_IQ_STANDARD
state = self.reset()
ASSERT(state)
state = self.standby()
ASSERT(state)
state = self.config(SX126X_PACKET_TYPE_LORA)
ASSERT(state)
if tcxoVoltage > 0.0:
state = self.setTCXO(tcxoVoltage)
ASSERT(state)
state = self.setSpreadingFactor(sf)
ASSERT(state)
state = self.setBandwidth(bw)
ASSERT(state)
state = self.setCodingRate(cr)
ASSERT(state)
state = self.setSyncWord(syncWord)
ASSERT(state)
state = self.setCurrentLimit(currentLimit)
ASSERT(state)
state = self.setPreambleLength(preambleLength)
ASSERT(state)
state = self.setDio2AsRfSwitch(True)
ASSERT(state)
if useRegulatorLDO:
state = self.setRegulatorLDO()
else:
state = self.setRegulatorDCDC()
return state
def beginFSK(self, br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, preambleDetectorLength, tcxoVoltage, useRegulatorLDO=False):
self._br = 21333
self._freqDev = 52428
self._rxBw = SX126X_GFSK_RX_BW_156_2
self._rxBwKhz = 156.2
self._pulseShape = SX126X_GFSK_FILTER_GAUSS_0_5
self._crcTypeFSK = SX126X_GFSK_CRC_2_BYTE_INV
self._preambleLengthFSK = preambleLength
self._addrComp = SX126X_GFSK_ADDRESS_FILT_OFF
self._preambleDetectorLength = preambleDetectorLength
state = self.reset()
ASSERT(state)
state = self.standby()
ASSERT(state)
state = self.config(SX126X_PACKET_TYPE_GFSK)
ASSERT(state)
if tcxoVoltage > 0.0:
state = self.setTCXO(tcxoVoltage)
ASSERT(state)
state = self.setBitRate(br)
ASSERT(state)
state = self.setFrequencyDeviation(freqDev)
ASSERT(state)
state = self.setRxBandwidth(rxBw)
ASSERT(state)
state = self.setCurrentLimit(currentLimit)
ASSERT(state)
state = self.setDataShaping(dataShaping)
ASSERT(state)
state = self.setPreambleLength(preambleLength)
ASSERT(state)
sync = [0x2D, 0x01]
state = self.setSyncWord(sync, 2)
ASSERT(state)
state = self.setWhitening(True, 0x0100)
ASSERT(state)
state = self.variablePacketLengthMode(SX126X_MAX_PACKET_LENGTH)
ASSERT(state)
state = self.setDio2AsRfSwitch(True)
ASSERT(state)
if useRegulatorLDO:
state = self.setRegulatorLDO()
else:
state = self.setRegulatorDCDC()
return state
def reset(self, verify=True):
if implementation.name == 'micropython':
self.rst.value(1)
sleep_us(150)
self.rst.value(0)
sleep_us(150)
self.rst.value(1)
sleep_us(150)
if implementation.name == 'circuitpython':
self.rst.value = True
sleep_us(150)
self.rst.value = False
sleep_us(150)
self.rst.value = True
sleep_us(150)
if not verify:
return ERR_NONE
start = ticks_ms()
while True:
state = self.standby()
if state == ERR_NONE:
return ERR_NONE
if abs(ticks_diff(start, ticks_ms())) >= 3000:
return state
sleep_ms(10)
def transmit(self, data, len_, addr=0):
state = self.standby()
ASSERT(state)
if len_ > SX126X_MAX_PACKET_LENGTH:
return ERR_PACKET_TOO_LONG
timeout = 0
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
timeout = int((self.getTimeOnAir(len_) * 3) / 2)
elif modem == SX126X_PACKET_TYPE_GFSK:
timeout = int(self.getTimeOnAir(len_) * 5)
else:
return ERR_UNKNOWN
state = self.startTransmit(data, len_, addr)
ASSERT(state)
start = ticks_us()
while not self.irq.value():
yield_()
if abs(ticks_diff(start, ticks_us())) > timeout:
self.clearIrqStatus()
self.standby()
return ERR_TX_TIMEOUT
elapsed = abs(ticks_diff(start, ticks_us()))
self._dataRate = (len_*8.0)/(float(elapsed)/1000000.0)
state = self.clearIrqStatus()
ASSERT(state)
state = self.standby()
return state
def receive(self, data, len_, timeout_en, timeout_ms):
state = self.standby()
ASSERT(state)
timeout = 0
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
symbolLength = float(1 << self._sf) / float(self._bwKhz)
timeout = int(symbolLength * 100.0 * 1000.0)
elif modem == SX126X_PACKET_TYPE_GFSK:
maxLen = len_
if len_ == 0:
maxLen = 0xFF
brBps = (float(SX126X_CRYSTAL_FREQ) * 1000000.0 * 32.0) / float(self._br)
timeout = int(((maxLen * 8.0) / brBps) * 1000000.0 * 5.0)
else:
return ERR_UNKNOWN
if timeout_ms == 0:
pass
else:
timeout = timeout_ms * 1000
if timeout_en:
timeoutValue = int(float(timeout) / 15.625)
else:
timeoutValue = SX126X_RX_TIMEOUT_NONE
state = self.startReceive(timeoutValue)
ASSERT(state)
start = ticks_us()
while not self.irq.value():
yield_()
if timeout_en:
if abs(ticks_diff(start, ticks_us())) > timeout:
self.fixImplicitTimeout()
self.clearIrqStatus()
self.standby()
return ERR_RX_TIMEOUT
if self._headerType == SX126X_LORA_HEADER_IMPLICIT and self.getPacketType() == SX126X_PACKET_TYPE_LORA:
state = self.fixImplicitTimeout()
ASSERT(state)
return self.readData(data, len_)
def transmitDirect(self, frf=0):
state = ERR_NONE
if frf != 0:
state = self.setRfFrequency(frf)
ASSERT(state)
data = [SX126X_CMD_NOP]
return self.SPIwriteCommand([SX126X_CMD_SET_TX_CONTINUOUS_WAVE], 1, data, 1)
def receiveDirect(self):
return ERR_UNKNOWN
def scanChannel(self):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
state = self.standby()
ASSERT(state)
state = self.setDioIrqParams(SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE, SX126X_IRQ_CAD_DETECTED | SX126X_IRQ_CAD_DONE)
ASSERT(state)
state = self.clearIrqStatus()
ASSERT(state)
state = self.setCad()
ASSERT(state)
while not self.irq.value():
yield_()
cadResult = self.getIrqStatus()
if cadResult & SX126X_IRQ_CAD_DETECTED:
self.clearIrqStatus()
return LORA_DETECTED
elif cadResult & SX126X_IRQ_CAD_DONE:
self.clearIrqStatus()
return CHANNEL_FREE
return ERR_UNKNOWN
def sleep(self, retainConfig=True):
sleepMode = [SX126X_SLEEP_START_WARM | SX126X_SLEEP_RTC_OFF]
if not retainConfig:
sleepMode = [SX126X_SLEEP_START_COLD | SX126X_SLEEP_RTC_OFF]
state = self.SPIwriteCommand([SX126X_CMD_SET_SLEEP], 1, sleepMode, 1, False)
sleep_us(500)
return state
def standby(self, mode=SX126X_STANDBY_RC):
data = [mode]
return self.SPIwriteCommand([SX126X_CMD_SET_STANDBY], 1, data, 1)
def setDio1Action(self, func):
try:
self.irq.callback(trigger=Pin.IRQ_RISING, handler=func) # Pycom variant uPy
except:
self.irq.irq(trigger=Pin.IRQ_RISING, handler=func) # Generic variant uPy
def clearDio1Action(self):
if implementation.name == 'micropython':
self.irq = Pin(self._irq, mode=Pin.IN)
if implementation.name == 'circuitpython':
self.irq = digitalio.DigitalInOut(self._irq)
self.irq.switch_to_input()
def startTransmit(self, data, len_, addr=0):
if len_ > SX126X_MAX_PACKET_LENGTH:
return ERR_PACKET_TOO_LONG
if self._addrComp != SX126X_GFSK_ADDRESS_FILT_OFF and len_ > (SX126X_MAX_PACKET_LENGTH - 1):
return ERR_PACKET_TOO_LONG
state = ERR_NONE
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
if self._txIq:
self._invertIQ = SX126X_LORA_IQ_INVERTED
else:
self._invertIQ = SX126X_LORA_IQ_STANDARD
if self._headerType == SX126X_LORA_HEADER_IMPLICIT:
if len_ != self._implicitLen:
return ERR_INVALID_PACKET_LENGTH
state = self.setPacketParams(self._preambleLength, self._crcType, len_, self._headerType, self._invertIQ)
elif modem == SX126X_PACKET_TYPE_GFSK:
if self._packetType == SX126X_GFSK_PACKET_FIXED:
if len_ != self._packetLength:
return ERR_INVALID_PACKET_LENGTH
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, len_, self._preambleDetectorLength)
else:
return ERR_UNKNOWN
ASSERT(state)
state = self.setDioIrqParams(SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT, SX126X_IRQ_TX_DONE)
ASSERT(state)
state = self.setBufferBaseAddress()
ASSERT(state)
state = self.writeBuffer(data, len_)
ASSERT(state)
state = self.clearIrqStatus()
ASSERT(state)
state = self.fixSensitivity()
ASSERT(state)
state = self.setTx(SX126X_TX_TIMEOUT_NONE)
ASSERT(state)
if implementation.name == 'micropython':
while self.gpio.value():
yield_()
if implementation.name == 'circuitpython':
while self.gpio.value:
yield_()
return state
def startReceive(self, timeout=SX126X_RX_TIMEOUT_INF):
state = ERR_NONE
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
if self._rxIq:
self._invertIQ = SX126X_LORA_IQ_INVERTED
else:
self._invertIQ = SX126X_LORA_IQ_STANDARD
state = self.setPacketParams(self._preambleLength, self._crcType, self._implicitLen, self._headerType, self._invertIQ)
elif modem == SX126X_PACKET_TYPE_GFSK:
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
else:
return ERR_UNKNOWN
ASSERT(state)
state = self.startReceiveCommon()
ASSERT(state)
state = self.setRx(timeout)
return state
def startReceiveDutyCycle(self, rxPeriod, sleepPeriod):
transitionTime = int(self._tcxoDelay + 1000)
sleepPeriod -= transitionTime
rxPeriodRaw = int((rxPeriod * 8) / 125)
sleepPeriodRaw = int((sleepPeriod * 8) / 125)
if rxPeriodRaw & 0xFF000000 or rxPeriodRaw == 0:
return ERR_INVALID_RX_PERIOD
if sleepPeriodRaw & 0xFF000000 or sleepPeriodRaw == 0:
return ERR_INVALID_SLEEP_PERIOD
state = self.startReceiveCommon()
ASSERT(state)
data = [int((rxPeriodRaw >> 16) & 0xFF), int((rxPeriodRaw >> 8) & 0xFF), int(rxPeriodRaw & 0xFF),
int((sleepPeriodRaw >> 16) & 0xFF),int((sleepPeriodRaw >> 8) & 0xFF),int(sleepPeriodRaw & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_RX_DUTY_CYCLE], 1, data, 6)
def startReceiveDutyCycleAuto(self, senderPreambleLength=0, minSymbols=8):
if senderPreambleLength == 0:
senderPreambleLength = self._preambleLength
sleepSymbols = int(senderPreambleLength - 2 * minSymbols)
if (2 * minSymbols) > senderPreambleLength:
return self.startReceive()
symbolLength = int(((10*1000) << self._sf) / (10 * self._bwKhz))
sleepPeriod = symbolLength * sleepSymbols
wakePeriod = int(max((symbolLength * (senderPreambleLength + 1) - (sleepPeriod - 1000)) / 2, symbolLength * (minSymbols + 1)))
if sleepPeriod < (self._tcxoDelay + 1016):
return self.startReceive()
return self.startReceiveDutyCycle(wakePeriod, sleepPeriod)
def startReceiveCommon(self):
state = self.setDioIrqParams(SX126X_IRQ_RX_DONE | SX126X_IRQ_TIMEOUT | SX126X_IRQ_CRC_ERR | SX126X_IRQ_HEADER_ERR, SX126X_IRQ_RX_DONE)
ASSERT(state)
state = self.setBufferBaseAddress()
ASSERT(state)
state = self.clearIrqStatus()
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
state = self.setPacketParams(self._preambleLength, self._crcType, self._implicitLen, self._headerType, self._invertIQ)
elif modem == SX126X_PACKET_TYPE_GFSK:
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType)
else:
return ERR_UNKNOWN
return state
def readData(self, data, len_):
state = self.standby()
ASSERT(state)
irq = self.getIrqStatus()
crcState = ERR_NONE
if irq & SX126X_IRQ_CRC_ERR or irq & SX126X_IRQ_HEADER_ERR:
crcState = ERR_CRC_MISMATCH
length = len_
if len_ == SX126X_MAX_PACKET_LENGTH:
length = self.getPacketLength()
state = self.readBuffer(data, length)
ASSERT(state)
state = self.clearIrqStatus()
ASSERT(crcState)
return state
def setBandwidth(self, bw):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
if not ((bw > 0) and (bw < 510)):
return ERR_INVALID_BANDWIDTH
bw_div2 = int(bw / 2 + 0.01)
switch = {3: SX126X_LORA_BW_7_8,
5: SX126X_LORA_BW_10_4,
7: SX126X_LORA_BW_15_6,
10: SX126X_LORA_BW_20_8,
15: SX126X_LORA_BW_31_25,
20: SX126X_LORA_BW_41_7,
31: SX126X_LORA_BW_62_5,
62: SX126X_LORA_BW_125_0,
125: SX126X_LORA_BW_250_0,
250: SX126X_LORA_BW_500_0}
try:
self._bw = switch[bw_div2]
except:
return ERR_INVALID_BANDWIDTH
self._bwKhz = bw
return self.setModulationParams(self._sf, self._bw, self._cr, self._ldro)
def setSpreadingFactor(self, sf):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
if not ((sf >= 5) and (sf <= 12)):
return ERR_INVALID_SPREADING_FACTOR
self._sf = sf
return self.setModulationParams(self._sf, self._bw, self._cr, self._ldro)
def setCodingRate(self, cr):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
if not ((cr >= 5) and (cr <= 8)):
return ERR_INVALID_CODING_RATE
self._cr = cr - 4
return self.setModulationParams(self._sf, self._bw, self._cr, self._ldro)
def setSyncWord(self, syncWord, *args):
if self.getPacketType() == SX126X_PACKET_TYPE_LORA:
if len(args) > 0:
controlBits = args[0]
else:
controlBits = 0x44
data = [int((syncWord & 0xF0) | ((controlBits & 0xF0) >> 4)), int(((syncWord & 0x0F) << 4) | (controlBits & 0x0F))]
return self.writeRegister(SX126X_REG_LORA_SYNC_WORD_MSB, data, 2)
elif self.getPacketType() == SX126X_PACKET_TYPE_GFSK:
len_ = args[0]
if len_ > 8:
return ERR_INVALID_SYNC_WORD
state = self.writeRegister(SX126X_REG_SYNC_WORD_0, syncWord, len_)
ASSERT(state)
self._syncWordLength = len_ * 8
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
return state
else:
return ERR_WRONG_MODEM
def setCurrentLimit(self, currentLimit):
if not ((currentLimit >= 0) and (currentLimit <= 140)):
return ERR_INVALID_CURRENT_LIMIT
rawLimit = [int(currentLimit / 2.5)]
return self.writeRegister(SX126X_REG_OCP_CONFIGURATION, rawLimit, 1)
def getCurrentLimit(self):
ocp = bytearray(1)
ocp_mv = memoryview(ocp)
self.readRegister(SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1)
return float(ocp[0]) * 2.5
def setPreambleLength(self, preambleLength):
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_LORA:
self._preambleLength = preambleLength
return self.setPacketParams(self._preambleLength, self._crcType, self._implicitLen, self._headerType, self._invertIQ)
elif modem == SX126X_PACKET_TYPE_GFSK:
self._preambleLengthFSK = preambleLength
return self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
return ERR_UNKNOWN
def setFrequencyDeviation(self, freqDev):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
if not (freqDev <= 200.0):
return ERR_INVALID_FREQUENCY_DEVIATION
freqDevRaw = int(((freqDev * 1000.0) * float(1 << 25)) / (SX126X_CRYSTAL_FREQ * 1000000.0))
self._freqDev = freqDevRaw
return self.setModulationParamsFSK(self._br, self._pulseShape, self._rxBw, self._freqDev)
def setBitRate(self, br):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
if not ((br >= 0.6) and (br <= 300.0)):
return ERR_INVALID_BIT_RATE
brRaw = int((SX126X_CRYSTAL_FREQ * 1000000.0 * 32.0) / (br * 1000.0))
self._br = brRaw
return self.setModulationParamsFSK(self._br, self._pulseShape, self._rxBw, self._freqDev)
def setRxBandwidth(self, rxBw):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
self._rxBwKhz = rxBw
if abs(rxBw - 4.8) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_4_8
elif abs(rxBw - 5.8) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_5_8
elif abs(rxBw - 7.3) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_7_3
elif abs(rxBw - 9.7) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_9_7
elif abs(rxBw - 11.7) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_11_7
elif abs(rxBw - 14.6) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_14_6
elif abs(rxBw - 19.5) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_19_5
elif abs(rxBw - 23.4) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_23_4
elif abs(rxBw - 29.3) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_29_3
elif abs(rxBw - 39.0) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_39_0
elif abs(rxBw - 46.9) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_46_9
elif abs(rxBw - 58.6) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_58_6
elif abs(rxBw - 78.2) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_78_2
elif abs(rxBw - 93.8) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_93_8
elif abs(rxBw - 117.3) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_117_3
elif abs(rxBw - 156.2) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_156_2
elif abs(rxBw - 187.2) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_187_2
elif abs(rxBw - 234.3) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_234_3
elif abs(rxBw - 312.0) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_312_0
elif abs(rxBw - 373.6) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_373_6
elif abs(rxBw - 467.0) <= 0.001:
self._rxBw = SX126X_GFSK_RX_BW_467_0
else:
return ERR_INVALID_RX_BANDWIDTH
return self.setModulationParamsFSK(self._br, self._pulseShape, self._rxBw, self._freqDev)
def setDataShaping(self, sh):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
sh *= 10.0
if abs(sh - 0.0) <= 0.001:
self._pulseShape = SX126X_GFSK_FILTER_NONE
elif abs(sh - 3.0) <= 0.001:
self._pulseShape = SX126X_GFSK_FILTER_GAUSS_0_3
elif abs(sh - 5.0) <= 0.001:
self._pulseShape = SX126X_GFSK_FILTER_GAUSS_0_5
elif abs(sh - 7.0) <= 0.001:
self._pulseShape = SX126X_GFSK_FILTER_GAUSS_0_7
elif abs(sh - 10.0) <= 0.001:
self._pulseShape = SX126X_GFSK_FILTER_GAUSS_1
else:
return ERR_INVALID_DATA_SHAPING
return self.setModulationParamsFSK(self._br, self._pulseShape, self._rxBw, self._freqDev)
def setSyncBits(self, syncWord, bitsLen):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
if bitsLen > 0x40:
return ERR_INVALID_SYNC_WORD
bytesLen = int(bitsLen / 8)
if (bitsLen % 8) != 0:
bytesLen += 1
state = self.writeRegister(SX126X_REG_SYNC_WORD_0, syncWord, bytesLen)
ASSERT(state)
self._syncWordLength = bitsLen
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
return state
def setNodeAddress(self, nodeAddr):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
self._addrComp = SX126X_GFSK_ADDRESS_FILT_NODE
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
ASSERT(state)
state = self.writeRegister(SX126X_REG_NODE_ADDRESS, [nodeAddr], 1)
return state
def setBroadcastAddress(self, broadAddr):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
self._addrComp = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
ASSERT(state)
state = self.writeRegister(SX126X_REG_BROADCAST_ADDRESS, [broadAddr], 1)
return state
def disableAddressFiltering(self):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
self._addrComp = SX126X_GFSK_ADDRESS_FILT_OFF
return self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
def setCRC(self, len_, initial=0x1D0F, polynomial=0x1021, inverted=True):
modem = self.getPacketType()
if modem == SX126X_PACKET_TYPE_GFSK:
if len_ == 0:
self._crcTypeFSK = SX126X_GFSK_CRC_OFF
elif len_ == 1:
if inverted:
self._crcTypeFSK = SX126X_GFSK_CRC_1_BYTE_INV
else:
self._crcTypeFSK = SX126X_GFSK_CRC_1_BYTE
elif len_ == 2:
if inverted:
self._crcTypeFSK = SX126X_GFSK_CRC_2_BYTE_INV
else:
self._crcTypeFSK = SX126X_GFSK_CRC_2_BYTE
else:
return ERR_INVALID_CRC_CONFIGURATION
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
ASSERT(state)
data = [int((initial >> 8) & 0xFF), int(initial & 0xFF)]
state = self.writeRegister(SX126X_REG_CRC_INITIAL_MSB, data, 2)
ASSERT(state)
data[0] = int((polynomial >> 8) & 0xFF)
data[1] = int(polynomial & 0xFF)
state = self.writeRegister(SX126X_REG_CRC_POLYNOMIAL_MSB, data, 2)
return state
elif modem == SX126X_PACKET_TYPE_LORA:
if len_:
self._crcType = SX126X_LORA_CRC_ON
else:
self._crcType = SX126X_LORA_CRC_OFF
return self.setPacketParams(self._preambleLength, self._crcType, self._implicitLen, self._headerType, self._invertIQ)
return ERR_UNKNOWN
def setWhitening(self, enabled, initial=0x0100):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
state = ERR_NONE
if enabled != True:
self._whitening = SX126X_GFSK_WHITENING_OFF
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
ASSERT(state)
else:
self._whitening = SX126X_GFSK_WHITENING_ON
data = bytearray(1)
data_mv = memoryview(data)
state = self.readRegister(SX126X_REG_WHITENING_INITIAL_MSB, data_mv, 1)
ASSERT(state)
data2 = [(data[0] & 0xFE) | int((initial >> 8) & 0x01), int(initial & 0xFF)]
state = self.writeRegister(SX126X_REG_WHITENING_INITIAL_MSB, data2, 2)
ASSERT(state)
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, self._packetType, self._packetLength, self._preambleDetectorLength)
ASSERT(state)
return state
def getDataRate(self):
return self._dataRate
def getRSSI(self):
packetStatus = self.getPacketStatus()
rssiPkt = int(packetStatus & 0xFF)
return -1.0 * rssiPkt/2.0
def getSNR(self):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
packetStatus = self.getPacketStatus()
snrPkt = int((packetStatus >> 8) & 0xFF)
if snrPkt < 128:
return snrPkt/4.0
else:
return (snrPkt - 256)/4.0
def getPacketLength(self, update=True):
rxBufStatus = bytearray(2)
rxBufStatus_mv = memoryview(rxBufStatus)
self.SPIreadCommand([SX126X_CMD_GET_RX_BUFFER_STATUS], 1, rxBufStatus_mv, 2)
return rxBufStatus[0]
def fixedPacketLengthMode(self, len_=SX126X_MAX_PACKET_LENGTH):
return self.setPacketMode(SX126X_GFSK_PACKET_FIXED, len_)
def variablePacketLengthMode(self, maxLen=SX126X_MAX_PACKET_LENGTH):
return self.setPacketMode(SX126X_GFSK_PACKET_VARIABLE, maxLen)
def getTimeOnAir(self, len_):
if self.getPacketType() == SX126X_PACKET_TYPE_LORA:
symbolLength_us = int(((1000 * 10) << self._sf) / (self._bwKhz * 10))
sfCoeff1_x4 = 17
sfCoeff2 = 8
if self._sf == 5 or self._sf == 6:
sfCoeff1_x4 = 25
sfCoeff2 = 0
sfDivisor = 4*self._sf
if symbolLength_us >= 16000:
sfDivisor = 4*(self._sf - 2)
bitsPerCrc = 16
N_symbol_header = 20 if self._headerType == SX126X_LORA_HEADER_EXPLICIT else 0
bitCount = int(8 * len_ + self._crcType * bitsPerCrc - 4 * self._sf + sfCoeff2 + N_symbol_header)
if bitCount < 0:
bitCount = 0
nPreCodedSymbols = int((bitCount + (sfDivisor - 1)) / sfDivisor)
nSymbol_x4 = int((self._preambleLength + 8) * 4 + sfCoeff1_x4 + nPreCodedSymbols * (self._cr + 4) * 4)
return int((symbolLength_us * nSymbol_x4) / 4)
else:
return int((len_ * 8 * self._br) / (SX126X_CRYSTAL_FREQ * 32))
def implicitHeader(self, len_):
return self.setHeaderType(SX126X_LORA_HEADER_IMPLICIT, len_)
def explicitHeader(self):
return self.setHeaderType(SX126X_LORA_HEADER_EXPLICIT)
def setRegulatorLDO(self):
return self.setRegulatorMode(SX126X_REGULATOR_LDO)
def setRegulatorDCDC(self):
return self.setRegulatorMode(SX126X_REGULATOR_DC_DC)
def setEncoding(self, encoding):
return self.setWhitening(encoding)
def forceLDRO(self, enable):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
self._ldroAuto = False
self._ldro = enable
return self.setModulationParams(self._sf, self._bw, self._cr, self._ldro)
def autoLDRO(self):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
self._ldroAuto = True
return self.setModulationParams(self._sf, self._bw, self._cr, self._ldro)
def setTCXO(self, voltage, delay=5000):
self.standby()
if self.getDeviceErrors() & SX126X_XOSC_START_ERR:
self.clearDeviceErrors()
if abs(voltage - 0.0) <= 0.001:
return self.reset()
data = [0,0,0,0]
if abs(voltage - 1.6) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_1_6
elif abs(voltage - 1.7) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_1_7
elif abs(voltage - 1.8) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_1_8
elif abs(voltage - 2.2) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_2_2
elif abs(voltage - 2.4) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_2_4
elif abs(voltage - 2.7) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_2_7
elif abs(voltage - 3.0) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_3_0
elif abs(voltage - 3.3) <= 0.001:
data[0] = SX126X_DIO3_OUTPUT_3_3
else:
return ERR_INVALID_TCXO_VOLTAGE
delayValue = int(float(delay) / 15.625)
data[1] = int((delayValue >> 16) & 0xFF)
data[2] = int((delayValue >> 8) & 0xFF)
data[3] = int(delayValue & 0xFF)
self._tcxoDelay = delay
return self.SPIwriteCommand([SX126X_CMD_SET_DIO3_AS_TCXO_CTRL], 1, data, 4)
def setDio2AsRfSwitch(self, enable=True):
data = [0]
if enable:
data = [SX126X_DIO2_AS_RF_SWITCH]
else:
data = [SX126X_DIO2_AS_IRQ]
return self.SPIwriteCommand([SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL], 1, data, 1)
def setTx(self, timeout=0):
data = [int((timeout >> 16) & 0xFF), int((timeout >> 8) & 0xFF), int(timeout & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_TX], 1, data, 3)
def setRx(self, timeout):
data = [int((timeout >> 16) & 0xFF), int((timeout >> 8) & 0xFF), int(timeout & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_RX], 1, data, 3)
def setCad(self):
return self.SPIwriteCommand([SX126X_CMD_SET_CAD], 1, [], 0)
def setPaConfig(self, paDutyCycle, deviceSel, hpMax=SX126X_PA_CONFIG_HP_MAX, paLut=SX126X_PA_CONFIG_PA_LUT):
data = [paDutyCycle, hpMax, deviceSel, paLut]
return self.SPIwriteCommand([SX126X_CMD_SET_PA_CONFIG], 1, data, 4)
def writeRegister(self, addr, data, numBytes):
cmd = [SX126X_CMD_WRITE_REGISTER, int((addr >> 8) & 0xFF), int(addr & 0xFF)]
state = self.SPIwriteCommand(cmd, 3, data, numBytes)
return state
def readRegister(self, addr, data, numBytes):
cmd = [SX126X_CMD_READ_REGISTER, int((addr >> 8) & 0xFF), int(addr & 0xFF)]
return self.SPItransfer(cmd, 3, False, [], data, numBytes, True)
def writeBuffer(self, data, numBytes, offset=0x00):
cmd = [SX126X_CMD_WRITE_BUFFER, offset]
state = self.SPIwriteCommand(cmd, 2, data, numBytes)
return state
def readBuffer(self, data, numBytes):
cmd = [SX126X_CMD_READ_BUFFER, SX126X_CMD_NOP]
state = self.SPIreadCommand(cmd, 2, data, numBytes)
return state
def setDioIrqParams(self, irqMask, dio1Mask, dio2Mask=SX126X_IRQ_NONE, dio3Mask=SX126X_IRQ_NONE):
data = [int((irqMask >> 8) & 0xFF), int(irqMask & 0xFF),
int((dio1Mask >> 8) & 0xFF), int(dio1Mask & 0xFF),
int((dio2Mask >> 8) & 0xFF), int(dio2Mask & 0xFF),
int((dio3Mask >> 8) & 0xFF), int(dio3Mask & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_DIO_IRQ_PARAMS], 1, data, 8)
def getIrqStatus(self):
data = bytearray(2)
data_mv = memoryview(data)
self.SPIreadCommand([SX126X_CMD_GET_IRQ_STATUS], 1, data_mv, 2)
return int((data[0] << 8) | data[1])
def clearIrqStatus(self, clearIrqParams=SX126X_IRQ_ALL):
data = [int((clearIrqParams >> 8) & 0xFF), int(clearIrqParams & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_CLEAR_IRQ_STATUS], 1, data, 2)
def setRfFrequency(self, frf):
data = [int((frf >> 24) & 0xFF),
int((frf >> 16) & 0xFF),
int((frf >> 8) & 0xFF),
int(frf & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_RF_FREQUENCY], 1, data, 4)
def calibrateImage(self, data):
return self.SPIwriteCommand([SX126X_CMD_CALIBRATE_IMAGE], 1, data, 2)
def getPacketType(self):
data = bytearray([0xFF])
data_mv = memoryview(data)
self.SPIreadCommand([SX126X_CMD_GET_PACKET_TYPE], 1, data_mv, 1)
return data[0]
def setTxParams(self, power, rampTime=SX126X_PA_RAMP_200U):
data = [power, rampTime]
return self.SPIwriteCommand([SX126X_CMD_SET_TX_PARAMS], 1, data, 2)
def setPacketMode(self, mode, len_):
if self.getPacketType() != SX126X_PACKET_TYPE_GFSK:
return ERR_WRONG_MODEM
state = self.setPacketParamsFSK(self._preambleLengthFSK, self._crcTypeFSK, self._syncWordLength, self._addrComp, self._whitening, mode, len_, self._preambleDetectorLength)
ASSERT(state)
self._packetType = mode
self._packetLength = len_
return state
def setHeaderType(self, headerType, len_=0xFF):
if self.getPacketType() != SX126X_PACKET_TYPE_LORA:
return ERR_WRONG_MODEM
state = self.setPacketParams(self._preambleLength, self._crcType, len_, headerType, self._invertIQ)
ASSERT(state)
self._headerType = headerType
self._implicitLen = len_
return state
def setModulationParams(self, sf, bw, cr, ldro):
if self._ldroAuto:
symbolLength = float((1 << self._sf)) / float(self._bwKhz)
if symbolLength >= 16.0:
self._ldro = SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON
else:
self._ldro = SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF
else:
self._ldro = ldro
data = [sf, bw, cr, self._ldro]
return self.SPIwriteCommand([SX126X_CMD_SET_MODULATION_PARAMS], 1, data, 4)
def setModulationParamsFSK(self, br, pulseShape, rxBw, freqDev):
data = [int((br >> 16) & 0xFF), int((br >> 8) & 0xFF), int(br & 0xFF),
pulseShape, rxBw,
int((freqDev >> 16) & 0xFF), int((freqDev >> 8) & 0xFF), int(freqDev & 0xFF)]
return self.SPIwriteCommand([SX126X_CMD_SET_MODULATION_PARAMS], 1, data, 8)
def setPacketParams(self, preambleLength, crcType, payloadLength, headerType, invertIQ=SX126X_LORA_IQ_STANDARD):
state = self.fixInvertedIQ(invertIQ)
ASSERT(state)
data = [int((preambleLength >> 8) & 0xFF), int(preambleLength & 0xFF),
headerType, payloadLength, crcType, invertIQ]
return self.SPIwriteCommand([SX126X_CMD_SET_PACKET_PARAMS], 1, data, 6)
def setPacketParamsFSK(self, preambleLength, crcType, syncWordLength, addrComp, whitening, packetType=SX126X_GFSK_PACKET_VARIABLE, payloadLength=0xFF, preambleDetectorLength=SX126X_GFSK_PREAMBLE_DETECT_16):
data = [int((preambleLength >> 8) & 0xFF), int(preambleLength & 0xFF),
preambleDetectorLength, syncWordLength, addrComp,
packetType, payloadLength, crcType, whitening]
return self.SPIwriteCommand([SX126X_CMD_SET_PACKET_PARAMS], 1, data, 9)
def setBufferBaseAddress(self, txBaseAddress=0x00, rxBaseAddress=0x00):
data = [txBaseAddress, rxBaseAddress]
return self.SPIwriteCommand([SX126X_CMD_SET_BUFFER_BASE_ADDRESS], 1, data, 2)
def setRegulatorMode(self, mode):
data = [mode]
return self.SPIwriteCommand([SX126X_CMD_SET_REGULATOR_MODE], 1, data, 1)
def getStatus(self):
data = bytearray(1)
data_mv = memoryview(data)
self.SPIreadCommand([SX126X_CMD_GET_STATUS], 1, data_mv, 1)
return data[0]
def getPacketStatus(self):
data = bytearray(3)
data_mv = memoryview(data)
self.SPIreadCommand([SX126X_CMD_GET_PACKET_STATUS], 1, data_mv, 3)
return (data[0] << 16) | (data[1] << 8) | data[2]
def getDeviceErrors(self):
data = bytearray(2)
data_mv = memoryview(data)
self.SPIreadCommand([SX126X_CMD_GET_DEVICE_ERRORS], 1, data_mv, 2)
opError = ((data[0] & 0xFF) << 8) & data[1]
return opError
def clearDeviceErrors(self):
data = [SX126X_CMD_NOP, SX126X_CMD_NOP]
return self.SPIwriteCommand([SX126X_CMD_CLEAR_DEVICE_ERRORS], 1, data, 2)
def setFrequencyRaw(self, freq):
frf = int((freq * (1 << SX126X_DIV_EXPONENT)) / SX126X_CRYSTAL_FREQ)
return self.setRfFrequency(frf)
def fixSensitivity(self):
sensitivityConfig = bytearray(1)
sensitivityConfig_mv = memoryview(sensitivityConfig)
state = self.readRegister(SX126X_REG_SENSITIVITY_CONFIG, sensitivityConfig_mv, 1)
ASSERT(state)
if self.getPacketType() == SX126X_PACKET_TYPE_LORA and abs(self._bwKhz - 500.0) <= 0.001:
sensitivityConfig_mv[0] &= 0xFB
else:
sensitivityConfig_mv[0] |= 0x04
return self.writeRegister(SX126X_REG_SENSITIVITY_CONFIG, sensitivityConfig, 1)
def fixPaClamping(self):
clampConfig = bytearray(1)
clampConfig_mv = memoryview(clampConfig)
state = self.readRegister(SX126X_REG_TX_CLAMP_CONFIG, clampConfig_mv, 1)
ASSERT(state)
clampConfig_mv[0] |= 0x1E
return self.writeRegister(SX126X_REG_TX_CLAMP_CONFIG, clampConfig, 1)
def fixImplicitTimeout(self):
if not (self._headerType == SX126X_LORA_HEADER_IMPLICIT and self.getPacketType() == SX126X_PACKET_TYPE_LORA):
return ERR_WRONG_MODEM
rtcStop = [0x00]
state = self.writeRegister(SX126X_REG_RTC_STOP, rtcStop, 1)
ASSERT(state)
rtcEvent = bytearray(1)
rtcEvent_mv = memoryview(rtcEvent)
state = self.readRegister(SX126X_REG_RTC_EVENT, rtcEvent_mv, 1)
ASSERT(state)
rtcEvent_mv[0] |= 0x02
return self.writeRegister(SX126X_REG_RTC_EVENT, rtcEvent, 1)
def fixInvertedIQ(self, iqConfig):
iqConfigCurrent = bytearray(1)
iqConfigCurrent_mv = memoryview(iqConfigCurrent)
state = self.readRegister(SX126X_REG_IQ_CONFIG, iqConfigCurrent_mv, 1)
ASSERT(state)
if iqConfig == SX126X_LORA_IQ_STANDARD:
iqConfigCurrent_mv[0] &= 0xFB
else:
iqConfigCurrent_mv[0] |= 0x04
return self.writeRegister(SX126X_REG_IQ_CONFIG, iqConfigCurrent, 1)
def config(self, modem):
state = self.setBufferBaseAddress()
ASSERT(state)
data = [0,0,0,0,0,0,0]
data[0] = modem
state = self.SPIwriteCommand([SX126X_CMD_SET_PACKET_TYPE], 1, data, 1)
ASSERT(state)
data[0] = SX126X_RX_TX_FALLBACK_MODE_STDBY_RC
state = self.SPIwriteCommand([SX126X_CMD_SET_RX_TX_FALLBACK_MODE], 1, data, 1)
ASSERT(state)
data[0] = SX126X_CAD_ON_8_SYMB
data[1] = self._sf + 13
data[2] = 10
data[3] = SX126X_CAD_GOTO_STDBY
data[4] = 0x00
data[5] = 0x00
data[6] = 0x00
state = self.SPIwriteCommand([SX126X_CMD_SET_CAD_PARAMS], 1, data, 7)
ASSERT(state)
state = self.clearIrqStatus()
state |= self.setDioIrqParams(SX126X_IRQ_NONE, SX126X_IRQ_NONE)
ASSERT(state)
data[0] = SX126X_CALIBRATE_ALL
state = self.SPIwriteCommand([SX126X_CMD_CALIBRATE], 1, data, 1)
ASSERT(state)
sleep_ms(5)
if implementation.name == 'micropython':
while self.gpio.value():
yield_()
if implementation.name == 'circuitpython':
while self.gpio.value:
yield_()
return ERR_NONE
def SPIwriteCommand(self, cmd, cmdLen, data, numBytes, waitForBusy=True):
return self.SPItransfer(cmd, cmdLen, True, data, [], numBytes, waitForBusy)
def SPIreadCommand(self, cmd, cmdLen, data, numBytes, waitForBusy=True):
return self.SPItransfer(cmd, cmdLen, False, [], data, numBytes, waitForBusy)
def SPItransfer(self, cmd, cmdLen, write, dataOut, dataIn, numBytes, waitForBusy, timeout=5000):
if implementation.name == 'micropython':
self.cs.value(0)
start = ticks_ms()
while self.gpio.value():
yield_()
if abs(ticks_diff(start, ticks_ms())) >= timeout:
self.cs.value(1)
return ERR_SPI_CMD_TIMEOUT
for i in range(cmdLen):
self.spi.write(cmd[i])
if implementation.name == 'circuitpython':
while not self.spi.try_lock():
pass
self.cs.value = False
start = ticks_ms()
while self.gpio.value:
yield_()
if abs(ticks_diff(start, ticks_ms())) >= timeout:
self.cs.value = True
self.spi.unlock()
return ERR_SPI_CMD_TIMEOUT
for i in range(cmdLen):
self.spi.write(bytes([cmd[i]]))
in_ = bytearray(1)
status = 0
if write:
for i in range(numBytes):
if implementation.name == 'micropython':
in_ = self.spi.read(1, write=dataOut[i])
if implementation.name == 'circuitpython':
self.spi.write_readinto(bytes([dataOut[i]]), in_)
if (in_[0] & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT or\
(in_[0] & 0b00001110) == SX126X_STATUS_CMD_INVALID or\
(in_[0] & 0b00001110) == SX126X_STATUS_CMD_FAILED:
status = in_[0] & 0b00001110
break
elif (in_[0] == 0x00) or (in_[0] == 0xFF):
status = SX126X_STATUS_SPI_FAILED
break
else:
if implementation.name == 'micropython':
in_ = self.spi.read(1, write=SX126X_CMD_NOP)
if implementation.name == 'circuitpython':
self.spi.readinto(in_)
if (in_[0] & 0b00001110) == SX126X_STATUS_CMD_TIMEOUT or\
(in_[0] & 0b00001110) == SX126X_STATUS_CMD_INVALID or\
(in_[0] & 0b00001110) == SX126X_STATUS_CMD_FAILED:
status = in_[0] & 0b00001110
elif (in_[0] == 0x00) or (in_[0] == 0xFF):
status = SX126X_STATUS_SPI_FAILED
else:
if implementation.name == 'micropython':
for i in range(numBytes):
dataIn[i] = self.spi.read(1, write=SX126X_CMD_NOP)[0]
if implementation.name == 'circuitpython':
for i in range(numBytes):
self.spi.readinto(in_)
dataIn[i] = in_[0]
if implementation.name == 'micropython':
self.cs.value(1)
if implementation.name == 'circuitpython':
self.cs.value = True
self.spi.unlock()
if waitForBusy:
sleep_us(1)
start = ticks_ms()
if implementation.name == 'micropython':
while self.gpio.value():
yield_()
if abs(ticks_diff(start, ticks_ms())) >= timeout:
status = SX126X_STATUS_CMD_TIMEOUT
break
if implementation.name == 'circuitpython':
while self.gpio.value:
yield_()
if abs(ticks_diff(start, ticks_ms())) >= timeout:
status = SX126X_STATUS_CMD_TIMEOUT
break
switch = {SX126X_STATUS_CMD_TIMEOUT: ERR_SPI_CMD_TIMEOUT,
SX126X_STATUS_CMD_INVALID: ERR_SPI_CMD_INVALID,
SX126X_STATUS_CMD_FAILED: ERR_SPI_CMD_FAILED,
SX126X_STATUS_SPI_FAILED: ERR_CHIP_NOT_FOUND}
try:
return switch[status]
except:
return ERR_NONE
`
i'll not change anything. just change my Pin ports to appay pyboard_v1.1_cn boards.
Can try to change line 46 to the following code,
self.spi = SPI(2, baudrate=2000000, sck=Pin(clk), mosi=Pin(mosi), miso=Pin(miso))
okey,trying...
now new problem say:
ValueError: explicit choice of sck/mosi/miso is not implemented
how about this?
self.spi = SPI(2, baudrate=2000000)
The pin of your SPI connection should be based on id as stated here.
In your case id=2 should be, (NSS, SCK, MISO, MOSI) = (Y5, Y6, Y7, Y8) = (PB12, PB13, PB14, PB15)
Sorry, I don't have pyboard in hand, its difficult for me to debug.
yes , it's 'B12=Y5=NSS \ B13=Y6=SCK \ B14=Y7=MISO \ B15=Y8=MOSI' , so i think self.spi = SPI(2, baudrate=2000000, sck=Pin(clk), mosi=Pin(mosi), miso=Pin(miso))
match that : Y6=SCK \ Y8=MOSI \ Y7=MISO . it's no problem right?
sck, mosi and miso arguments are not implemented on micropython port for pyboard, should remove that from SPI object.
Just use self.spi = SPI(2, baudrate=2000000)
okey, try agin.
guy. new problem here:
Traceback (most recent call last): File "main.py", line 11, in <module> File "sx1268.py", line 27, in begin File "sx126x.py", line 116, in begin File "sx126x.py", line 241, in reset File "sx126x.py", line 390, in standby File "sx126x.py", line 1271, in SPIwriteCommand File "sx126x.py", line 1288, in SPItransfer TypeError: object with buffer protocol required
i'll changed :
with sx126x.py code:
line 40 def __init__(self, cs, irq, rst, gpio):
line 46 self.spi = SPI(2, baudrate=2000000)
line 44 self.spi = SPI(2, mode=SPI.MASTER, baudrate=2000000)
with sx1268.py code:
line 19 def __init__(self, cs, irq, rst, gpio):
line 20 super().__init__(cs, irq, rst, gpio)
try change the followings,
self.spi.write(bytes([cmd[i]]))
in_ = self.spi.read(1, write=bytes([dataOut[i]]))
in_ = self.spi.read(1, write=bytes([SX126X_CMD_NOP]))
dataIn[i] = self.spi.read(1, write=bytes([SX126X_CMD_NOP]))[0]
got it! try again.
changed say:
Traceback (most recent call last):
File "main.py", line 11, in
try change the following lines,
line 1311 to in_ = self.spi.read(1, bytes([dataOut[i]]))
line 1326 to in_ = self.spi.read(1, bytes([SX126X_CMD_NOP]))
line 1340 to dataIn[i] = self.spi.read(1, bytes([SX126X_CMD_NOP]))[0]
changed say:
Traceback (most recent call last):
File "main.py", line 11, in
try change the following lines,
line 1311 to in = self.spi.read(1, dataOut[i]) line 1326 to in = self.spi.read(1, SX126X_CMD_NOP) line 1340 to dataIn[i] = self.spi.read(1, SX126X_CMD_NOP)[0]
got it! change right now...
resay:
Traceback (most recent call last):
File "main.py", line 11, in
May I know what frequency you are using? SX1268 is meant for 410MHz to 810 MHz
just default frequency . because i want to conn 2 sx1268 modules. just useing RX and TX somthing text will be okey. so i have 2 sx1268 modules here.
the default example is using sx1262, try to change that and your frequency.
so like edit right:
sx.begin(freq=433
, bw=500.0, sf=12, cr=8, syncWord=0x12,
power=-5, currentLimit=60.0, preambleLength=8,
implicit=False, implicitLen=0xFF,
crcOn=True, txIq=False, rxIq=False,
tcxoVoltage=1.7, useRegulatorLDO=False, blocking=True)
yes
i'll changed that:
freq=434.0, bw=125.0, sf=9, cr=7, syncWord=SX126X_SYNC_WORD_PRIVATE, power=14, currentLimit=60.0, preambleLength=8, implicit=False, implicitLen=0xFF, crcOn=True, txIq=False, rxIq=False, tcxoVoltage=1.6, useRegulatorLDO=False, blocking=True
copy from sx1268.py code line 23
but got a new problem say:
Traceback (most recent call last):
File "main.py", line 11, in
SX126X_SYNC_WORD_PRIVATE = 0x12
Can you check your sx1268, does it comes with TCXO? If it does, try to set the correct voltage with tcxoVoltage,
or disable it by setting to 0 if it is not present.
oh !!!!! guy! did it! it's work!!! so! cool!
ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE b'Hello World!' ERR_NONE
i'll useing pyboard_v1.1_cn and pyboard_plus to driver here!
thank you guy ! you're so nice to me.! did you have chat tools number ? join you friend and show you somthing...:)
Glad to hear that everything's worked out.
hey! i look at your micropySX126X drivers in 2days ago . but i want know how to working that ? if all files push down to mpy-boards . like pyboard_v1.1 . it's not working! return msg say : no memory .... so um ~~ how can i cut driver to mini ver? come on suggest something for me. thanks so much!