Skip to content

Commit 7df2c3f

Browse files
committed
added support for SX1276 LoRa module
issue fossasia#62
1 parent 2c41fe7 commit 7df2c3f

File tree

2 files changed

+303
-4
lines changed

2 files changed

+303
-4
lines changed

PSL/SENSORS/Sx1276.py

Lines changed: 296 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,296 @@
1+
# This library allows P2P connections for LoRa modules that are built with the SX1276 chip from Semtech
2+
# It does not implement the LoRaWAN stack, and is only meant for standalone long range communications
3+
# Register definitions adapted from sample code for SEMTECH SX1276
4+
import time
5+
6+
def connect(SPI):
7+
return SX1276(SPI)
8+
9+
10+
class SX1276():
11+
name = 'SX1276'
12+
#********************LoRA mode***************************/
13+
LR_RegFifo = 0x00
14+
#Common settings
15+
LR_RegOpMode = 0x01
16+
LR_RegFrMsb = 0x06
17+
LR_RegFrMid = 0x07
18+
LR_RegFrLsb = 0x08
19+
#Tx settings
20+
LR_RegPaConfig = 0x09
21+
LR_RegPaRamp = 0x0A
22+
LR_RegOcp = 0x0B
23+
#Rx settings
24+
LR_RegLna = 0x0C
25+
#LoRa registers
26+
LR_RegFifoAddrPtr = 0x0D
27+
LR_RegFifoTxBaseAddr = 0x0E
28+
LR_RegFifoRxBaseAddr = 0x0F
29+
LR_RegFifoRxCurrentaddr = 0x10
30+
LR_RegIrqFlagsMask = 0x11
31+
LR_RegIrqFlags = 0x12
32+
LR_RegRxNbBytes = 0x13
33+
LR_RegRxHeaderCntValueMsb = 0x14
34+
LR_RegRxHeaderCntValueLsb = 0x15
35+
LR_RegRxPacketCntValueMsb = 0x16
36+
LR_RegRxPacketCntValueLsb = 0x17
37+
LR_RegModemStat = 0x18
38+
LR_RegPktSnrValue = 0x19
39+
LR_RegPktRssiValue = 0x1A
40+
LR_RegRssiValue = 0x1B
41+
LR_RegHopChannel = 0x1C
42+
LR_RegModemConfig1 = 0x1D
43+
LR_RegModemConfig2 = 0x1E
44+
LR_RegSymbTimeoutLsb = 0x1F
45+
LR_RegPreambleMsb = 0x20
46+
LR_RegPreambleLsb = 0x21
47+
LR_RegPayloadLength = 0x22
48+
LR_RegMaxPayloadLength = 0x23
49+
LR_RegHopPeriod = 0x24
50+
LR_RegFifoRxByteAddr = 0x25
51+
52+
#I/O settings
53+
REG_LR_DIOMAPPING1 = 0x40
54+
REG_LR_DIOMAPPING2 = 0x41
55+
#Version
56+
REG_LR_VERSION = 0x42
57+
#Additional settings
58+
REG_LR_PLLHOP = 0x44
59+
REG_LR_TCXO = 0x4B
60+
REG_LR_PADAC = 0x4D
61+
REG_LR_FORMERTEMP = 0x5B
62+
63+
REG_LR_AGCREF = 0x61
64+
REG_LR_AGCTHRESH1 = 0x62
65+
REG_LR_AGCTHRESH2 = 0x63
66+
REG_LR_AGCTHRESH3 = 0x64
67+
68+
#/********************FSK/ook mode***************************/
69+
RegFIFO = 0x00 #FIFO
70+
RegOpMode = 0x01 #Operation mode
71+
RegBitRateMsb = 0x02 #BR MSB
72+
RegBitRateLsb = 0x03 #BR LSB
73+
RegFdevMsb = 0x04 #FD MSB
74+
RegFdevLsb = 0x05 #FD LSB
75+
RegFreqMsb = 0x06 #Freq MSB
76+
RegFreqMid = 0x07 #Freq Middle byte
77+
RegFreqLsb = 0x08 #Freq LSB
78+
RegPaConfig = 0x09
79+
RegPaRamp = 0x0a
80+
RegOcp = 0x0b
81+
RegLna = 0x0c
82+
RegRxConfig = 0x0d
83+
RegRssiConfig = 0x0e
84+
RegRssiCollision = 0x0f
85+
RegRssiThresh = 0x10
86+
RegRssiValue = 0x11
87+
RegRxBw = 0x12
88+
RegAfcBw = 0x13
89+
RegOokPeak = 0x14
90+
RegOokFix = 0x15
91+
RegOokAvg = 0x16
92+
93+
RegAfcFei = 0x1a
94+
RegAfcMsb = 0x1b
95+
RegAfcLsb = 0x1c
96+
RegFeiMsb = 0x1d
97+
RegFeiLsb = 0x1e
98+
RegPreambleDetect = 0x1f
99+
RegRxTimeout1 = 0x20
100+
RegRxTimeout2 = 0x21
101+
RegRxTimeout3 = 0x22
102+
RegRxDelay = 0x23
103+
RegOsc = 0x24 #Set OSC
104+
RegPreambleMsb = 0x25
105+
RegPreambleLsb = 0x26
106+
RegSyncConfig = 0x27
107+
RegSyncValue1 = 0x28
108+
RegSyncValue2 = 0x29
109+
RegSyncValue3 = 0x2a
110+
RegSyncValue4 = 0x2b
111+
RegSyncValue5 = 0x2c
112+
RegSyncValue6 = 0x2d
113+
RegSyncValue7 = 0x2e
114+
RegSyncValue8 = 0x2f
115+
RegPacketConfig1 = 0x30
116+
RegPacketConfig2 = 0x31
117+
RegPayloadLength = 0x32
118+
RegNodeAdrs = 0x33
119+
RegBroadcastAdrs = 0x34
120+
RegFifoThresh = 0x35
121+
RegSeqConfig1 = 0x36
122+
RegSeqConfig2 = 0x37
123+
RegTimerResol = 0x38
124+
RegTimer1Coef = 0x39
125+
RegTimer2Coef = 0x3a
126+
RegImageCal = 0x3b
127+
RegTemp = 0x3c
128+
RegLowBat = 0x3d
129+
RegIrqFlags1 = 0x3e
130+
RegIrqFlags2 = 0x3f
131+
RegDioMapping1 = 0x40
132+
RegDioMapping2 = 0x41
133+
RegVersion = 0x42
134+
135+
RegPllHop = 0x44
136+
RegPaDac = 0x4d
137+
RegBitRateFrac = 0x5d
138+
139+
CR_SETTINGS = {'4_5': 0x01,'4_6': 0x02,'4_7': 0x03,'4_8': 0x04}
140+
sx1276_7_8FreqTbl = [[0x6C,0x80,0x00]] #434MHz
141+
sx1276_7_8PowerTbl = [0xFF,0xFC,0xF9,0xF6] #20dbm,17dbm,14dbm,11dbm
142+
sx1276_7_8SpreadFactorTbl = [6,7,8,9,10,11,12]
143+
144+
#7.8KHz,10.4KHz,15.6KHz,20.8KHz,31.2KHz,41.7KHz,62.5KHz,125KHz,250KHz,500KHz
145+
sx1276_7_8LoRaBwTbl = [0,1,2,3,4,5,6,7,8,9]
146+
sampleData = [ord(a) for a in "Mark1 Lora sx1276_7_8"]
147+
148+
mode = 0x01 #lora mode
149+
Freq_Sel = 0x00 #433M
150+
Power_Sel = 0x00
151+
Lora_Rate_Sel = 0x06
152+
BandWide_Sel = 0x07
153+
Fsk_Rate_Sel = 0x00
154+
155+
def __init__(self,SPI,**args):
156+
self.SPI = SPI
157+
self.SPI.set_parameters(2,6,1,0)
158+
self.CR = self.CR_SETTINGS['4_5']
159+
self.CRC = 1
160+
self.name = 'SX1276'
161+
162+
self.config()
163+
self.LoRaEntryRX();
164+
165+
166+
def standby(self):
167+
self.SPIWrite(self.LR_RegOpMode,[0x09]) #Low freq mode
168+
#self.SPIWrite(self.LR_RegOpMode,[0x01]) #High freq mode
169+
170+
def sleep(self):
171+
self.SPIWrite(self.LR_RegOpMode,[0x08])
172+
173+
def EntryLoRa(self):
174+
self.SPIWrite(self.LR_RegOpMode,[0x88]) #Low freq mode
175+
#self.SPIWrite(self.LR_RegOpMode,[0x80]) #High freq mode
176+
177+
def LoRaClearIRQ(self):
178+
self.SPIWrite(self.LR_RegIrqFlags,[0xFF])
179+
180+
def LoRaEntryRX(self):
181+
self.config() #setting base parameter
182+
self.SPIWrite(self.REG_LR_PADAC,[0x84]) #Normal and Rx
183+
self.SPIWrite(self.LR_RegHopPeriod,[0xFF]) #RegHopPeriod NO FHSS
184+
self.SPIWrite(self.REG_LR_DIOMAPPING1,[0x01]) #DIO0=00, DIO1=00, DIO2=00, DIO3=01
185+
186+
self.SPIWrite(self.LR_RegIrqFlagsMask,[0x3F]) #Open RxDone interrupt & Timeout
187+
self.LoRaClearIRQ()
188+
189+
self.SPIWrite(self.RegPayloadLength,[21]) #RegPayloadLength 21byte(this register must difine when the data long of one byte in SF is 6)
190+
191+
addr = self.SPIRead(self.LR_RegFifoRxBaseAddr,1)[0] #Read RxBaseAddr
192+
print ('rx address',addr, self.SPIRead(self.LR_RegFifoRxCurrentaddr,1)[0])
193+
self.SPIWrite(self.LR_RegFifoAddrPtr,[addr]) #RxBaseAddr -> FiFoAddrPtr
194+
self.SPIWrite(self.LR_RegOpMode,[0x8D]) #Continuous Rx Mode//Low Frequency Mode
195+
#self.SPIWrite(self.LR_RegOpMode,[0x05]) #High freq mode
196+
197+
while 1:
198+
if self.SPIRead(self.LR_RegModemStat,1)[0]&0x04 == 0x04: #Rx-on going RegModemStat
199+
print ('done')
200+
break
201+
print ('waiting :',time.ctime(),self.SPIRead(self.LR_RegModemStat,1))
202+
203+
def LoRaReadRSSI(self):
204+
tmp = self.SPIRead(self.LR_RegRssiValue,1)[0]
205+
tmp = tmp+127-137 #127:Max RSSI, 137:RSSI offset
206+
return tmp
207+
208+
def LoRaRxPacket(self):
209+
#if get_state('ID1'): #IRQ is high
210+
time.sleep(0.01)
211+
addr = self.SPIRead(self.LR_RegFifoRxCurrentaddr,1)[0] #last packet addr
212+
self.SPIWrite(self.LR_RegFifoAddrPtr,[addr])
213+
if self.sx1276_7_8SpreadFactorTbl[self.Lora_Rate_Sel] == 6: #Spread Factor = 6
214+
packet_size = 21
215+
else:
216+
packet_size = self.SPIRead(self.LR_RegRxNbBytes,1)[0]
217+
RxData = self.SPIRead(0x00,packet_size)
218+
self.LoRaClearIRQ()
219+
return RxData
220+
221+
def LoRaEntryTX(self):
222+
length = 21
223+
self.config() #setting base parameter
224+
self.SPIWrite(self.REG_LR_PADAC,[0x87]) #Tx at 20dbm
225+
self.SPIWrite(self.LR_RegHopPeriod,[0x00]) #RegHopPeriod NO FHSS
226+
self.SPIWrite(self.REG_LR_DIOMAPPING1,[0x41]) #DIO0=01, DIO1=00, DIO2=00, DIO3=01
227+
228+
self.LoRaClearIRQ()
229+
self.SPIWrite(self.LR_RegIrqFlagsMask,[0xF7]) #Open TxDone interrupt
230+
self.SPIWrite(self.RegPayloadLength,[length]) #RegPayloadLength 21byte
231+
232+
addr = self.SPIRead(self.LR_RegFifoTxBaseAddr,1)[0] #Read TxBaseAddr
233+
print ('tx address',addr)
234+
self.SPIWrite(self.LR_RegFifoAddrPtr,[addr]) #TxBaseAddr -> FiFoAddrPtr
235+
236+
while 1:
237+
if self.SPIRead(self.LR_RegPayloadLength,1)[0] == length: #Rx-on going RegModemStat
238+
print ('done')
239+
break
240+
print ('waiting :',time.ctime(),self.SPIRead(self.LR_RegPayloadLength,1))
241+
time.sleep(0.1)
242+
243+
def LoRaTxPacket(self,dataArray):
244+
self.SPIWrite(0x00,dataArray)
245+
self.SPIWrite(self.LR_RegOpMode,[0x8B]) #TX Mode
246+
#while not self.get_state('ID1'):
247+
time.sleep(0.1)
248+
self.SPIRead(self.LR_RegIrqFlags,1)
249+
self.LoRaClearIRQ()
250+
self.standby()
251+
print (len(lora.sampleData),lora.sampleData)
252+
253+
def ReadRSSI(self):
254+
tmp = self.SPIRead(self.LR_RegIrqFlagsMask,1)[0]
255+
tmp >>=1
256+
return 127-tmp
257+
258+
def config(self):
259+
self.sleep()
260+
time.sleep(0.015)
261+
self.EntryLoRa()
262+
self.SPIWrite(self.LR_RegFrMsb,self.sx1276_7_8FreqTbl[self.Freq_Sel])
263+
self.SPIWrite(self.LR_RegPaConfig,[self.sx1276_7_8PowerTbl[self.Power_Sel]])
264+
265+
self.SPIWrite(self.LR_RegOcp,[0x0B]) #Close ocp
266+
self.SPIWrite(self.LR_RegLna,[0x23]) #RegLNA , HIGH, LNA enable
267+
268+
if self.sx1276_7_8SpreadFactorTbl[self.Lora_Rate_Sel]==6:
269+
self.SPIWrite(self.LR_RegModemConfig1,[(self.sx1276_7_8LoRaBwTbl[self.BandWide_Sel]<<4)+(self.CR<<1)+0x01]) # Enable CRC Enable(0x02) & Error Coding rate 4/5(0x01), 4/6(0x02), 4/7
270+
self.SPIWrite(self.LR_RegModemConfig2,[(self.sx1276_7_8SpreadFactorTbl[self.Lora_Rate_Sel]<<4)+(self.CRC<<2)+0x03]) # SFactor & LNA gain set by the internal AGC loop
271+
tmp = self.SPIRead(0x31)[0]
272+
tmp&=0xF8;tmp|=0x05
273+
self.SPIWrite(0x31,[tmp])
274+
self.SPIWrite(0x37,[0x0C])
275+
else:
276+
self.SPIWrite(self.LR_RegModemConfig1,[(self.sx1276_7_8LoRaBwTbl[self.BandWide_Sel]<<4)+(self.CR<<1)+0x00])
277+
self.SPIWrite(self.LR_RegModemConfig2,[(self.sx1276_7_8SpreadFactorTbl[self.Lora_Rate_Sel]<<4)+(self.CRC<<2)+0x03])
278+
279+
self.SPIWrite(self.LR_RegSymbTimeoutLsb,[0xFF]) #Max timeout
280+
self.SPIWrite(self.LR_RegPreambleMsb,[0x00])
281+
self.SPIWrite(self.LR_RegPreambleLsb,[12]) #RegPreambleLsb 8+4=12byte Preamble
282+
283+
self.SPIWrite(self.REG_LR_DIOMAPPING2,[0x01]) #RegDioMapping2 DIO5=00, DIO4=01
284+
self.standby()
285+
286+
def SPIWrite(self,adr,byteArray):
287+
return self.SPI.xfer('CS1',[0x80|adr]+byteArray)[1:]
288+
289+
def SPIRead(self,adr,total_bytes):
290+
return self.SPI.xfer('CS1',[adr]+[0]*total_bytes)[1:]
291+
292+
def getRaw(self):
293+
val = self.SPIRead(0x02,1)
294+
return val
295+
296+

PSL/sciencelab.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4143,12 +4143,15 @@ def raiseException(self, ex, msg):
41434143

41444144

41454145
if __name__ == "__main__":
4146-
print("""this is not an executable file
4146+
print("""this is not an executable file
41474147
from PSL import sciencelab
41484148
I=sciencelab.connect()
41494149
eg.
41504150
I.get_average_voltage('CH1')
41514151
""")
4152-
# I=connect(verbose = True)
4153-
# for a in range(20):print (I.get_capacitance())
4154-
# I=connect(verbose=True,load_calibration=False)
4152+
I=connect(verbose = True)
4153+
t = time.time()
4154+
for a in range(100):
4155+
s = I.read_flash(3,a)
4156+
#print(s.replace('\n','.'),len(s))
4157+
print (time.time()-t)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy