Skip to content

Commit a985243

Browse files
committed
Python LoRaRF library first commit
0 parents  commit a985243

14 files changed

Lines changed: 1664 additions & 0 deletions

.gitignore

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
### Python ###
2+
# Byte-compiled / optimized / DLL files
3+
__pycache__/
4+
*.py[cod]
5+
*$py.class
6+
7+
# C extensions
8+
*.so
9+
10+
# Distribution / packaging
11+
.Python
12+
build/
13+
develop-eggs/
14+
dist/
15+
downloads/
16+
eggs/
17+
.eggs/
18+
lib/
19+
lib64/
20+
parts/
21+
sdist/
22+
var/
23+
wheels/
24+
pip-wheel-metadata/
25+
share/python-wheels/
26+
*.egg-info/
27+
.installed.cfg
28+
*.egg
29+
MANIFEST
30+
31+
# Python virtual environment
32+
pyvenv.cfg
33+
bin/
34+
include/
35+
36+
# PyInstaller
37+
# Usually these files are written by a python script from a template
38+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
39+
*.manifest
40+
*.spec
41+
42+
# Installer logs
43+
pip-log.txt
44+
pip-delete-this-directory.txt
45+
46+
### VisualStudioCode ###
47+
.vscode/*
48+
!.vscode/tasks.json
49+
!.vscode/launch.json
50+
*.code-workspace

LICENCE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2021 Chandra Wijaya Sentosa
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy
4+
of this software and associated documentation files (the "Software"), to deal
5+
in the Software without restriction, including without limitation the rights
6+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7+
copies of the Software, and to permit persons to whom the Software is
8+
furnished to do so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.

LoRaRF/LoRaIO.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import RPi.GPIO
2+
3+
DEF_GPIO = 0
4+
RPi_GPIO = 0
5+
BB_GPIO = 1
6+
7+
class LoRaIO :
8+
9+
GPIO = RPi.GPIO
10+
11+
def __init__(self, GPIO_lib = DEF_GPIO) :
12+
if GPIO_lib == RPi_GPIO :
13+
GPIO = RPi.GPIO
14+
GPIO.setmode(RPi.GPIO.BCM)
15+
GPIO.setwarnings(False)
16+
elif GPIO_lib == BB_GPIO :
17+
print("Board currently not supported")
18+
else :
19+
print("Board currently not supported")

LoRaRF/SX126x.py

Lines changed: 1008 additions & 0 deletions
Large diffs are not rendered by default.

LoRaRF/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# __init__.py
2+
from . import LoRaIO
3+
from .SX126x import SX126x

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# LoRa-RF Python
2+
3+
LoRa-RF Python is a library for basic transmitting and receiving data using LoRa modem. Support configuring frequency, modulation parameter, transmit power, receive gain and other RF parameters on both LoRa and FSK modulation. Also support handling transmit and receive using interrupt signal.
4+
The library works with various RF module with Semtech SX1261, SX1262, and SX1268 chip.

examples/SX126x_api_rx.py

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import os, sys
2+
currentdir = os.path.dirname(os.path.realpath(__file__))
3+
parentdir = os.path.dirname(currentdir)
4+
sys.path.append(parentdir)
5+
from LoRaRF import SX126x
6+
from LoRaRF import LoRaIO
7+
import time
8+
9+
busId = 1; csId = 0
10+
board = LoRaIO.RPi_GPIO; resetPin = 22; busyPin = 23; irqPin = 24; txenPin = 26; rxenPin = 25
11+
12+
LoRa = SX126x(busId, csId, LoRaIO.RPi_GPIO, resetPin, busyPin)
13+
GPIO = LoRaIO.LoRaIO(LoRaIO.DEF_GPIO).GPIO
14+
15+
# TCXO control setting
16+
dio3Voltage = LoRa.DIO3_OUTPUT_1_8
17+
tcxoDelay = LoRa.TCXO_DELAY_10
18+
# RF frequency setting
19+
rfFrequency = 915000000
20+
# RX gain setting
21+
gain = LoRa.RX_GAIN_POWER_SAVING
22+
# Define modulation parameters setting
23+
sf = LoRa.LORA_SF_7
24+
bw = LoRa.LORA_BW_125
25+
cr = LoRa.LORA_CR_4_5
26+
ldro = LoRa.LORA_LDRO_OFF
27+
# Define packet parameters setting
28+
preambleLength = 0x0C
29+
headerType = LoRa.LORA_HEADER_EXPLICIT
30+
payloadLength = 0x40
31+
crcType = LoRa.LORA_CRC_ON
32+
invertIq = LoRa.LORA_IQ_STANDARD
33+
# SyncWord setting
34+
sw = [0x34, 0x44]
35+
# Receive flag
36+
received = False
37+
intSet = False
38+
39+
def setting() :
40+
print("-- SETTING FUNCTION --")
41+
# SPI bus setting
42+
LoRa.setSpi(busId, csId)
43+
# GPIO Pins setting
44+
print("Setting pins")
45+
LoRa.setPins(LoRaIO.RPi_GPIO, resetPin, busyPin, irqPin, txenPin, rxenPin)
46+
# Reset RF module by setting resetPin to LOW and begin SPI communication
47+
LoRa.reset()
48+
# Optionally configure TCXO or XTAL used in RF module
49+
print("Set RF module to use TCXO as clock reference")
50+
LoRa._setDio3AsTcxoCtrl(dio3Voltage, tcxoDelay)
51+
# Set to standby mode and set packet type to LoRa
52+
print("Going to standby mode")
53+
LoRa._setStandby(LoRa.STANDBY_RC)
54+
print("Set packet type to LoRa")
55+
LoRa._setPacketType(LoRa.LORA_MODEM)
56+
# Set frequency to selected frequency (rfFrequency = rfFreq * 32000000 / 2 ^ 25)
57+
print(f"Set frequency to {rfFrequency/1000000} Mhz")
58+
rfFreq = int(rfFrequency * 33554432 / 32000000)
59+
LoRa._setRfFrequency(rfFreq)
60+
# Set rx gain to selected gain
61+
if gain == LoRa.RX_GAIN_BOOSTED : gainMsg = "boosted gain"
62+
else : gainMsg = "power saving gain"
63+
print(f"Set RX gain to {gainMsg} dBm")
64+
LoRa._writeRegister(LoRa.REG_RX_GAIN, [gain], 1)
65+
# Configure modulation parameter with predefined spreading factor, bandwidth, coding rate, and low data rate optimize setting
66+
print("Set modulation with predefined parameters")
67+
LoRa._setModulationParamsLoRa(sf, bw, cr, ldro)
68+
# Configure packet parameter with predefined preamble length, header mode type, payload length, crc type, and invert iq option
69+
LoRa._setPacketParamsLoRa(preambleLength, headerType, payloadLength, crcType, invertIq)
70+
# Set predefined syncronize word
71+
print("Set syncWord to 0x{0:02X}{1:02X}".format(sw[0], sw[1]))
72+
LoRa._writeRegister(LoRa.REG_LORA_SYNC_WORD_MSB, sw, 2)
73+
74+
def checkReceiveDone(channel) :
75+
global received
76+
received = True
77+
78+
def receive(message, timeout) :
79+
print("\n-- RECEIVE FUNCTION --")
80+
# Activate interrupt when receive done on DIO1
81+
print("Set RX done, timeout, and CRC error IRQ on DIO1")
82+
mask = LoRa.IRQ_RX_DONE | LoRa.IRQ_TIMEOUT | LoRa.IRQ_CRC_ERR
83+
LoRa._setDioIrqParams(mask, mask, LoRa.IRQ_NONE, LoRa.IRQ_NONE)
84+
# Calculate timeout (timeout duration = timeout * 15.625 us)
85+
tOut = timeout * 64
86+
# Set RF module to RX mode to receive message
87+
print("Receiving LoRa packet within predefined timeout")
88+
LoRa._setRx(tOut)
89+
# Attach irqPin to DIO1
90+
print(f"Attach interrupt on pin {irqPin} (irqPin)")
91+
global intSet
92+
if not intSet :
93+
GPIO.setup(irqPin, GPIO.IN)
94+
GPIO.add_event_detect(irqPin, GPIO.RISING, callback=checkReceiveDone, bouncetime=100)
95+
intSet = True
96+
# Set rxen and txen pin state for receiving packet
97+
GPIO.output(rxenPin, GPIO.HIGH)
98+
GPIO.output(txenPin, GPIO.LOW)
99+
# Wait for RX done interrupt
100+
print("Wait for RX done interrupt")
101+
global received
102+
while not received : pass
103+
# Clear transmit interrupt flag
104+
received = False
105+
# Clear the interrupt status
106+
irqStat = []
107+
LoRa._getIrqStatus(irqStat)
108+
print("Clear IRQ status")
109+
LoRa._clearIrqStatus(irqStat[0])
110+
GPIO.output(rxenPin, GPIO.LOW)
111+
# Exit function if timeout reached
112+
if irqStat[0] & LoRa.IRQ_TIMEOUT :
113+
return irqStat[0]
114+
print("Packet received!")
115+
# Get last received length and buffer base address
116+
print("Get received length and buffer base address")
117+
payloadLengthRx = []; rxStartBufferPointer = []
118+
LoRa._getRxBufferStatus(payloadLengthRx, rxStartBufferPointer)
119+
# Get and display packet status
120+
print("Get received packet status")
121+
rssiPkt = []; snrPkt = []; signalRssiPkt = []
122+
LoRa._getPacketStatus(rssiPkt, snrPkt, signalRssiPkt)
123+
rssi = rssiPkt[0] / -2
124+
snr = snrPkt[0] / 4
125+
signalRssi = signalRssiPkt[0] / -2
126+
print(f"Packet status: RSSI = {rssi} | SNR = {snr} | signalRSSI = {signalRssi}")
127+
# Read message from buffer
128+
print("Read message from buffer")
129+
LoRa._readBuffer(rxStartBufferPointer[0], message, payloadLengthRx[0])
130+
# Return interrupt status
131+
return irqStat[0]
132+
133+
# Seetings for LoRa communication
134+
setting()
135+
136+
while True :
137+
138+
# Receive message
139+
messageList = []
140+
timeout = 5000
141+
status = receive(messageList, timeout)
142+
message = ""
143+
for i in range(len(messageList)) : message += chr(messageList[i])
144+
# Display status if error happen
145+
if status & LoRa.IRQ_RX_DONE :
146+
print(f"Message: \'{message}\'")
147+
elif status & LoRa.IRQ_TIMEOUT :
148+
print("Receive timeout")
149+
elif status & LoRa.IRQ_CRC_ERR :
150+
print("CRC error")

0 commit comments

Comments
 (0)