decided the relay will be coded in python

This commit is contained in:
2026-03-04 16:31:57 +11:00
parent 98bb4fcc36
commit 166819acce
12 changed files with 2146 additions and 195 deletions

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"micropico.syncFolder": "relay"
}

View File

@@ -1,29 +0,0 @@
#pragma once
#include <stdint.h>
/*
This is the struct that gets packed and then sent over LoRa.
It's packed and uses stdint types because different hardware or compilers may attempt to
optimize it or change the size of different things, completely stuffing up and corrupting
our data. Endianess also matters.
Version 1:
Message Types:
- message: send a message via plain text to someone
- hello: announce yourself to other nodes, payload should include:
bytes 1-4: node id
byte 5: battery level or 255 for unkown
byte 6: name length
continuing bytes: name
*/
typedef struct {
uint8_t version; // version number to prevent breaking older packet formats
uint8_t ttl; // the number of hops left in the lifespan of the packet, prevents infinite hopping
uint8_t packetType; // packet type (message is the only type right now)
uint32_t senderId; // unique id of the person who sent the packet
uint32_t targetId; // 0xFFFFFFFF = broadcast
uint32_t messageId; // we can ignore packets if we've seen them twice
uint16_t payloadLength; // length of data
uint8_t payload[]; // actual data
} __attribute__((packed)) Packet;

1
relay/.gitignore vendored
View File

@@ -1 +0,0 @@
build

3
relay/.micropico Normal file
View File

@@ -0,0 +1,3 @@
{
"info": "This file is just used to identify a project folder."
}

View File

@@ -1,19 +0,0 @@
cmake_minimum_required(VERSION 4.2)
include(pico_sdk_import.cmake)
project(relay C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(PICO_EXAMPLES_PATH $(PROJECT_SOURCE_DIR))
pico_sdk_init()
add_executable(relay
main.c
)
target_link_libraries(relay pico_stdlib)
pico_add_extra_outputs(relay)

414
relay/_sx126x.py Normal file
View File

@@ -0,0 +1,414 @@
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'
}

View File

@@ -1,23 +0,0 @@
#include "../include/packet.h"
#include <stdio.h>
#include "pico/stdlib.h"
#define LED_PIN 25
int main() {
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
stdio_init_all();
while (true) {
printf("hello!!!\n");
gpio_put(LED_PIN, 1);
sleep_ms(2000);
gpio_put(LED_PIN, 0);
sleep_ms(2000);
}
}

32
relay/main.py Normal file
View File

@@ -0,0 +1,32 @@
from sx1262 import SX1262
from _sx126x import *
import time
def cb(events):
if events & SX1262.RX_DONE:
msg, err = sx.recv()
error = SX1262.STATUS[err]
print('Receive: {}, {}'.format(msg, error))
elif events & SX1262.TX_DONE:
print('TX done.')
def main():
print("Creating class...")
# initialize our radio, im using the HAT SX1262 hat for the pico
radio = SX1262(spi_bus=1, clk=10, mosi=11, miso=12, cs=3, irq=20, rst=15, gpio=2)
# start LoRa
print("Beginning LoRa...")
#radio.reset()
radio.begin(freq=915, bw=125, power=22)
radio.setBlockingCallback(False, cb)
while True:
print(f"Noise Floor: {radio.getRSSIInst()}")
time.sleep(0.5)
if __name__ == "__main__":
main()

View File

@@ -1,121 +0,0 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
# Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
#
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
# following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
# disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
endif ()
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
endif()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
)
if (NOT pico_sdk)
message("Downloading Raspberry Pi Pico SDK")
# GIT_SUBMODULES_RECURSE was added in 3.17
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
FetchContent_Populate(
pico_sdk
QUIET
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
GIT_SUBMODULES_RECURSE FALSE
SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src
BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build
SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild
)
else ()
FetchContent_Populate(
pico_sdk
QUIET
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
SOURCE_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-src
BINARY_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-build
SUBBUILD_DIR ${FETCHCONTENT_BASE_DIR}/pico_sdk-subbuild
)
endif ()
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

268
relay/sx1262.py Normal file
View File

@@ -0,0 +1,268 @@
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)

1421
relay/sx126x.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,14 +2,17 @@ from pyvis.network import Network
def main():
net = Network(notebook=False, cdn_resources="local", neighborhood_highlight=True, bgcolor="#222222", font_color="#FAFAFA", layout="hierarchical")
net = Network(notebook=False, cdn_resources="local", neighborhood_highlight=True, bgcolor="#222222", font_color="#FAFAFA", layout=True)
net.add_nodes([0,1,2,3,4], label=['1','2','3','4','5'],color=['#E0E0FF','#E0FFE0','#E0E0FF','#E0E0FF','#E0E0FF'])
net.add_nodes([0,1,2,3,4,5,6], label=['1','2','3','4','5','6','7'],color=['#E0E0FF','#E0FFE0','#E0E0FF','#E0E0FF','#E0E0FF','#E0E0FF','#E0FFE0'])
net.add_edge(0, 1, length=500)
net.add_edge(1, 2, length=750)
net.add_edge(2, 3, length=500)
net.add_edge(3, 4, length=250)
net.add_edge(2, 4, length=250)
net.add_edge(4, 5, length=750)
net.add_edge(5, 6, length=500)
net.add_edge(1, 6, length=0)
net.write_html("network.html", notebook=False)