LoRa, MQTT and Oled
This commit is contained in:
@@ -0,0 +1,413 @@
|
||||
from sys import implementation
|
||||
|
||||
if implementation.name == 'micropython':
|
||||
from utime import sleep_ms
|
||||
|
||||
if implementation.name == 'circuitpython':
|
||||
from time import sleep
|
||||
def sleep_ms(ms):
|
||||
sleep(ms/1000)
|
||||
|
||||
def ASSERT(state):
|
||||
assert state == ERR_NONE, ERROR[state]
|
||||
|
||||
def yield_():
|
||||
sleep_ms(1)
|
||||
|
||||
SX126X_FREQUENCY_STEP_SIZE = 0.9536743164
|
||||
SX126X_MAX_PACKET_LENGTH = const(255)
|
||||
SX126X_CRYSTAL_FREQ = 32.0
|
||||
SX126X_DIV_EXPONENT = const(25)
|
||||
SX126X_CMD_NOP = const(0x00)
|
||||
SX126X_CMD_SET_SLEEP = const(0x84)
|
||||
SX126X_CMD_SET_STANDBY = const(0x80)
|
||||
SX126X_CMD_SET_FS = const(0xC1)
|
||||
SX126X_CMD_SET_TX = const(0x83)
|
||||
SX126X_CMD_SET_RX = const(0x82)
|
||||
SX126X_CMD_STOP_TIMER_ON_PREAMBLE = const(0x9F)
|
||||
SX126X_CMD_SET_RX_DUTY_CYCLE = const(0x94)
|
||||
SX126X_CMD_SET_CAD = const(0xC5)
|
||||
SX126X_CMD_SET_TX_CONTINUOUS_WAVE = const(0xD1)
|
||||
SX126X_CMD_SET_TX_INFINITE_PREAMBLE = const(0xD2)
|
||||
SX126X_CMD_SET_REGULATOR_MODE = const(0x96)
|
||||
SX126X_CMD_CALIBRATE = const(0x89)
|
||||
SX126X_CMD_CALIBRATE_IMAGE = const(0x98)
|
||||
SX126X_CMD_SET_PA_CONFIG = const(0x95)
|
||||
SX126X_CMD_SET_RX_TX_FALLBACK_MODE = const(0x93)
|
||||
SX126X_CMD_WRITE_REGISTER = const(0x0D)
|
||||
SX126X_CMD_READ_REGISTER = const(0x1D)
|
||||
SX126X_CMD_WRITE_BUFFER = const(0x0E)
|
||||
SX126X_CMD_READ_BUFFER = const(0x1E)
|
||||
SX126X_CMD_SET_DIO_IRQ_PARAMS = const(0x08)
|
||||
SX126X_CMD_GET_IRQ_STATUS = const(0x12)
|
||||
SX126X_CMD_CLEAR_IRQ_STATUS = const(0x02)
|
||||
SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL = const(0x9D)
|
||||
SX126X_CMD_SET_DIO3_AS_TCXO_CTRL = const(0x97)
|
||||
SX126X_CMD_SET_RF_FREQUENCY = const(0x86)
|
||||
SX126X_CMD_SET_PACKET_TYPE = const(0x8A)
|
||||
SX126X_CMD_GET_PACKET_TYPE = const(0x11)
|
||||
SX126X_CMD_SET_TX_PARAMS = const(0x8E)
|
||||
SX126X_CMD_SET_MODULATION_PARAMS = const(0x8B)
|
||||
SX126X_CMD_SET_PACKET_PARAMS = const(0x8C)
|
||||
SX126X_CMD_SET_CAD_PARAMS = const(0x88)
|
||||
SX126X_CMD_SET_BUFFER_BASE_ADDRESS = const(0x8F)
|
||||
SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT = const(0x0A)
|
||||
SX126X_CMD_GET_STATUS = const(0xC0)
|
||||
SX126X_CMD_GET_RSSI_INST = const(0x15)
|
||||
SX126X_CMD_GET_RX_BUFFER_STATUS = const(0x13)
|
||||
SX126X_CMD_GET_PACKET_STATUS = const(0x14)
|
||||
SX126X_CMD_GET_DEVICE_ERRORS = const(0x17)
|
||||
SX126X_CMD_CLEAR_DEVICE_ERRORS = const(0x07)
|
||||
SX126X_CMD_GET_STATS = const(0x10)
|
||||
SX126X_CMD_RESET_STATS = const(0x00)
|
||||
SX126X_REG_WHITENING_INITIAL_MSB = const(0x06B8)
|
||||
SX126X_REG_WHITENING_INITIAL_LSB = const(0x06B9)
|
||||
SX126X_REG_CRC_INITIAL_MSB = const(0x06BC)
|
||||
SX126X_REG_CRC_INITIAL_LSB = const(0x06BD)
|
||||
SX126X_REG_CRC_POLYNOMIAL_MSB = const(0x06BE)
|
||||
SX126X_REG_CRC_POLYNOMIAL_LSB = const(0x06BF)
|
||||
SX126X_REG_SYNC_WORD_0 = const(0x06C0)
|
||||
SX126X_REG_SYNC_WORD_1 = const(0x06C1)
|
||||
SX126X_REG_SYNC_WORD_2 = const(0x06C2)
|
||||
SX126X_REG_SYNC_WORD_3 = const(0x06C3)
|
||||
SX126X_REG_SYNC_WORD_4 = const(0x06C4)
|
||||
SX126X_REG_SYNC_WORD_5 = const(0x06C5)
|
||||
SX126X_REG_SYNC_WORD_6 = const(0x06C6)
|
||||
SX126X_REG_SYNC_WORD_7 = const(0x06C7)
|
||||
SX126X_REG_NODE_ADDRESS = const(0x06CD)
|
||||
SX126X_REG_BROADCAST_ADDRESS = const(0x06CE)
|
||||
SX126X_REG_LORA_SYNC_WORD_MSB = const(0x0740)
|
||||
SX126X_REG_LORA_SYNC_WORD_LSB = const(0x0741)
|
||||
SX126X_REG_RANDOM_NUMBER_0 = const(0x0819)
|
||||
SX126X_REG_RANDOM_NUMBER_1 = const(0x081A)
|
||||
SX126X_REG_RANDOM_NUMBER_2 = const(0x081B)
|
||||
SX126X_REG_RANDOM_NUMBER_3 = const(0x081C)
|
||||
SX126X_REG_RX_GAIN = const(0x08AC)
|
||||
SX126X_REG_OCP_CONFIGURATION = const(0x08E7)
|
||||
SX126X_REG_XTA_TRIM = const(0x0911)
|
||||
SX126X_REG_XTB_TRIM = const(0x0912)
|
||||
SX126X_REG_SENSITIVITY_CONFIG = const(0x0889)
|
||||
SX126X_REG_TX_CLAMP_CONFIG = const(0x08D8)
|
||||
SX126X_REG_RTC_STOP = const(0x0920)
|
||||
SX126X_REG_RTC_EVENT = const(0x0944)
|
||||
SX126X_REG_IQ_CONFIG = const(0x0736)
|
||||
SX126X_REG_RX_GAIN_RETENTION_0 = const(0x029F)
|
||||
SX126X_REG_RX_GAIN_RETENTION_1 = const(0x02A0)
|
||||
SX126X_REG_RX_GAIN_RETENTION_2 = const(0x02A1)
|
||||
SX126X_SLEEP_START_COLD = const(0b00000000)
|
||||
SX126X_SLEEP_START_WARM = const(0b00000100)
|
||||
SX126X_SLEEP_RTC_OFF = const(0b00000000)
|
||||
SX126X_SLEEP_RTC_ON = const(0b00000001)
|
||||
SX126X_STANDBY_RC = const(0x00)
|
||||
SX126X_STANDBY_XOSC = const(0x01)
|
||||
SX126X_RX_TIMEOUT_NONE = const(0x000000)
|
||||
SX126X_RX_TIMEOUT_INF = const(0xFFFFFF)
|
||||
SX126X_TX_TIMEOUT_NONE = const(0x000000)
|
||||
SX126X_STOP_ON_PREAMBLE_OFF = const(0x00)
|
||||
SX126X_STOP_ON_PREAMBLE_ON = const(0x01)
|
||||
SX126X_REGULATOR_LDO = const(0x00)
|
||||
SX126X_REGULATOR_DC_DC = const(0x01)
|
||||
SX126X_CALIBRATE_IMAGE_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_IMAGE_ON = const(0b01000000)
|
||||
SX126X_CALIBRATE_ADC_BULK_P_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_ADC_BULK_P_ON = const(0b00100000)
|
||||
SX126X_CALIBRATE_ADC_BULK_N_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_ADC_BULK_N_ON = const(0b00010000)
|
||||
SX126X_CALIBRATE_ADC_PULSE_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_ADC_PULSE_ON = const(0b00001000)
|
||||
SX126X_CALIBRATE_PLL_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_PLL_ON = const(0b00000100)
|
||||
SX126X_CALIBRATE_RC13M_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_RC13M_ON = const(0b00000010)
|
||||
SX126X_CALIBRATE_RC64K_OFF = const(0b00000000)
|
||||
SX126X_CALIBRATE_RC64K_ON = const(0b00000001)
|
||||
SX126X_CALIBRATE_ALL = const(0b01111111)
|
||||
SX126X_CAL_IMG_430_MHZ_1 = const(0x6B)
|
||||
SX126X_CAL_IMG_430_MHZ_2 = const(0x6F)
|
||||
SX126X_CAL_IMG_470_MHZ_1 = const(0x75)
|
||||
SX126X_CAL_IMG_470_MHZ_2 = const(0x81)
|
||||
SX126X_CAL_IMG_779_MHZ_1 = const(0xC1)
|
||||
SX126X_CAL_IMG_779_MHZ_2 = const(0xC5)
|
||||
SX126X_CAL_IMG_863_MHZ_1 = const(0xD7)
|
||||
SX126X_CAL_IMG_863_MHZ_2 = const(0xDB)
|
||||
SX126X_CAL_IMG_902_MHZ_1 = const(0xE1)
|
||||
SX126X_CAL_IMG_902_MHZ_2 = const(0xE9)
|
||||
SX126X_PA_CONFIG_HP_MAX = const(0x07)
|
||||
SX126X_PA_CONFIG_PA_LUT = const(0x01)
|
||||
SX126X_PA_CONFIG_SX1262_8 = const(0x00)
|
||||
SX126X_RX_TX_FALLBACK_MODE_FS = const(0x40)
|
||||
SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC = const(0x30)
|
||||
SX126X_RX_TX_FALLBACK_MODE_STDBY_RC = const(0x20)
|
||||
SX126X_IRQ_TIMEOUT = const(0b1000000000)
|
||||
SX126X_IRQ_CAD_DETECTED = const(0b0100000000)
|
||||
SX126X_IRQ_CAD_DONE = const(0b0010000000)
|
||||
SX126X_IRQ_CRC_ERR = const(0b0001000000)
|
||||
SX126X_IRQ_HEADER_ERR = const(0b0000100000)
|
||||
SX126X_IRQ_HEADER_VALID = const(0b0000010000)
|
||||
SX126X_IRQ_SYNC_WORD_VALID = const(0b0000001000)
|
||||
SX126X_IRQ_PREAMBLE_DETECTED = const(0b0000000100)
|
||||
SX126X_IRQ_RX_DONE = const(0b0000000010)
|
||||
SX126X_IRQ_TX_DONE = const(0b0000000001)
|
||||
SX126X_IRQ_ALL = const(0b1111111111)
|
||||
SX126X_IRQ_NONE = const(0b0000000000)
|
||||
SX126X_DIO2_AS_IRQ = const(0x00)
|
||||
SX126X_DIO2_AS_RF_SWITCH = const(0x01)
|
||||
SX126X_DIO3_OUTPUT_1_6 = const(0x00)
|
||||
SX126X_DIO3_OUTPUT_1_7 = const(0x01)
|
||||
SX126X_DIO3_OUTPUT_1_8 = const(0x02)
|
||||
SX126X_DIO3_OUTPUT_2_2 = const(0x03)
|
||||
SX126X_DIO3_OUTPUT_2_4 = const(0x04)
|
||||
SX126X_DIO3_OUTPUT_2_7 = const(0x05)
|
||||
SX126X_DIO3_OUTPUT_3_0 = const(0x06)
|
||||
SX126X_DIO3_OUTPUT_3_3 = const(0x07)
|
||||
SX126X_PACKET_TYPE_GFSK = const(0x00)
|
||||
SX126X_PACKET_TYPE_LORA = const(0x01)
|
||||
SX126X_PA_RAMP_10U = const(0x00)
|
||||
SX126X_PA_RAMP_20U = const(0x01)
|
||||
SX126X_PA_RAMP_40U = const(0x02)
|
||||
SX126X_PA_RAMP_80U = const(0x03)
|
||||
SX126X_PA_RAMP_200U = const(0x04)
|
||||
SX126X_PA_RAMP_800U = const(0x05)
|
||||
SX126X_PA_RAMP_1700U = const(0x06)
|
||||
SX126X_PA_RAMP_3400U = const(0x07)
|
||||
SX126X_GFSK_FILTER_NONE = const(0x00)
|
||||
SX126X_GFSK_FILTER_GAUSS_0_3 = const(0x08)
|
||||
SX126X_GFSK_FILTER_GAUSS_0_5 = const(0x09)
|
||||
SX126X_GFSK_FILTER_GAUSS_0_7 = const(0x0A)
|
||||
SX126X_GFSK_FILTER_GAUSS_1 = const(0x0B)
|
||||
SX126X_GFSK_RX_BW_4_8 = const(0x1F)
|
||||
SX126X_GFSK_RX_BW_5_8 = const(0x17)
|
||||
SX126X_GFSK_RX_BW_7_3 = const(0x0F)
|
||||
SX126X_GFSK_RX_BW_9_7 = const(0x1E)
|
||||
SX126X_GFSK_RX_BW_11_7 = const(0x16)
|
||||
SX126X_GFSK_RX_BW_14_6 = const(0x0E)
|
||||
SX126X_GFSK_RX_BW_19_5 = const(0x1D)
|
||||
SX126X_GFSK_RX_BW_23_4 = const(0x15)
|
||||
SX126X_GFSK_RX_BW_29_3 = const(0x0D)
|
||||
SX126X_GFSK_RX_BW_39_0 = const(0x1C)
|
||||
SX126X_GFSK_RX_BW_46_9 = const(0x14)
|
||||
SX126X_GFSK_RX_BW_58_6 = const(0x0C)
|
||||
SX126X_GFSK_RX_BW_78_2 = const(0x1B)
|
||||
SX126X_GFSK_RX_BW_93_8 = const(0x13)
|
||||
SX126X_GFSK_RX_BW_117_3 = const(0x0B)
|
||||
SX126X_GFSK_RX_BW_156_2 = const(0x1A)
|
||||
SX126X_GFSK_RX_BW_187_2 = const(0x12)
|
||||
SX126X_GFSK_RX_BW_234_3 = const(0x0A)
|
||||
SX126X_GFSK_RX_BW_312_0 = const(0x19)
|
||||
SX126X_GFSK_RX_BW_373_6 = const(0x11)
|
||||
SX126X_GFSK_RX_BW_467_0 = const(0x09)
|
||||
SX126X_LORA_BW_7_8 = const(0x00)
|
||||
SX126X_LORA_BW_10_4 = const(0x08)
|
||||
SX126X_LORA_BW_15_6 = const(0x01)
|
||||
SX126X_LORA_BW_20_8 = const(0x09)
|
||||
SX126X_LORA_BW_31_25 = const(0x02)
|
||||
SX126X_LORA_BW_41_7 = const(0x0A)
|
||||
SX126X_LORA_BW_62_5 = const(0x03)
|
||||
SX126X_LORA_BW_125_0 = const(0x04)
|
||||
SX126X_LORA_BW_250_0 = const(0x05)
|
||||
SX126X_LORA_BW_500_0 = const(0x06)
|
||||
SX126X_LORA_CR_4_5 = const(0x01)
|
||||
SX126X_LORA_CR_4_6 = const(0x02)
|
||||
SX126X_LORA_CR_4_7 = const(0x03)
|
||||
SX126X_LORA_CR_4_8 = const(0x04)
|
||||
SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF = const(0x00)
|
||||
SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON = const(0x01)
|
||||
SX126X_GFSK_PREAMBLE_DETECT_OFF = const(0x00)
|
||||
SX126X_GFSK_PREAMBLE_DETECT_8 = const(0x04)
|
||||
SX126X_GFSK_PREAMBLE_DETECT_16 = const(0x05)
|
||||
SX126X_GFSK_PREAMBLE_DETECT_24 = const(0x06)
|
||||
SX126X_GFSK_PREAMBLE_DETECT_32 = const(0x07)
|
||||
SX126X_GFSK_ADDRESS_FILT_OFF = const(0x00)
|
||||
SX126X_GFSK_ADDRESS_FILT_NODE = const(0x01)
|
||||
SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST = const(0x02)
|
||||
SX126X_GFSK_PACKET_FIXED = const(0x00)
|
||||
SX126X_GFSK_PACKET_VARIABLE = const(0x01)
|
||||
SX126X_GFSK_CRC_OFF = const(0x01)
|
||||
SX126X_GFSK_CRC_1_BYTE = const(0x00)
|
||||
SX126X_GFSK_CRC_2_BYTE = const(0x02)
|
||||
SX126X_GFSK_CRC_1_BYTE_INV = const(0x04)
|
||||
SX126X_GFSK_CRC_2_BYTE_INV = const(0x06)
|
||||
SX126X_GFSK_WHITENING_OFF = const(0x00)
|
||||
SX126X_GFSK_WHITENING_ON = const(0x01)
|
||||
SX126X_LORA_HEADER_EXPLICIT = const(0x00)
|
||||
SX126X_LORA_HEADER_IMPLICIT = const(0x01)
|
||||
SX126X_LORA_CRC_OFF = const(0x00)
|
||||
SX126X_LORA_CRC_ON = const(0x01)
|
||||
SX126X_LORA_IQ_STANDARD = const(0x00)
|
||||
SX126X_LORA_IQ_INVERTED = const(0x01)
|
||||
SX126X_CAD_ON_1_SYMB = const(0x00)
|
||||
SX126X_CAD_ON_2_SYMB = const(0x01)
|
||||
SX126X_CAD_ON_4_SYMB = const(0x02)
|
||||
SX126X_CAD_ON_8_SYMB = const(0x03)
|
||||
SX126X_CAD_ON_16_SYMB = const(0x04)
|
||||
SX126X_CAD_GOTO_STDBY = const(0x00)
|
||||
SX126X_CAD_GOTO_RX = const(0x01)
|
||||
SX126X_STATUS_MODE_STDBY_RC = const(0b00100000)
|
||||
SX126X_STATUS_MODE_STDBY_XOSC = const(0b00110000)
|
||||
SX126X_STATUS_MODE_FS = const(0b01000000)
|
||||
SX126X_STATUS_MODE_RX = const(0b01010000)
|
||||
SX126X_STATUS_MODE_TX = const(0b01100000)
|
||||
SX126X_STATUS_DATA_AVAILABLE = const(0b00000100)
|
||||
SX126X_STATUS_CMD_TIMEOUT = const(0b00000110)
|
||||
SX126X_STATUS_CMD_INVALID = const(0b00001000)
|
||||
SX126X_STATUS_CMD_FAILED = const(0b00001010)
|
||||
SX126X_STATUS_TX_DONE = const(0b00001100)
|
||||
SX126X_STATUS_SPI_FAILED = const(0b11111111)
|
||||
SX126X_GFSK_RX_STATUS_PREAMBLE_ERR = const(0b10000000)
|
||||
SX126X_GFSK_RX_STATUS_SYNC_ERR = const(0b01000000)
|
||||
SX126X_GFSK_RX_STATUS_ADRS_ERR = const(0b00100000)
|
||||
SX126X_GFSK_RX_STATUS_CRC_ERR = const(0b00010000)
|
||||
SX126X_GFSK_RX_STATUS_LENGTH_ERR = const(0b00001000)
|
||||
SX126X_GFSK_RX_STATUS_ABORT_ERR = const(0b00000100)
|
||||
SX126X_GFSK_RX_STATUS_PACKET_RECEIVED = const(0b00000010)
|
||||
SX126X_GFSK_RX_STATUS_PACKET_SENT = const(0b00000001)
|
||||
SX126X_PA_RAMP_ERR = const(0b100000000)
|
||||
SX126X_PLL_LOCK_ERR = const(0b001000000)
|
||||
SX126X_XOSC_START_ERR = const(0b000100000)
|
||||
SX126X_IMG_CALIB_ERR = const(0b000010000)
|
||||
SX126X_ADC_CALIB_ERR = const(0b000001000)
|
||||
SX126X_PLL_CALIB_ERR = const(0b000000100)
|
||||
SX126X_RC13M_CALIB_ERR = const(0b000000010)
|
||||
SX126X_RC64K_CALIB_ERR = const(0b000000001)
|
||||
SX126X_SYNC_WORD_PUBLIC = const(0x34)
|
||||
SX126X_SYNC_WORD_PRIVATE = const(0x12)
|
||||
|
||||
ERR_NONE = const(0)
|
||||
ERR_UNKNOWN = const(-1)
|
||||
ERR_CHIP_NOT_FOUND = const(-2)
|
||||
ERR_MEMORY_ALLOCATION_FAILED = const(-3)
|
||||
ERR_PACKET_TOO_LONG = const(-4)
|
||||
ERR_TX_TIMEOUT = const(-5)
|
||||
ERR_RX_TIMEOUT = const(-6)
|
||||
ERR_CRC_MISMATCH = const(-7)
|
||||
ERR_INVALID_BANDWIDTH = const(-8)
|
||||
ERR_INVALID_SPREADING_FACTOR = const(-9)
|
||||
ERR_INVALID_CODING_RATE = const(-10)
|
||||
ERR_INVALID_BIT_RANGE = const(-11)
|
||||
ERR_INVALID_FREQUENCY = const(-12)
|
||||
ERR_INVALID_OUTPUT_POWER = const(-13)
|
||||
PREAMBLE_DETECTED = const(-14)
|
||||
CHANNEL_FREE = const(-15)
|
||||
ERR_SPI_WRITE_FAILED = const(-16)
|
||||
ERR_INVALID_CURRENT_LIMIT = const(-17)
|
||||
ERR_INVALID_PREAMBLE_LENGTH = const(-18)
|
||||
ERR_INVALID_GAIN = const(-19)
|
||||
ERR_WRONG_MODEM = const(-20)
|
||||
ERR_INVALID_NUM_SAMPLES = const(-21)
|
||||
ERR_INVALID_RSSI_OFFSET = const(-22)
|
||||
ERR_INVALID_ENCODING = const(-23)
|
||||
ERR_INVALID_BIT_RATE = const(-101)
|
||||
ERR_INVALID_FREQUENCY_DEVIATION = const(-102)
|
||||
ERR_INVALID_BIT_RATE_BW_RATIO = const(-103)
|
||||
ERR_INVALID_RX_BANDWIDTH = const(-104)
|
||||
ERR_INVALID_SYNC_WORD = const(-105)
|
||||
ERR_INVALID_DATA_SHAPING = const(-106)
|
||||
ERR_INVALID_MODULATION = const(-107)
|
||||
ERR_AT_FAILED = const(-201)
|
||||
ERR_URL_MALFORMED = const(-202)
|
||||
ERR_RESPONSE_MALFORMED_AT = const(-203)
|
||||
ERR_RESPONSE_MALFORMED = const(-204)
|
||||
ERR_MQTT_CONN_VERSION_REJECTED = const(-205)
|
||||
ERR_MQTT_CONN_ID_REJECTED = const(-206)
|
||||
ERR_MQTT_CONN_SERVER_UNAVAILABLE = const(-207)
|
||||
ERR_MQTT_CONN_BAD_USERNAME_PASSWORD = const(-208)
|
||||
ERR_MQTT_CONN_NOT_AUTHORIZED = const(-208)
|
||||
ERR_MQTT_UNEXPECTED_PACKET_ID = const(-209)
|
||||
ERR_MQTT_NO_NEW_PACKET_AVAILABLE = const(-210)
|
||||
ERR_CMD_MODE_FAILED = const(-301)
|
||||
ERR_FRAME_MALFORMED = const(-302)
|
||||
ERR_FRAME_INCORRECT_CHECKSUM = const(-303)
|
||||
ERR_FRAME_UNEXPECTED_ID = const(-304)
|
||||
ERR_FRAME_NO_RESPONSE = const(-305)
|
||||
ERR_INVALID_RTTY_SHIFT = const(-401)
|
||||
ERR_UNSUPPORTED_ENCODING = const(-402)
|
||||
ERR_INVALID_DATA_RATE = const(-501)
|
||||
ERR_INVALID_ADDRESS_WIDTH = const(-502)
|
||||
ERR_INVALID_PIPE_NUMBER = const(-503)
|
||||
ERR_ACK_NOT_RECEIVED = const(-504)
|
||||
ERR_INVALID_NUM_BROAD_ADDRS = const(-601)
|
||||
ERR_INVALID_CRC_CONFIGURATION = const(-701)
|
||||
LORA_DETECTED = const(-702)
|
||||
ERR_INVALID_TCXO_VOLTAGE = const(-703)
|
||||
ERR_INVALID_MODULATION_PARAMETERS = const(-704)
|
||||
ERR_SPI_CMD_TIMEOUT = const(-705)
|
||||
ERR_SPI_CMD_INVALID = const(-706)
|
||||
ERR_SPI_CMD_FAILED = const(-707)
|
||||
ERR_INVALID_SLEEP_PERIOD = const(-708)
|
||||
ERR_INVALID_RX_PERIOD = const(-709)
|
||||
ERR_INVALID_CALLSIGN = const(-801)
|
||||
ERR_INVALID_NUM_REPEATERS = const(-802)
|
||||
ERR_INVALID_REPEATER_CALLSIGN = const(-803)
|
||||
ERR_INVALID_PACKET_TYPE = const(-804)
|
||||
ERR_INVALID_PACKET_LENGTH = const(-805)
|
||||
|
||||
ERROR = {
|
||||
0: 'ERR_NONE',
|
||||
-1: 'ERR_UNKNOWN',
|
||||
-2: 'ERR_CHIP_NOT_FOUND',
|
||||
-3: 'ERR_MEMORY_ALLOCATION_FAILED',
|
||||
-4: 'ERR_PACKET_TOO_LONG',
|
||||
-5: 'ERR_TX_TIMEOUT',
|
||||
-6: 'ERR_RX_TIMEOUT',
|
||||
-7: 'ERR_CRC_MISMATCH',
|
||||
-8: 'ERR_INVALID_BANDWIDTH',
|
||||
-9: 'ERR_INVALID_SPREADING_FACTOR',
|
||||
-10: 'ERR_INVALID_CODING_RATE',
|
||||
-11: 'ERR_INVALID_BIT_RANGE',
|
||||
-12: 'ERR_INVALID_FREQUENCY',
|
||||
-13: 'ERR_INVALID_OUTPUT_POWER',
|
||||
-14: 'PREAMBLE_DETECTED',
|
||||
-15: 'CHANNEL_FREE',
|
||||
-16: 'ERR_SPI_WRITE_FAILED',
|
||||
-17: 'ERR_INVALID_CURRENT_LIMIT',
|
||||
-18: 'ERR_INVALID_PREAMBLE_LENGTH',
|
||||
-19: 'ERR_INVALID_GAIN',
|
||||
-20: 'ERR_WRONG_MODEM',
|
||||
-21: 'ERR_INVALID_NUM_SAMPLES',
|
||||
-22: 'ERR_INVALID_RSSI_OFFSET',
|
||||
-23: 'ERR_INVALID_ENCODING',
|
||||
-101: 'ERR_INVALID_BIT_RATE',
|
||||
-102: 'ERR_INVALID_FREQUENCY_DEVIATION',
|
||||
-103: 'ERR_INVALID_BIT_RATE_BW_RATIO',
|
||||
-104: 'ERR_INVALID_RX_BANDWIDTH',
|
||||
-105: 'ERR_INVALID_SYNC_WORD',
|
||||
-106: 'ERR_INVALID_DATA_SHAPING',
|
||||
-107: 'ERR_INVALID_MODULATION',
|
||||
-201: 'ERR_AT_FAILED',
|
||||
-202: 'ERR_URL_MALFORMED',
|
||||
-203: 'ERR_RESPONSE_MALFORMED_AT',
|
||||
-204: 'ERR_RESPONSE_MALFORMED',
|
||||
-205: 'ERR_MQTT_CONN_VERSION_REJECTED',
|
||||
-206: 'ERR_MQTT_CONN_ID_REJECTED',
|
||||
-207: 'ERR_MQTT_CONN_SERVER_UNAVAILABLE',
|
||||
-208: 'ERR_MQTT_CONN_BAD_USERNAME_PASSWORD',
|
||||
-208: 'ERR_MQTT_CONN_NOT_AUTHORIZED',
|
||||
-209: 'ERR_MQTT_UNEXPECTED_PACKET_ID',
|
||||
-210: 'ERR_MQTT_NO_NEW_PACKET_AVAILABLE',
|
||||
-301: 'ERR_CMD_MODE_FAILED',
|
||||
-302: 'ERR_FRAME_MALFORMED',
|
||||
-303: 'ERR_FRAME_INCORRECT_CHECKSUM',
|
||||
-304: 'ERR_FRAME_UNEXPECTED_ID',
|
||||
-305: 'ERR_FRAME_NO_RESPONSE',
|
||||
-401: 'ERR_INVALID_RTTY_SHIFT',
|
||||
-402: 'ERR_UNSUPPORTED_ENCODING',
|
||||
-501: 'ERR_INVALID_DATA_RATE',
|
||||
-502: 'ERR_INVALID_ADDRESS_WIDTH',
|
||||
-503: 'ERR_INVALID_PIPE_NUMBER',
|
||||
-504: 'ERR_ACK_NOT_RECEIVED',
|
||||
-601: 'ERR_INVALID_NUM_BROAD_ADDRS',
|
||||
-701: 'ERR_INVALID_CRC_CONFIGURATION',
|
||||
-702: 'LORA_DETECTED',
|
||||
-703: 'ERR_INVALID_TCXO_VOLTAGE',
|
||||
-704: 'ERR_INVALID_MODULATION_PARAMETERS',
|
||||
-705: 'ERR_SPI_CMD_TIMEOUT',
|
||||
-706: 'ERR_SPI_CMD_INVALID',
|
||||
-707: 'ERR_SPI_CMD_FAILED',
|
||||
-708: 'ERR_INVALID_SLEEP_PERIOD',
|
||||
-709: 'ERR_INVALID_RX_PERIOD',
|
||||
-801: 'ERR_INVALID_CALLSIGN',
|
||||
-802: 'ERR_INVALID_NUM_REPEATERS',
|
||||
-803: 'ERR_INVALID_REPEATER_CALLSIGN',
|
||||
-804: 'ERR_INVALID_PACKET_TYPE',
|
||||
-805: 'ERR_INVALID_PACKET_LENGTH'
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
|
||||
|
||||
from micropython import const
|
||||
import framebuf
|
||||
|
||||
|
||||
# register definitions
|
||||
SET_CONTRAST = const(0x81)
|
||||
SET_ENTIRE_ON = const(0xA4)
|
||||
SET_NORM_INV = const(0xA6)
|
||||
SET_DISP = const(0xAE)
|
||||
SET_MEM_ADDR = const(0x20)
|
||||
SET_COL_ADDR = const(0x21)
|
||||
SET_PAGE_ADDR = const(0x22)
|
||||
SET_DISP_START_LINE = const(0x40)
|
||||
SET_SEG_REMAP = const(0xA0)
|
||||
SET_MUX_RATIO = const(0xA8)
|
||||
SET_COM_OUT_DIR = const(0xC0)
|
||||
SET_DISP_OFFSET = const(0xD3)
|
||||
SET_COM_PIN_CFG = const(0xDA)
|
||||
SET_DISP_CLK_DIV = const(0xD5)
|
||||
SET_PRECHARGE = const(0xD9)
|
||||
SET_VCOM_DESEL = const(0xDB)
|
||||
SET_CHARGE_PUMP = const(0x8D)
|
||||
|
||||
# Subclassing FrameBuffer provides support for graphics primitives
|
||||
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
|
||||
class SSD1306(framebuf.FrameBuffer):
|
||||
def __init__(self, width, height, external_vcc):
|
||||
self.width = width
|
||||
self.height = height
|
||||
self.external_vcc = external_vcc
|
||||
self.pages = self.height // 8
|
||||
self.buffer = bytearray(self.pages * self.width)
|
||||
super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
|
||||
self.init_display()
|
||||
|
||||
def init_display(self):
|
||||
for cmd in (
|
||||
SET_DISP | 0x00, # off
|
||||
# address setting
|
||||
SET_MEM_ADDR,
|
||||
0x00, # horizontal
|
||||
# resolution and layout
|
||||
SET_DISP_START_LINE | 0x00,
|
||||
SET_SEG_REMAP | 0x01, # column addr 127 mapped to SEG0
|
||||
SET_MUX_RATIO,
|
||||
self.height - 1,
|
||||
SET_COM_OUT_DIR | 0x08, # scan from COM[N] to COM0
|
||||
SET_DISP_OFFSET,
|
||||
0x00,
|
||||
SET_COM_PIN_CFG,
|
||||
0x02 if self.width > 2 * self.height else 0x12,
|
||||
# timing and driving scheme
|
||||
SET_DISP_CLK_DIV,
|
||||
0x80,
|
||||
SET_PRECHARGE,
|
||||
0x22 if self.external_vcc else 0xF1,
|
||||
SET_VCOM_DESEL,
|
||||
0x30, # 0.83*Vcc
|
||||
# display
|
||||
SET_CONTRAST,
|
||||
0xFF, # maximum
|
||||
SET_ENTIRE_ON, # output follows RAM contents
|
||||
SET_NORM_INV, # not inverted
|
||||
# charge pump
|
||||
SET_CHARGE_PUMP,
|
||||
0x10 if self.external_vcc else 0x14,
|
||||
SET_DISP | 0x01,
|
||||
): # on
|
||||
self.write_cmd(cmd)
|
||||
self.fill(0)
|
||||
self.show()
|
||||
|
||||
def poweroff(self):
|
||||
self.write_cmd(SET_DISP | 0x00)
|
||||
|
||||
def poweron(self):
|
||||
self.write_cmd(SET_DISP | 0x01)
|
||||
|
||||
def contrast(self, contrast):
|
||||
self.write_cmd(SET_CONTRAST)
|
||||
self.write_cmd(contrast)
|
||||
|
||||
def invert(self, invert):
|
||||
self.write_cmd(SET_NORM_INV | (invert & 1))
|
||||
|
||||
def show(self):
|
||||
x0 = 0
|
||||
x1 = self.width - 1
|
||||
if self.width == 64:
|
||||
# displays with width of 64 pixels are shifted by 32
|
||||
x0 += 32
|
||||
x1 += 32
|
||||
self.write_cmd(SET_COL_ADDR)
|
||||
self.write_cmd(x0)
|
||||
self.write_cmd(x1)
|
||||
self.write_cmd(SET_PAGE_ADDR)
|
||||
self.write_cmd(0)
|
||||
self.write_cmd(self.pages - 1)
|
||||
self.write_data(self.buffer)
|
||||
|
||||
|
||||
class SSD1306_I2C(SSD1306):
|
||||
def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
|
||||
self.i2c = i2c
|
||||
self.addr = addr
|
||||
self.temp = bytearray(2)
|
||||
self.write_list = [b"\x40", None] # Co=0, D/C#=1
|
||||
super().__init__(width, height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.temp[0] = 0x80 # Co=1, D/C#=0
|
||||
self.temp[1] = cmd
|
||||
self.i2c.writeto(self.addr, self.temp)
|
||||
|
||||
def write_data(self, buf):
|
||||
self.write_list[1] = buf
|
||||
self.i2c.writevto(self.addr, self.write_list)
|
||||
|
||||
|
||||
class SSD1306_SPI(SSD1306):
|
||||
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
|
||||
self.rate = 10 * 1024 * 1024
|
||||
dc.init(dc.OUT, value=0)
|
||||
res.init(res.OUT, value=0)
|
||||
cs.init(cs.OUT, value=1)
|
||||
self.spi = spi
|
||||
self.dc = dc
|
||||
self.res = res
|
||||
self.cs = cs
|
||||
import time
|
||||
|
||||
self.res(1)
|
||||
time.sleep_ms(1)
|
||||
self.res(0)
|
||||
time.sleep_ms(10)
|
||||
self.res(1)
|
||||
super().__init__(width, height, external_vcc)
|
||||
|
||||
def write_cmd(self, cmd):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
self.cs(1)
|
||||
self.dc(0)
|
||||
self.cs(0)
|
||||
self.spi.write(bytearray([cmd]))
|
||||
self.cs(1)
|
||||
|
||||
def write_data(self, buf):
|
||||
self.spi.init(baudrate=self.rate, polarity=0, phase=0)
|
||||
self.cs(1)
|
||||
self.dc(1)
|
||||
self.cs(0)
|
||||
self.spi.write(buf)
|
||||
self.cs(1)
|
||||
@@ -0,0 +1,273 @@
|
||||
from _sx126x import *
|
||||
from sx126x import SX126X
|
||||
|
||||
_SX126X_PA_CONFIG_SX1261 = const(0x01)
|
||||
|
||||
class SX1261(SX126X):
|
||||
TX_DONE = SX126X_IRQ_TX_DONE
|
||||
RX_DONE = SX126X_IRQ_RX_DONE
|
||||
ADDR_FILT_OFF = SX126X_GFSK_ADDRESS_FILT_OFF
|
||||
ADDR_FILT_NODE = SX126X_GFSK_ADDRESS_FILT_NODE
|
||||
ADDR_FILT_NODE_BROAD = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST
|
||||
PREAMBLE_DETECT_OFF = SX126X_GFSK_PREAMBLE_DETECT_OFF
|
||||
PREAMBLE_DETECT_8 = SX126X_GFSK_PREAMBLE_DETECT_8
|
||||
PREAMBLE_DETECT_16 = SX126X_GFSK_PREAMBLE_DETECT_16
|
||||
PREAMBLE_DETECT_24 = SX126X_GFSK_PREAMBLE_DETECT_24
|
||||
PREAMBLE_DETECT_32 = SX126X_GFSK_PREAMBLE_DETECT_32
|
||||
STATUS = ERROR
|
||||
|
||||
def __init__(self, spi_bus, clk, mosi, miso, cs, irq, rst, gpio):
|
||||
super().__init__(spi_bus, clk, mosi, miso, cs, irq, rst, gpio)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
|
||||
def begin(self, 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):
|
||||
state = super().begin(bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO, txIq, rxIq)
|
||||
ASSERT(state)
|
||||
|
||||
if not implicit:
|
||||
state = super().explicitHeader()
|
||||
else:
|
||||
state = super().implicitHeader(implicitLen)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcOn)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def beginFSK(self, freq=434.0, br=48.0, freqDev=50.0, rxBw=156.2, power=14, currentLimit=60.0,
|
||||
preambleLength=16, dataShaping=0.5, syncWord=[0x2D, 0x01], syncBitsLength=16,
|
||||
addrFilter=SX126X_GFSK_ADDRESS_FILT_OFF, addr=0x00, crcLength=2, crcInitial=0x1D0F, crcPolynomial=0x1021,
|
||||
crcInverted=True, whiteningOn=True, whiteningInitial=0x0100,
|
||||
fixedPacketLength=False, packetLength=0xFF, preambleDetectorLength=SX126X_GFSK_PREAMBLE_DETECT_16,
|
||||
tcxoVoltage=1.6, useRegulatorLDO=False,
|
||||
blocking=True):
|
||||
state = super().beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, preambleDetectorLength, tcxoVoltage, useRegulatorLDO)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setSyncBits(syncWord, syncBitsLength)
|
||||
ASSERT(state)
|
||||
|
||||
if addrFilter == SX126X_GFSK_ADDRESS_FILT_OFF:
|
||||
state = super().disableAddressFiltering()
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE:
|
||||
state = super().setNodeAddress(addr)
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST:
|
||||
state = super().setBroadcastAddress(addr)
|
||||
else:
|
||||
state = ERR_UNKNOWN
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcLength, crcInitial, crcPolynomial, crcInverted)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setWhitening(whiteningOn, whiteningInitial)
|
||||
ASSERT(state)
|
||||
|
||||
if fixedPacketLength:
|
||||
state = super().fixedPacketLengthMode(packetLength)
|
||||
else:
|
||||
state = super().variablePacketLengthMode(packetLength)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def setFrequency(self, freq, calibrate=True):
|
||||
if freq < 150.0 or freq > 960.0:
|
||||
return ERR_INVALID_FREQUENCY
|
||||
|
||||
state = ERR_NONE
|
||||
|
||||
if calibrate:
|
||||
data = bytearray(2)
|
||||
if freq > 900.0:
|
||||
data[0] = SX126X_CAL_IMG_902_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_902_MHZ_2
|
||||
elif freq > 850.0:
|
||||
data[0] = SX126X_CAL_IMG_863_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_863_MHZ_2
|
||||
elif freq > 770.0:
|
||||
data[0] = SX126X_CAL_IMG_779_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_779_MHZ_2
|
||||
elif freq > 460.0:
|
||||
data[0] = SX126X_CAL_IMG_470_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_470_MHZ_2
|
||||
else:
|
||||
data[0] = SX126X_CAL_IMG_430_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_430_MHZ_2
|
||||
state = super().calibrateImage(data)
|
||||
ASSERT(state)
|
||||
|
||||
return super().setFrequencyRaw(freq)
|
||||
|
||||
def setOutputPower(self, power):
|
||||
if not ((power >= -17) and (power <= 14)):
|
||||
return ERR_INVALID_OUTPUT_POWER
|
||||
|
||||
ocp = bytearray(1)
|
||||
ocp_mv = memoryview(ocp)
|
||||
state = super().readRegister(SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setPaConfig(0x04, _SX126X_PA_CONFIG_SX1261, 0x00)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setTxParams(power)
|
||||
ASSERT(state)
|
||||
|
||||
return super().writeRegister(SX126X_REG_OCP_CONFIGURATION, ocp, 1)
|
||||
|
||||
def setTxIq(self, txIq):
|
||||
self._txIq = txIq
|
||||
|
||||
def setRxIq(self, rxIq):
|
||||
self._rxIq = rxIq
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setPreambleDetectorLength(self, preambleDetectorLength):
|
||||
self._preambleDetectorLength = preambleDetectorLength
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setBlockingCallback(self, blocking, callback=None):
|
||||
self.blocking = blocking
|
||||
if not self.blocking:
|
||||
state = super().startReceive()
|
||||
ASSERT(state)
|
||||
if callback != None:
|
||||
self._callbackFunction = callback
|
||||
super().setDio1Action(self._onIRQ)
|
||||
else:
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
else:
|
||||
state = super().standby()
|
||||
ASSERT(state)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
|
||||
def recv(self, len=0, timeout_en=False, timeout_ms=0):
|
||||
if not self.blocking:
|
||||
return self._readData(len)
|
||||
else:
|
||||
return self._receive(len, timeout_en, timeout_ms)
|
||||
|
||||
def send(self, data):
|
||||
if not self.blocking:
|
||||
return self._startTransmit(data)
|
||||
else:
|
||||
return self._transmit(data)
|
||||
|
||||
def _events(self):
|
||||
return super().getIrqStatus()
|
||||
|
||||
def _receive(self, len_=0, timeout_en=False, timeout_ms=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = len_
|
||||
|
||||
if len_ == 0:
|
||||
length = SX126X_MAX_PACKET_LENGTH
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().receive(data_mv, length, timeout_en, timeout_ms)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
if len_ == 0:
|
||||
length = super().getPacketLength(False)
|
||||
data = data[:length]
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
return bytes(data), state
|
||||
|
||||
def _transmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
# --- AJOUT : FORÇAGE DU CRC À OFF AVANT L'ENVOI ---
|
||||
super().setCRC(False)
|
||||
|
||||
state = super().transmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _readData(self, len_=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = super().getPacketLength()
|
||||
|
||||
if len_ < length and len_ != 0:
|
||||
length = len_
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().readData(data_mv, length)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
return bytes(data), state
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
def _startTransmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
# --- AJOUT : FORÇAGE DU CRC À OFF AVANT L'ENVOI ---
|
||||
super().setCRC(False)
|
||||
|
||||
state = super().startTransmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _dummyFunction(self, *args):
|
||||
pass
|
||||
|
||||
def _onIRQ(self, callback):
|
||||
events = self._events()
|
||||
if events & SX126X_IRQ_TX_DONE:
|
||||
super().startReceive()
|
||||
self._callbackFunction(events)
|
||||
@@ -0,0 +1,267 @@
|
||||
from _sx126x import *
|
||||
from sx126x import SX126X
|
||||
|
||||
_SX126X_PA_CONFIG_SX1262 = const(0x00)
|
||||
|
||||
class SX1262(SX126X):
|
||||
TX_DONE = SX126X_IRQ_TX_DONE
|
||||
RX_DONE = SX126X_IRQ_RX_DONE
|
||||
ADDR_FILT_OFF = SX126X_GFSK_ADDRESS_FILT_OFF
|
||||
ADDR_FILT_NODE = SX126X_GFSK_ADDRESS_FILT_NODE
|
||||
ADDR_FILT_NODE_BROAD = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST
|
||||
PREAMBLE_DETECT_OFF = SX126X_GFSK_PREAMBLE_DETECT_OFF
|
||||
PREAMBLE_DETECT_8 = SX126X_GFSK_PREAMBLE_DETECT_8
|
||||
PREAMBLE_DETECT_16 = SX126X_GFSK_PREAMBLE_DETECT_16
|
||||
PREAMBLE_DETECT_24 = SX126X_GFSK_PREAMBLE_DETECT_24
|
||||
PREAMBLE_DETECT_32 = SX126X_GFSK_PREAMBLE_DETECT_32
|
||||
STATUS = ERROR
|
||||
|
||||
def __init__(self, spi_bus, clk, mosi, miso, cs, irq, rst, gpio):
|
||||
super().__init__(spi_bus, clk, mosi, miso, cs, irq, rst, gpio)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
|
||||
def begin(self, 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):
|
||||
state = super().begin(bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO, txIq, rxIq)
|
||||
ASSERT(state)
|
||||
|
||||
if not implicit:
|
||||
state = super().explicitHeader()
|
||||
else:
|
||||
state = super().implicitHeader(implicitLen)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcOn)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def beginFSK(self, freq=434.0, br=48.0, freqDev=50.0, rxBw=156.2, power=14, currentLimit=60.0,
|
||||
preambleLength=16, dataShaping=0.5, syncWord=[0x2D, 0x01], syncBitsLength=16,
|
||||
addrFilter=SX126X_GFSK_ADDRESS_FILT_OFF, addr=0x00, crcLength=2, crcInitial=0x1D0F, crcPolynomial=0x1021,
|
||||
crcInverted=True, whiteningOn=True, whiteningInitial=0x0100,
|
||||
fixedPacketLength=False, packetLength=0xFF, preambleDetectorLength=SX126X_GFSK_PREAMBLE_DETECT_16,
|
||||
tcxoVoltage=1.6, useRegulatorLDO=False,
|
||||
blocking=True):
|
||||
state = super().beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, preambleDetectorLength, tcxoVoltage, useRegulatorLDO)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setSyncBits(syncWord, syncBitsLength)
|
||||
ASSERT(state)
|
||||
|
||||
if addrFilter == SX126X_GFSK_ADDRESS_FILT_OFF:
|
||||
state = super().disableAddressFiltering()
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE:
|
||||
state = super().setNodeAddress(addr)
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST:
|
||||
state = super().setBroadcastAddress(addr)
|
||||
else:
|
||||
state = ERR_UNKNOWN
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcLength, crcInitial, crcPolynomial, crcInverted)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setWhitening(whiteningOn, whiteningInitial)
|
||||
ASSERT(state)
|
||||
|
||||
if fixedPacketLength:
|
||||
state = super().fixedPacketLengthMode(packetLength)
|
||||
else:
|
||||
state = super().variablePacketLengthMode(packetLength)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def setFrequency(self, freq, calibrate=True):
|
||||
if freq < 150.0 or freq > 960.0:
|
||||
return ERR_INVALID_FREQUENCY
|
||||
|
||||
state = ERR_NONE
|
||||
|
||||
if calibrate:
|
||||
data = bytearray(2)
|
||||
if freq > 900.0:
|
||||
data[0] = SX126X_CAL_IMG_902_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_902_MHZ_2
|
||||
elif freq > 850.0:
|
||||
data[0] = SX126X_CAL_IMG_863_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_863_MHZ_2
|
||||
elif freq > 770.0:
|
||||
data[0] = SX126X_CAL_IMG_779_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_779_MHZ_2
|
||||
elif freq > 460.0:
|
||||
data[0] = SX126X_CAL_IMG_470_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_470_MHZ_2
|
||||
else:
|
||||
data[0] = SX126X_CAL_IMG_430_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_430_MHZ_2
|
||||
state = super().calibrateImage(data)
|
||||
ASSERT(state)
|
||||
|
||||
return super().setFrequencyRaw(freq)
|
||||
|
||||
def setOutputPower(self, power):
|
||||
if not ((power >= -9) and (power <= 22)):
|
||||
return ERR_INVALID_OUTPUT_POWER
|
||||
|
||||
ocp = bytearray(1)
|
||||
ocp_mv = memoryview(ocp)
|
||||
state = super().readRegister(SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setPaConfig(0x04, _SX126X_PA_CONFIG_SX1262)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setTxParams(power)
|
||||
ASSERT(state)
|
||||
|
||||
return super().writeRegister(SX126X_REG_OCP_CONFIGURATION, ocp, 1)
|
||||
|
||||
def setTxIq(self, txIq):
|
||||
self._txIq = txIq
|
||||
|
||||
def setRxIq(self, rxIq):
|
||||
self._rxIq = rxIq
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setPreambleDetectorLength(self, preambleDetectorLength):
|
||||
self._preambleDetectorLength = preambleDetectorLength
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setBlockingCallback(self, blocking, callback=None):
|
||||
self.blocking = blocking
|
||||
if not self.blocking:
|
||||
state = super().startReceive()
|
||||
ASSERT(state)
|
||||
if callback != None:
|
||||
self._callbackFunction = callback
|
||||
super().setDio1Action(self._onIRQ)
|
||||
else:
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
else:
|
||||
state = super().standby()
|
||||
ASSERT(state)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
|
||||
def recv(self, len=0, timeout_en=False, timeout_ms=0):
|
||||
if not self.blocking:
|
||||
return self._readData(len)
|
||||
else:
|
||||
return self._receive(len, timeout_en, timeout_ms)
|
||||
|
||||
def send(self, data):
|
||||
if not self.blocking:
|
||||
return self._startTransmit(data)
|
||||
else:
|
||||
return self._transmit(data)
|
||||
|
||||
def _events(self):
|
||||
return super().getIrqStatus()
|
||||
|
||||
def _receive(self, len_=0, timeout_en=False, timeout_ms=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = len_
|
||||
|
||||
if len_ == 0:
|
||||
length = SX126X_MAX_PACKET_LENGTH
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().receive(data_mv, length, timeout_en, timeout_ms)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
if len_ == 0:
|
||||
length = super().getPacketLength(False)
|
||||
data = data[:length]
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
return bytes(data), state
|
||||
|
||||
def _transmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
state = super().transmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _readData(self, len_=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = super().getPacketLength()
|
||||
|
||||
if len_ < length and len_ != 0:
|
||||
length = len_
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().readData(data_mv, length)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
return bytes(data), state
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
def _startTransmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
state = super().startTransmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _dummyFunction(self, *args):
|
||||
pass
|
||||
|
||||
def _onIRQ(self, callback):
|
||||
events = self._events()
|
||||
if events & SX126X_IRQ_TX_DONE:
|
||||
super().startReceive()
|
||||
self._callbackFunction(events)
|
||||
@@ -0,0 +1,261 @@
|
||||
from _sx126x import *
|
||||
from sx126x import SX126X
|
||||
|
||||
_SX126X_PA_CONFIG_SX1268 = const(0x00)
|
||||
|
||||
class SX1268(SX126X):
|
||||
TX_DONE = SX126X_IRQ_TX_DONE
|
||||
RX_DONE = SX126X_IRQ_RX_DONE
|
||||
ADDR_FILT_OFF = SX126X_GFSK_ADDRESS_FILT_OFF
|
||||
ADDR_FILT_NODE = SX126X_GFSK_ADDRESS_FILT_NODE
|
||||
ADDR_FILT_NODE_BROAD = SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST
|
||||
PREAMBLE_DETECT_OFF = SX126X_GFSK_PREAMBLE_DETECT_OFF
|
||||
PREAMBLE_DETECT_8 = SX126X_GFSK_PREAMBLE_DETECT_8
|
||||
PREAMBLE_DETECT_16 = SX126X_GFSK_PREAMBLE_DETECT_16
|
||||
PREAMBLE_DETECT_24 = SX126X_GFSK_PREAMBLE_DETECT_24
|
||||
PREAMBLE_DETECT_32 = SX126X_GFSK_PREAMBLE_DETECT_32
|
||||
STATUS = ERROR
|
||||
|
||||
def __init__(self, spi_bus, clk, mosi, miso, cs, irq, rst, gpio):
|
||||
super().__init__(spi_bus, clk, mosi, miso, cs, irq, rst, gpio)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
|
||||
def begin(self, 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):
|
||||
state = super().begin(bw, sf, cr, syncWord, currentLimit, preambleLength, tcxoVoltage, useRegulatorLDO, txIq, rxIq)
|
||||
ASSERT(state)
|
||||
|
||||
if not implicit:
|
||||
state = super().explicitHeader()
|
||||
else:
|
||||
state = super().implicitHeader(implicitLen)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcOn)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def beginFSK(self, freq=434.0, br=48.0, freqDev=50.0, rxBw=156.2, power=14, currentLimit=60.0,
|
||||
preambleLength=16, dataShaping=0.5, syncWord=[0x2D, 0x01], syncBitsLength=16,
|
||||
addrFilter=SX126X_GFSK_ADDRESS_FILT_OFF, addr=0x00, crcLength=2, crcInitial=0x1D0F, crcPolynomial=0x1021,
|
||||
crcInverted=True, whiteningOn=True, whiteningInitial=0x0100,
|
||||
fixedPacketLength=False, packetLength=0xFF, preambleDetectorLength=SX126X_GFSK_PREAMBLE_DETECT_16,
|
||||
tcxoVoltage=1.6, useRegulatorLDO=False,
|
||||
blocking=True):
|
||||
state = super().beginFSK(br, freqDev, rxBw, currentLimit, preambleLength, dataShaping, preambleDetectorLength, tcxoVoltage, useRegulatorLDO)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setSyncBits(syncWord, syncBitsLength)
|
||||
ASSERT(state)
|
||||
|
||||
if addrFilter == SX126X_GFSK_ADDRESS_FILT_OFF:
|
||||
state = super().disableAddressFiltering()
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE:
|
||||
state = super().setNodeAddress(addr)
|
||||
elif addrFilter == SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST:
|
||||
state = super().setBroadcastAddress(addr)
|
||||
else:
|
||||
state = ERR_UNKNOWN
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setCRC(crcLength, crcInitial, crcPolynomial, crcInverted)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setWhitening(whiteningOn, whiteningInitial)
|
||||
ASSERT(state)
|
||||
|
||||
if fixedPacketLength:
|
||||
state = super().fixedPacketLengthMode(packetLength)
|
||||
else:
|
||||
state = super().variablePacketLengthMode(packetLength)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setFrequency(freq)
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setOutputPower(power)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().fixPaClamping()
|
||||
ASSERT(state)
|
||||
|
||||
state = self.setBlockingCallback(blocking)
|
||||
|
||||
return state
|
||||
|
||||
def setFrequency(self, freq, calibrate=True):
|
||||
if freq < 410.0 or freq > 810.0:
|
||||
return ERR_INVALID_FREQUENCY
|
||||
|
||||
state = ERR_NONE
|
||||
|
||||
if calibrate:
|
||||
data = bytearray(2)
|
||||
if freq > 770.0:
|
||||
data[0] = SX126X_CAL_IMG_779_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_779_MHZ_2
|
||||
elif freq > 460.0:
|
||||
data[0] = SX126X_CAL_IMG_470_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_470_MHZ_2
|
||||
else:
|
||||
data[0] = SX126X_CAL_IMG_430_MHZ_1
|
||||
data[1] = SX126X_CAL_IMG_430_MHZ_2
|
||||
state = super().calibrateImage(data)
|
||||
ASSERT(state)
|
||||
|
||||
return super().setFrequencyRaw(freq)
|
||||
|
||||
def setOutputPower(self, power):
|
||||
if not ((power >= -9) and (power <= 22)):
|
||||
return ERR_INVALID_OUTPUT_POWER
|
||||
|
||||
ocp = bytearray(1)
|
||||
ocp_mv = memoryview(ocp)
|
||||
state = super().readRegister(SX126X_REG_OCP_CONFIGURATION, ocp_mv, 1)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setPaConfig(0x04, _SX126X_PA_CONFIG_SX1268)
|
||||
ASSERT(state)
|
||||
|
||||
state = super().setTxParams(power)
|
||||
ASSERT(state)
|
||||
|
||||
return super().writeRegister(SX126X_REG_OCP_CONFIGURATION, ocp, 1)
|
||||
|
||||
def setTxIq(self, txIq):
|
||||
self._txIq = txIq
|
||||
|
||||
def setRxIq(self, rxIq):
|
||||
self._rxIq = rxIq
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setPreambleDetectorLength(self, preambleDetectorLength):
|
||||
self._preambleDetectorLength = preambleDetectorLength
|
||||
if not self.blocking:
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
def setBlockingCallback(self, blocking, callback=None):
|
||||
self.blocking = blocking
|
||||
if not self.blocking:
|
||||
state = super().startReceive()
|
||||
ASSERT(state)
|
||||
if callback != None:
|
||||
self._callbackFunction = callback
|
||||
super().setDio1Action(self._onIRQ)
|
||||
else:
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
else:
|
||||
state = super().standby()
|
||||
ASSERT(state)
|
||||
self._callbackFunction = self._dummyFunction
|
||||
super().clearDio1Action()
|
||||
return state
|
||||
|
||||
def recv(self, len=0, timeout_en=False, timeout_ms=0):
|
||||
if not self.blocking:
|
||||
return self._readData(len)
|
||||
else:
|
||||
return self._receive(len, timeout_en, timeout_ms)
|
||||
|
||||
def send(self, data):
|
||||
if not self.blocking:
|
||||
return self._startTransmit(data)
|
||||
else:
|
||||
return self._transmit(data)
|
||||
|
||||
def _events(self):
|
||||
return super().getIrqStatus()
|
||||
|
||||
def _receive(self, len_=0, timeout_en=False, timeout_ms=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = len_
|
||||
|
||||
if len_ == 0:
|
||||
length = SX126X_MAX_PACKET_LENGTH
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().receive(data_mv, length, timeout_en, timeout_ms)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
if len_ == 0:
|
||||
length = super().getPacketLength(False)
|
||||
data = data[:length]
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
return bytes(data), state
|
||||
|
||||
def _transmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
state = super().transmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _readData(self, len_=0):
|
||||
state = ERR_NONE
|
||||
|
||||
length = super().getPacketLength()
|
||||
|
||||
if len_ < length and len_ != 0:
|
||||
length = len_
|
||||
|
||||
data = bytearray(length)
|
||||
data_mv = memoryview(data)
|
||||
|
||||
try:
|
||||
state = super().readData(data_mv, length)
|
||||
except AssertionError as e:
|
||||
state = list(ERROR.keys())[list(ERROR.values()).index(str(e))]
|
||||
|
||||
ASSERT(super().startReceive())
|
||||
|
||||
if state == ERR_NONE or state == ERR_CRC_MISMATCH:
|
||||
return bytes(data), state
|
||||
|
||||
else:
|
||||
return b'', state
|
||||
|
||||
def _startTransmit(self, data):
|
||||
if isinstance(data, bytes) or isinstance(data, bytearray):
|
||||
pass
|
||||
else:
|
||||
return 0, ERR_INVALID_PACKET_TYPE
|
||||
|
||||
state = super().startTransmit(data, len(data))
|
||||
return len(data), state
|
||||
|
||||
def _dummyFunction(self, *args):
|
||||
pass
|
||||
|
||||
def _onIRQ(self, callback):
|
||||
events = self._events()
|
||||
if events & SX126X_IRQ_TX_DONE:
|
||||
super().startReceive()
|
||||
self._callbackFunction(events)
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user